Merge branch 'dev' of https://github.com/nightscout/AndroidAPS into dev
This commit is contained in:
commit
5c910306c6
8
.github/dependabot.yml
vendored
Normal file
8
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gradle
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: dev
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,6 +2,7 @@
|
|||
.gradle
|
||||
/local.properties
|
||||
.DS_Store
|
||||
app/jacoco.exec
|
||||
/build
|
||||
/captures
|
||||
*.apk
|
||||
|
|
|
@ -36,7 +36,7 @@ Translations
|
|||
------------
|
||||
|
||||
* If possible, always use Android translation mechanism (with strings.xml and @strings/id) instead of hardcoded texts
|
||||
* Provide only English strings - all other languages will be crowd translated via Crowdn https://translations.androidaps.org/
|
||||
* Provide only English strings - all other languages will be crowd translated via Crowdin (https://crowdin.com/project/androidaps and https://crowdin.com/project/androidapsdocs)
|
||||
|
||||
Hints
|
||||
-----
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url "https://plugins.gradle.org/m2/" } // jacoco 0.2
|
||||
}
|
||||
|
||||
|
@ -11,7 +10,6 @@ buildscript {
|
|||
}
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
//apply plugin: 'jacoco-android'
|
||||
|
@ -23,7 +21,6 @@ jacoco {
|
|||
}
|
||||
|
||||
repositories {
|
||||
jcenter { url "https://jcenter.bintray.com/" }
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ def gitAvailable = { ->
|
|||
|
||||
}
|
||||
|
||||
def allCommited = { ->
|
||||
def allCommitted = { ->
|
||||
StringBuilder stringBuilder = new StringBuilder()
|
||||
try {
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
|
@ -116,15 +113,16 @@ android {
|
|||
ndkVersion "21.1.6352462"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 24
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 28
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "2.7.2-dev"
|
||||
version "2.8.2.1-dev-a"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
|
||||
buildConfigField "String", "COMMITTED", '"' + allCommitted() + '"'
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
// if you change minSdkVersion to less than 11, you need to change executeTask for wear
|
||||
|
||||
|
@ -156,8 +154,8 @@ android {
|
|||
ext.enableCrashlytics = false
|
||||
}
|
||||
}
|
||||
flavorDimensions "standard"
|
||||
productFlavors {
|
||||
flavorDimensions "standard"
|
||||
full {
|
||||
applicationId "info.nightscout.androidaps"
|
||||
dimension "standard"
|
||||
|
@ -218,9 +216,6 @@ android {
|
|||
|
||||
useLibrary "org.apache.http.legacy"
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
@ -235,34 +230,34 @@ dependencies {
|
|||
wearApp project(':wear')
|
||||
|
||||
implementation project(':core')
|
||||
implementation project(':database')
|
||||
implementation project(':dana')
|
||||
implementation project(':danars')
|
||||
implementation project(':danar')
|
||||
implementation project(':rileylink')
|
||||
implementation project(':medtronic')
|
||||
implementation project(':omnipod')
|
||||
implementation project(':omnipod-eros')
|
||||
implementation project(':omnipod-dash')
|
||||
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
|
||||
testImplementation "junit:junit:$junit_version"
|
||||
testImplementation 'org.json:json:20200518'
|
||||
testImplementation 'org.json:json:20201115'
|
||||
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
|
||||
testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
|
||||
testImplementation 'joda-time:joda-time:2.10.6'
|
||||
testImplementation('com.google.truth:truth:1.0.1') {
|
||||
testImplementation "joda-time:joda-time:$jodatime_version"
|
||||
testImplementation('com.google.truth:truth:1.1.2') {
|
||||
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"
|
||||
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0-alpha04'
|
||||
androidTestImplementation "androidx.test.ext:junit:$androidx_junit"
|
||||
androidTestImplementation "androidx.test:rules:$androidx_rules"
|
||||
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
|
||||
/* Dagger2 - We are going to use dagger.android which includes
|
||||
* support for Activity and fragment injection so we need to include
|
||||
|
@ -314,12 +309,12 @@ tasks.whenTaskAdded { task ->
|
|||
printf('--------------\n')
|
||||
printf('isMaster: %s\n', isMaster().toString())
|
||||
printf('gitAvailable: %s\n', gitAvailable().toString())
|
||||
printf('allCommited: %s\n', allCommited().toString())
|
||||
printf('allCommitted: %s\n', allCommitted().toString())
|
||||
printf('--------------\n')
|
||||
if (isMaster() && !gitAvailable()) {
|
||||
throw new GradleException('GIT system is not available. On Windows try to run Android Studio as an Administrator. Check if GIT is installed and Studio have permissions to use it')
|
||||
}
|
||||
if (isMaster() && !allCommited()) {
|
||||
if (isMaster() && !allCommitted()) {
|
||||
throw new GradleException('There are uncommitted changes. Clone sources again as described in wiki and do not allow gradle update')
|
||||
}
|
||||
|
||||
|
|
BIN
app/libs/wearpreferenceactivity-0.5.0.aar
Normal file
BIN
app/libs/wearpreferenceactivity-0.5.0.aar
Normal file
Binary file not shown.
|
@ -135,10 +135,6 @@
|
|||
android:resource="@xml/filepaths" />
|
||||
</provider>
|
||||
|
||||
<!-- Service processing incomming data -->
|
||||
<service
|
||||
android:name=".services.DataService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".services.LocationService"
|
||||
android:exported="false" />
|
||||
|
|
|
@ -151,7 +151,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
}
|
||||
}
|
||||
//cherry pick from oref upstream dev cb8e94990301277fb1016c778b4e9efa55a6edbc
|
||||
if (bg <= 10 || bg === 38 || noise >= 3 || minAgo > 12 || minAgo < -5 || ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) ) {
|
||||
if (bg <= 10 || bg === 38 || noise >= 3 || minAgo > 12 || minAgo < -5 || ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) && !isSaveCgmSource ) {
|
||||
if (currenttemp.rate > basal) { // high temp is running
|
||||
rT.reason += ". Replacing high temp basal of "+currenttemp.rate+" with neutral temp of "+basal;
|
||||
rT.deliverAt = deliverAt;
|
||||
|
|
|
@ -2,5 +2,9 @@
|
|||
51:6D:12:67:4C:27:F4:9B:9F:E5:42:9B:01:B3:98:E4:66:2B:85:B7:A8:DD:70:32:B7:6A:D7:97:9A:0D:97:10
|
||||
#Leaked
|
||||
55:5D:70:C9:BE:10:41:7E:4B:01:A9:C4:C6:44:4A:F8:69:71:35:25:ED:95:23:16:C7:15:E8:EB:C6:08:FC:B1
|
||||
# àqΣnΖ`ZϼγwÛ/τàΒϳ9Φ'$ΑϵžλUΛ`ÆÌΣЃA
|
||||
E0:71:A3:6E:96:60:5A:FC:B3:77:DB:2F:C4:E0:92:F3:39:A6:27:24:91:F5:7E:BB:55:9B:60:C6:CC:A3:03:41
|
||||
# 2ΙšÄΠΒϨÒÇeЄtЄЗž-*Ж*ZcHijЊÄœ<|x"Ε
|
||||
32:99:61:C4:A0:92:E8:D2:C7:65:04:74:04:17:7E:2D:2A:16:2A:5A:63:48:69:6A:0A:C4:53:3C:7C:78:22:95
|
||||
# mςRr¡ЇζΛLφK&ĐΨ5CnЎϴPDñЍŒkϼ{ΨδwВb
|
||||
6D:C2:52:72:A1:07:B6:9B:4C:C6:4B:26:10:A8:35:43:6E:0E:F4:50:44:F1:0D:52:6B:FC:7B:A8:B4:77:12:62
|
|
@ -1,15 +1,21 @@
|
|||
package info.nightscout.androidaps
|
||||
|
||||
import android.os.Build
|
||||
import info.nightscout.androidaps.interfaces.ConfigInterface
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class Config @Inject constructor(): ConfigInterface{
|
||||
class Config @Inject constructor() : ConfigInterface {
|
||||
|
||||
override val SUPPORTEDNSVERSION = 1002 // 0.10.00
|
||||
override val APS = BuildConfig.FLAVOR == "full"
|
||||
override val NSCLIENT = BuildConfig.FLAVOR == "nsclient" || BuildConfig.FLAVOR == "nsclient2"
|
||||
override val PUMPCONTROL = BuildConfig.FLAVOR == "pumpcontrol"
|
||||
override val PUMPDRIVERS = BuildConfig.FLAVOR == "full" || BuildConfig.FLAVOR == "pumpcontrol"
|
||||
override val FLAVOR = BuildConfig.FLAVOR
|
||||
override val VERSION_NAME = BuildConfig.VERSION_NAME
|
||||
|
||||
override val currentDeviceModelString =
|
||||
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
|
||||
}
|
|
@ -2,7 +2,6 @@ package info.nightscout.androidaps
|
|||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.os.PersistableBundle
|
||||
|
@ -22,9 +21,9 @@ import android.widget.TextView
|
|||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.joanzapata.iconify.Iconify
|
||||
import com.joanzapata.iconify.fonts.FontAwesomeModule
|
||||
import dev.doubledot.doki.ui.DokiActivity
|
||||
|
@ -33,6 +32,7 @@ import info.nightscout.androidaps.activities.PreferencesActivity
|
|||
import info.nightscout.androidaps.activities.ProfileHelperActivity
|
||||
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
||||
import info.nightscout.androidaps.activities.StatsActivity
|
||||
import info.nightscout.androidaps.databinding.ActivityMainBinding
|
||||
import info.nightscout.androidaps.events.EventAppExit
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||
|
@ -46,8 +46,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
|||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
||||
|
@ -59,13 +57,11 @@ import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
|
|||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||
import info.nightscout.androidaps.utils.resources.IconsProvider
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import info.nightscout.androidaps.utils.tabs.TabPageAdapter
|
||||
import info.nightscout.androidaps.utils.ui.UIRunnable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.system.exitProcess
|
||||
|
@ -75,10 +71,10 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
private val disposable = CompositeDisposable()
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var androidPermission: AndroidPermission
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
|
||||
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
||||
@Inject lateinit var loopPlugin: LoopPlugin
|
||||
|
@ -91,40 +87,36 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin
|
||||
@Inject lateinit var config: Config
|
||||
@Inject lateinit var importExportPrefs: ImportExportPrefs
|
||||
|
||||
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
||||
private var pluginPreferencesMenuItem: MenuItem? = null
|
||||
private var menu: Menu? = null
|
||||
|
||||
val callForPrefFile = registerForActivityResult(PrefsFileContract()) {
|
||||
it?.let {
|
||||
importExportPrefs.importSharedPreferences(this, it)
|
||||
}
|
||||
}
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Iconify.with(FontAwesomeModule())
|
||||
LocaleHelper.update(applicationContext)
|
||||
setContentView(R.layout.activity_main)
|
||||
setSupportActionBar(toolbar)
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setHomeButtonEnabled(true)
|
||||
actionBarDrawerToggle = ActionBarDrawerToggle(this, main_drawer_layout, R.string.open_navigation, R.string.close_navigation).also {
|
||||
main_drawer_layout.addDrawerListener(it)
|
||||
actionBarDrawerToggle = ActionBarDrawerToggle(this, binding.mainDrawerLayout, R.string.open_navigation, R.string.close_navigation).also {
|
||||
binding.mainDrawerLayout.addDrawerListener(it)
|
||||
it.syncState()
|
||||
}
|
||||
|
||||
// initialize screen wake lock
|
||||
processPreferenceChange(EventPreferenceChange(resourceHelper.gs(R.string.key_keep_screen_on)))
|
||||
main_pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
binding.mainPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
override fun onPageSelected(position: Int) {
|
||||
setPluginPreferenceMenuName()
|
||||
checkPluginPreferences(main_pager)
|
||||
checkPluginPreferences(binding.mainPager)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -134,7 +126,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
setupViews()
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventRebuildTabs::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
if (it.recreate) recreate()
|
||||
else setupViews()
|
||||
|
@ -143,7 +135,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ processPreferenceChange(it) }, fabricPrivacy::logException)
|
||||
)
|
||||
if (!sp.getBoolean(R.string.key_setupwizard_processed, false) && !isRunningRealPumpTest()) {
|
||||
|
@ -195,69 +187,53 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
private fun setupViews() {
|
||||
// Menu
|
||||
val pageAdapter = TabPageAdapter(this)
|
||||
main_navigation_view.setNavigationItemSelectedListener { true }
|
||||
val menu = main_navigation_view.menu.also { it.clear() }
|
||||
binding.mainNavigationView.setNavigationItemSelectedListener { true }
|
||||
val menu = binding.mainNavigationView.menu.also { it.clear() }
|
||||
for (p in activePlugin.getPluginsList()) {
|
||||
pageAdapter.registerNewFragment(p)
|
||||
if (p.isEnabled() && p.hasFragment() && !p.isFragmentVisible() && !p.pluginDescription.neverVisible) {
|
||||
val menuItem = menu.add(p.name)
|
||||
menuItem.isCheckable = true
|
||||
if(p.menuIcon != -1) {
|
||||
if (p.menuIcon != -1) {
|
||||
menuItem.setIcon(p.menuIcon)
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
menuItem.setIcon(R.drawable.ic_settings)
|
||||
}
|
||||
menuItem.setOnMenuItemClickListener {
|
||||
val intent = Intent(this, SingleFragmentActivity::class.java)
|
||||
intent.putExtra("plugin", activePlugin.getPluginsList().indexOf(p))
|
||||
startActivity(intent)
|
||||
main_drawer_layout.closeDrawers()
|
||||
binding.mainDrawerLayout.closeDrawers()
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
main_pager.adapter = pageAdapter
|
||||
main_pager.offscreenPageLimit = 8 // This may cause more memory consumption
|
||||
checkPluginPreferences(main_pager)
|
||||
binding.mainPager.adapter = pageAdapter
|
||||
binding.mainPager.offscreenPageLimit = 8 // This may cause more memory consumption
|
||||
checkPluginPreferences(binding.mainPager)
|
||||
|
||||
// Tabs
|
||||
if (sp.getBoolean(R.string.key_short_tabtitles, false)) {
|
||||
tabs_normal.visibility = View.GONE
|
||||
tabs_compact.visibility = View.VISIBLE
|
||||
toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, resources.getDimension(R.dimen.compact_height).toInt())
|
||||
TabLayoutMediator(tabs_compact, main_pager) { tab, position ->
|
||||
tab.text = (main_pager.adapter as TabPageAdapter).getPluginAt(position).nameShort
|
||||
binding.tabsNormal.visibility = View.GONE
|
||||
binding.tabsCompact.visibility = View.VISIBLE
|
||||
binding.toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, resources.getDimension(R.dimen.compact_height).toInt())
|
||||
TabLayoutMediator(binding.tabsCompact, binding.mainPager) { tab, position ->
|
||||
tab.text = (binding.mainPager.adapter as TabPageAdapter).getPluginAt(position).nameShort
|
||||
}.attach()
|
||||
} else {
|
||||
tabs_normal.visibility = View.VISIBLE
|
||||
tabs_compact.visibility = View.GONE
|
||||
binding.tabsNormal.visibility = View.VISIBLE
|
||||
binding.tabsCompact.visibility = View.GONE
|
||||
val typedValue = TypedValue()
|
||||
if (theme.resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
|
||||
toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT,
|
||||
binding.toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT,
|
||||
TypedValue.complexToDimensionPixelSize(typedValue.data, resources.displayMetrics))
|
||||
}
|
||||
TabLayoutMediator(tabs_normal, main_pager) { tab, position ->
|
||||
tab.text = (main_pager.adapter as TabPageAdapter).getPluginAt(position).name
|
||||
TabLayoutMediator(binding.tabsNormal, binding.mainPager) { tab, position ->
|
||||
tab.text = (binding.mainPager.adapter as TabPageAdapter).getPluginAt(position).name
|
||||
}.attach()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (permissions.isNotEmpty()) {
|
||||
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
|
||||
when (requestCode) {
|
||||
AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted
|
||||
OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
|
||||
|
||||
AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY, AndroidPermission.CASE_PHONE_STATE, AndroidPermission.CASE_SYSTEM_WINDOW -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||
val v = currentFocus
|
||||
|
@ -275,16 +251,18 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun setPluginPreferenceMenuName() {
|
||||
val plugin = (main_pager.adapter as TabPageAdapter).getPluginAt(main_pager.currentItem)
|
||||
this.menu?.findItem(R.id.nav_plugin_preferences)?.title = resourceHelper.gs(R.string.nav_preferences_plugin, plugin.name)
|
||||
if (binding.mainPager.currentItem >= 0) {
|
||||
val plugin = (binding.mainPager.adapter as TabPageAdapter).getPluginAt(binding.mainPager.currentItem)
|
||||
this.menu?.findItem(R.id.nav_plugin_preferences)?.title = resourceHelper.gs(R.string.nav_preferences_plugin, plugin.name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
this.menu = menu
|
||||
this.menu = menu
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
|
||||
setPluginPreferenceMenuName()
|
||||
checkPluginPreferences(main_pager)
|
||||
checkPluginPreferences(binding.mainPager)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -316,6 +294,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n"
|
||||
message += "${resourceHelper.gs(R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.nightscoutVersionName}"
|
||||
if (buildHelper.isEngineeringMode()) message += "\n${resourceHelper.gs(R.string.engineering_mode_enabled)}"
|
||||
if (!fabricPrivacy.fabricEnabled()) message += "\n${resourceHelper.gs(R.string.fabric_upload_disabled)}"
|
||||
message += resourceHelper.gs(R.string.about_link_urls)
|
||||
val messageSpanned = SpannableString(message)
|
||||
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
|
||||
|
@ -341,7 +320,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
|
||||
R.id.nav_plugin_preferences -> {
|
||||
val plugin = (main_pager.adapter as TabPageAdapter).getPluginAt(main_pager.currentItem)
|
||||
val plugin = (binding.mainPager.adapter as TabPageAdapter).getPluginAt(binding.mainPager.currentItem)
|
||||
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, {
|
||||
val i = Intent(this, PreferencesActivity::class.java)
|
||||
i.putExtra("id", plugin.preferencesId)
|
||||
|
@ -396,6 +375,12 @@ class MainActivity : NoSplashAppCompatActivity() {
|
|||
fabricPrivacy.firebaseAnalytics.setUserProperty("Profile", activePlugin.activeProfileInterface.javaClass.simpleName)
|
||||
activePlugin.activeSensitivity.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Sensitivity", it::class.java.simpleName) }
|
||||
activePlugin.activeInsulin.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Insulin", it::class.java.simpleName) }
|
||||
// Add to crash log too
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("HEAD", BuildConfig.HEAD)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("Version", BuildConfig.VERSION)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("Remote", remote)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("Committed", BuildConfig.COMMITTED)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("Hash", hashes[0])
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package info.nightscout.androidaps;
|
|||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
|
@ -19,6 +18,9 @@ import javax.inject.Inject;
|
|||
|
||||
import dagger.android.AndroidInjector;
|
||||
import dagger.android.DaggerApplication;
|
||||
import info.nightscout.androidaps.database.AppRepository;
|
||||
import info.nightscout.androidaps.database.transactions.VersionChangeTransaction;
|
||||
import info.nightscout.androidaps.db.CompatDBHelper;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.StaticInjector;
|
||||
import info.nightscout.androidaps.dependencyInjection.DaggerAppComponent;
|
||||
|
@ -39,14 +41,14 @@ import info.nightscout.androidaps.services.Intents;
|
|||
import info.nightscout.androidaps.utils.ActivityMonitor;
|
||||
import info.nightscout.androidaps.utils.locale.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
||||
public class MainApp extends DaggerApplication {
|
||||
|
||||
static MainApp sInstance;
|
||||
private static Resources sResources;
|
||||
|
||||
static DatabaseHelper sDatabaseHelper = null;
|
||||
|
||||
private final CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
@Inject PluginStore pluginStore;
|
||||
@Inject AAPSLogger aapsLogger;
|
||||
@Inject ActivityMonitor activityMonitor;
|
||||
|
@ -58,6 +60,8 @@ public class MainApp extends DaggerApplication {
|
|||
@Inject ConfigBuilderPlugin configBuilderPlugin;
|
||||
@Inject KeepAliveReceiver.KeepAliveManager keepAliveManager;
|
||||
@Inject List<PluginBase> plugins;
|
||||
@Inject CompatDBHelper compatDBHelper;
|
||||
@Inject AppRepository repository;
|
||||
|
||||
@Inject StaticInjector staticInjector; // TODO avoid , here fake only to initialize
|
||||
|
||||
|
@ -66,10 +70,8 @@ public class MainApp extends DaggerApplication {
|
|||
super.onCreate();
|
||||
|
||||
aapsLogger.debug("onCreate");
|
||||
sInstance = this;
|
||||
sResources = getResources();
|
||||
LocaleHelper.INSTANCE.update(this);
|
||||
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
|
||||
sDatabaseHelper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
|
||||
/*
|
||||
Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
|
||||
if (ex instanceof InternalError) {
|
||||
|
@ -79,6 +81,15 @@ public class MainApp extends DaggerApplication {
|
|||
aapsLogger.error("Uncaught exception crashing app", ex);
|
||||
});
|
||||
*/
|
||||
String gitRemote = BuildConfig.REMOTE;
|
||||
String commitHash = BuildConfig.HEAD;
|
||||
if (gitRemote.contains("NoGitSystemAvailable")) {
|
||||
gitRemote = null;
|
||||
commitHash = null;
|
||||
}
|
||||
disposable.add(repository.runTransaction(new VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe());
|
||||
disposable.add(compatDBHelper.dbChangeDisposable());
|
||||
|
||||
registerActivityLifecycleCallbacks(activityMonitor);
|
||||
|
||||
JodaTimeAndroid.init(this);
|
||||
|
@ -121,7 +132,6 @@ public class MainApp extends DaggerApplication {
|
|||
.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void registerLocalBroadcastReceiver() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intents.ACTION_NEW_TREATMENT);
|
||||
|
|
|
@ -420,6 +420,6 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
|||
|
||||
fun setFilter(filter: String) {
|
||||
this.filter = filter
|
||||
updateFilterVisibility(filter, preferenceScreen)
|
||||
preferenceManager?.preferenceScreen?.let { updateFilterVisibility(filter, it) }
|
||||
}
|
||||
}
|
|
@ -7,23 +7,22 @@ import android.text.TextWatcher
|
|||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceScreen
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.ActivityPreferencesBinding
|
||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.activity_preferences.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
|
||||
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
private var preferenceId = 0
|
||||
private var myPreferenceFragment: MyPreferenceFragment? = null
|
||||
|
||||
var preferenceId = 0
|
||||
var myPreferenceFragment: MyPreferenceFragment? = null
|
||||
private lateinit var binding: ActivityPreferencesBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_preferences)
|
||||
binding = ActivityPreferencesBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
pref_filter.addTextChangedListener(object : TextWatcher {
|
||||
binding.prefFilter.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
filterPreferences()
|
||||
|
@ -37,23 +36,21 @@ class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompa
|
|||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
myPreferenceFragment = MyPreferenceFragment()
|
||||
preferenceId = intent.getIntExtra("id", -1)
|
||||
val args = Bundle()
|
||||
args.putInt("id", preferenceId)
|
||||
args.putString("filter", pref_filter.text.toString())
|
||||
myPreferenceFragment?.arguments = args
|
||||
supportFragmentManager.beginTransaction().replace(R.id.frame_layout, myPreferenceFragment!!).commit()
|
||||
myPreferenceFragment?.arguments = Bundle().also {
|
||||
it.putInt("id", preferenceId)
|
||||
it.putString("filter", binding.prefFilter.text.toString())
|
||||
}
|
||||
if (savedInstanceState == null)
|
||||
supportFragmentManager.beginTransaction().replace(R.id.frame_layout, myPreferenceFragment!!).commit()
|
||||
}
|
||||
|
||||
override fun onPreferenceStartScreen(caller: PreferenceFragmentCompat, pref: PreferenceScreen): Boolean {
|
||||
val fragment = MyPreferenceFragment()
|
||||
val args = Bundle()
|
||||
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.key)
|
||||
args.putInt("id", preferenceId)
|
||||
fragment.arguments = args
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.frame_layout, fragment, pref.key)
|
||||
.addToBackStack(pref.key)
|
||||
.commit()
|
||||
fragment.arguments = Bundle().also {
|
||||
it.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.key)
|
||||
it.putInt("id", preferenceId)
|
||||
}
|
||||
supportFragmentManager.beginTransaction().replace(R.id.frame_layout, fragment, pref.key).addToBackStack(pref.key).commit()
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -62,6 +59,6 @@ class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompa
|
|||
}
|
||||
|
||||
private fun filterPreferences() {
|
||||
myPreferenceFragment?.setFilter(pref_filter.text.toString())
|
||||
myPreferenceFragment?.setFilter(binding.prefFilter.text.toString())
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import info.nightscout.androidaps.R
|
|||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
|
||||
import info.nightscout.androidaps.data.defaultProfile.DefaultProfileDPV
|
||||
import info.nightscout.androidaps.databinding.ActivityProfilehelperBinding
|
||||
import info.nightscout.androidaps.db.ProfileSwitch
|
||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
|
@ -24,15 +25,13 @@ import info.nightscout.androidaps.utils.T
|
|||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
||||
import kotlinx.android.synthetic.main.activity_profilehelper.*
|
||||
import java.text.DecimalFormat
|
||||
import javax.inject.Inject
|
||||
|
||||
class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var tddCalculator: TddCalculator
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var defaultProfile: DefaultProfile
|
||||
|
@ -65,27 +64,31 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
private lateinit var profileSwitch: List<ProfileSwitch>
|
||||
private val profileSwitchUsed = arrayOf(0, 0)
|
||||
|
||||
private lateinit var binding: ActivityProfilehelperBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_profilehelper)
|
||||
|
||||
profilehelper_menu1.setOnClickListener {
|
||||
binding = ActivityProfilehelperBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
binding.menu1.setOnClickListener {
|
||||
switchTab(0, typeSelected[0])
|
||||
}
|
||||
profilehelper_menu2.setOnClickListener {
|
||||
binding.menu2.setOnClickListener {
|
||||
switchTab(1, typeSelected[1])
|
||||
}
|
||||
|
||||
profilehelper_profiletype.setOnClickListener {
|
||||
PopupMenu(this, profilehelper_profiletype).apply {
|
||||
binding.profiletype.setOnClickListener {
|
||||
PopupMenu(this, binding.profiletype).apply {
|
||||
menuInflater.inflate(R.menu.menu_profilehelper, menu)
|
||||
setOnMenuItemClickListener { item ->
|
||||
profilehelper_profiletype.setText(item.title)
|
||||
binding.profiletype.setText(item.title)
|
||||
when (item.itemId) {
|
||||
R.id.menu_default -> switchTab(tabSelected, ProfileType.MOTOL_DEFAULT)
|
||||
R.id.menu_default_dpv -> switchTab(tabSelected, ProfileType.DPV_DEFAULT)
|
||||
R.id.menu_current -> switchTab(tabSelected, ProfileType.CURRENT)
|
||||
R.id.menu_available -> switchTab(tabSelected, ProfileType.AVAILABLE_PROFILE)
|
||||
R.id.menu_default -> switchTab(tabSelected, ProfileType.MOTOL_DEFAULT)
|
||||
R.id.menu_default_dpv -> switchTab(tabSelected, ProfileType.DPV_DEFAULT)
|
||||
R.id.menu_current -> switchTab(tabSelected, ProfileType.CURRENT)
|
||||
R.id.menu_available -> switchTab(tabSelected, ProfileType.AVAILABLE_PROFILE)
|
||||
R.id.menu_profileswitch -> switchTab(tabSelected, ProfileType.PROFILE_SWITCH)
|
||||
}
|
||||
true
|
||||
|
@ -97,12 +100,12 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
// Active profile
|
||||
profileList = activePlugin.activeProfileInterface.profile?.getProfileList() ?: ArrayList()
|
||||
|
||||
profilehelper_available_profile_list.setOnClickListener {
|
||||
PopupMenu(this, profilehelper_available_profile_list).apply {
|
||||
binding.availableProfileList.setOnClickListener {
|
||||
PopupMenu(this, binding.availableProfileList).apply {
|
||||
var order = 0
|
||||
for (name in profileList) menu.add(Menu.NONE, order, order++, name)
|
||||
setOnMenuItemClickListener { item ->
|
||||
profilehelper_available_profile_list.setText(item.title)
|
||||
binding.availableProfileList.setText(item.title)
|
||||
profileUsed[tabSelected] = item.itemId
|
||||
true
|
||||
}
|
||||
|
@ -113,12 +116,12 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
// Profile switch
|
||||
profileSwitch = databaseHelper.getProfileSwitchData(dateUtil._now() - T.months(2).msecs(), true)
|
||||
|
||||
profilehelper_profileswitch_list.setOnClickListener {
|
||||
PopupMenu(this, profilehelper_profileswitch_list).apply {
|
||||
binding.profileswitchList.setOnClickListener {
|
||||
PopupMenu(this, binding.profileswitchList).apply {
|
||||
var order = 0
|
||||
for (name in profileSwitch) menu.add(Menu.NONE, order, order++, name.customizedName)
|
||||
setOnMenuItemClickListener { item ->
|
||||
profilehelper_profileswitch_list.setText(item.title)
|
||||
binding.profileswitchList.setText(item.title)
|
||||
profileSwitchUsed[tabSelected] = item.itemId
|
||||
true
|
||||
}
|
||||
|
@ -127,7 +130,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
|
||||
// Default profile
|
||||
profilehelper_copytolocalprofile.setOnClickListener {
|
||||
binding.copytolocalprofile.setOnClickListener {
|
||||
val age = ageUsed[tabSelected]
|
||||
val weight = weightUsed[tabSelected]
|
||||
val tdd = tddUsed[tabSelected]
|
||||
|
@ -142,31 +145,31 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
profilehelper_age.setParams(0.0, 1.0, 18.0, 1.0, DecimalFormat("0"), false, null)
|
||||
profilehelper_weight.setParams(0.0, 0.0, 150.0, 1.0, DecimalFormat("0"), false, null, object : TextWatcher {
|
||||
binding.age.setParams(0.0, 1.0, 18.0, 1.0, DecimalFormat("0"), false, null)
|
||||
binding.weight.setParams(0.0, 0.0, 150.0, 1.0, DecimalFormat("0"), false, null, 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) {
|
||||
profilehelper_tdd_row.visibility = (profilehelper_weight.value == 0.0).toVisibility()
|
||||
binding.tddRow.visibility = (binding.weight.value == 0.0).toVisibility()
|
||||
}
|
||||
})
|
||||
profilehelper_tdd.setParams(0.0, 0.0, 200.0, 1.0, DecimalFormat("0"), false, null, object : TextWatcher {
|
||||
binding.tdd.setParams(0.0, 0.0, 200.0, 1.0, DecimalFormat("0"), false, null, 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) {
|
||||
profilehelper_weight_row.visibility = (profilehelper_tdd.value == 0.0).toVisibility()
|
||||
binding.weightRow.visibility = (binding.tdd.value == 0.0).toVisibility()
|
||||
}
|
||||
})
|
||||
|
||||
profilehelper_basalpctfromtdd.setParams(32.0, 32.0, 37.0, 1.0, DecimalFormat("0"), false, null)
|
||||
binding.basalpctfromtdd.setParams(32.0, 32.0, 37.0, 1.0, DecimalFormat("0"), false, null)
|
||||
|
||||
profilehelper_tdds.text = tddCalculator.stats()
|
||||
binding.tdds.text = tddCalculator.stats()
|
||||
|
||||
// Current profile
|
||||
profilehelper_current_profile_text.text = profileFunction.getProfileName()
|
||||
binding.currentProfileText.text = profileFunction.getProfileName()
|
||||
|
||||
// General
|
||||
profilehelper_compareprofile.setOnClickListener {
|
||||
binding.compareprofile.setOnClickListener {
|
||||
storeValues()
|
||||
for (i in 0..1) {
|
||||
if (typeSelected[i] == ProfileType.MOTOL_DEFAULT) {
|
||||
|
@ -221,28 +224,32 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun getProfile(age: Double, tdd: Double, weight: Double, basalPct: Double, tab: Int): Profile? =
|
||||
when (typeSelected[tab]) {
|
||||
ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
|
||||
ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits())
|
||||
ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile()
|
||||
ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString())
|
||||
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile()
|
||||
try { // profile must not exist
|
||||
when (typeSelected[tab]) {
|
||||
ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
|
||||
ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits())
|
||||
ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile()
|
||||
ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString())
|
||||
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
private fun getProfileName(age: Double, tdd: Double, weight: Double, basalSumPct: Double, tab: Int): String =
|
||||
when (typeSelected[tab]) {
|
||||
ProfileType.MOTOL_DEFAULT -> if (tdd > 0) resourceHelper.gs(R.string.formatwithtdd, age, tdd) else resourceHelper.gs(R.string.formatwithweight, age, weight)
|
||||
ProfileType.DPV_DEFAULT -> resourceHelper.gs(R.string.formatwittddandpct, age, tdd, (basalSumPct * 100).toInt())
|
||||
ProfileType.CURRENT -> profileFunction.getProfileName()
|
||||
ProfileType.MOTOL_DEFAULT -> if (tdd > 0) resourceHelper.gs(R.string.formatwithtdd, age, tdd) else resourceHelper.gs(R.string.formatwithweight, age, weight)
|
||||
ProfileType.DPV_DEFAULT -> resourceHelper.gs(R.string.formatwittddandpct, age, tdd, (basalSumPct * 100).toInt())
|
||||
ProfileType.CURRENT -> profileFunction.getProfileName()
|
||||
ProfileType.AVAILABLE_PROFILE -> profileList[profileUsed[tab]].toString()
|
||||
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].customizedName
|
||||
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].customizedName
|
||||
}
|
||||
|
||||
private fun storeValues() {
|
||||
ageUsed[tabSelected] = profilehelper_age.value
|
||||
weightUsed[tabSelected] = profilehelper_weight.value
|
||||
tddUsed[tabSelected] = profilehelper_tdd.value
|
||||
pctUsed[tabSelected] = profilehelper_basalpctfromtdd.value
|
||||
ageUsed[tabSelected] = binding.age.value
|
||||
weightUsed[tabSelected] = binding.weight.value
|
||||
tddUsed[tabSelected] = binding.tdd.value
|
||||
pctUsed[tabSelected] = binding.basalpctfromtdd.value
|
||||
}
|
||||
|
||||
private fun switchTab(tab: Int, newContent: ProfileType, storeOld: Boolean = true) {
|
||||
|
@ -252,10 +259,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
|
||||
tabSelected = tab
|
||||
typeSelected[tabSelected] = newContent
|
||||
profilehelper_profiletype_title.defaultHintTextColor = ColorStateList.valueOf(resourceHelper.gc(if (tab == 0) R.color.tabBgColorSelected else R.color.examinedProfile))
|
||||
binding.profiletypeTitle.defaultHintTextColor = ColorStateList.valueOf(resourceHelper.gc(if (tab == 0) R.color.tabBgColorSelected else R.color.examinedProfile))
|
||||
|
||||
// show new content
|
||||
profilehelper_profiletype.setText(
|
||||
binding.profiletype.setText(
|
||||
when (typeSelected[tabSelected]) {
|
||||
ProfileType.MOTOL_DEFAULT -> resourceHelper.gs(R.string.motoldefaultprofile)
|
||||
ProfileType.DPV_DEFAULT -> resourceHelper.gs(R.string.dpvdefaultprofile)
|
||||
|
@ -263,26 +270,26 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
|||
ProfileType.AVAILABLE_PROFILE -> resourceHelper.gs(R.string.availableprofile)
|
||||
ProfileType.PROFILE_SWITCH -> resourceHelper.gs(R.string.careportal_profileswitch)
|
||||
})
|
||||
profilehelper_default_profile.visibility = (newContent == ProfileType.MOTOL_DEFAULT || newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
||||
profilehelper_current_profile.visibility = (newContent == ProfileType.CURRENT).toVisibility()
|
||||
profilehelper_available_profile.visibility = (newContent == ProfileType.AVAILABLE_PROFILE).toVisibility()
|
||||
profilehelper_profile_switch.visibility = (newContent == ProfileType.PROFILE_SWITCH).toVisibility()
|
||||
binding.defaultProfile.visibility = (newContent == ProfileType.MOTOL_DEFAULT || newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
||||
binding.currentProfile.visibility = (newContent == ProfileType.CURRENT).toVisibility()
|
||||
binding.availableProfile.visibility = (newContent == ProfileType.AVAILABLE_PROFILE).toVisibility()
|
||||
binding.profileSwitch.visibility = (newContent == ProfileType.PROFILE_SWITCH).toVisibility()
|
||||
|
||||
// restore selected values
|
||||
profilehelper_age.value = ageUsed[tabSelected]
|
||||
profilehelper_weight.value = weightUsed[tabSelected]
|
||||
profilehelper_tdd.value = tddUsed[tabSelected]
|
||||
profilehelper_basalpctfromtdd.value = pctUsed[tabSelected]
|
||||
binding.age.value = ageUsed[tabSelected]
|
||||
binding.weight.value = weightUsed[tabSelected]
|
||||
binding.tdd.value = tddUsed[tabSelected]
|
||||
binding.basalpctfromtdd.value = pctUsed[tabSelected]
|
||||
|
||||
profilehelper_basalpctfromtdd_row.visibility = (newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
||||
binding.basalpctfromtddRow.visibility = (newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
||||
if (profileList.isNotEmpty())
|
||||
profilehelper_available_profile_list.setText(profileList[profileUsed[tabSelected]].toString())
|
||||
binding.availableProfileList.setText(profileList[profileUsed[tabSelected]].toString())
|
||||
if (profileSwitch.isNotEmpty())
|
||||
profilehelper_profileswitch_list.setText(profileSwitch[profileSwitchUsed[tabSelected]].customizedName)
|
||||
binding.profileswitchList.setText(profileSwitch[profileSwitchUsed[tabSelected]].customizedName)
|
||||
}
|
||||
|
||||
private fun setBackgroundColorOnSelected(tab: Int) {
|
||||
profilehelper_menu1.setBackgroundColor(resourceHelper.gc(if (tab == 1) R.color.defaultbackground else R.color.tabBgColorSelected))
|
||||
profilehelper_menu2.setBackgroundColor(resourceHelper.gc(if (tab == 0) R.color.defaultbackground else R.color.examinedProfile))
|
||||
binding.menu1.setBackgroundColor(resourceHelper.gc(if (tab == 1) R.color.defaultbackground else R.color.tabBgColorSelected))
|
||||
binding.menu2.setBackgroundColor(resourceHelper.gc(if (tab == 0) R.color.defaultbackground else R.color.examinedProfile))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ class RequestDexcomPermissionActivity : DialogAppCompatActivity() {
|
|||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
finish()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,29 +5,20 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||
import javax.inject.Inject
|
||||
|
||||
class SingleFragmentActivity : DaggerAppCompatActivity() {
|
||||
class SingleFragmentActivity : DaggerAppCompatActivityWithResult() {
|
||||
|
||||
@Inject lateinit var pluginStore: PluginStore
|
||||
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||
@Inject lateinit var importExportPrefs: ImportExportPrefs
|
||||
|
||||
private var plugin: PluginBase? = null
|
||||
|
||||
val callForPrefFile = registerForActivityResult(PrefsFileContract()) {
|
||||
it?.let {
|
||||
importExportPrefs.importSharedPreferences(this, it)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_single_fragment)
|
||||
|
|
|
@ -2,35 +2,39 @@ package info.nightscout.androidaps.activities
|
|||
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.ActivityStatsBinding
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
||||
import info.nightscout.androidaps.utils.stats.TirCalculator
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.activity_stats.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class StatsActivity : NoSplashAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var tddCalculator: TddCalculator
|
||||
@Inject lateinit var tirCalculator: TirCalculator
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var activityMonitor: ActivityMonitor
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private lateinit var binding: ActivityStatsBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_stats)
|
||||
binding = ActivityStatsBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
stats_tdds.text = tddCalculator.stats()
|
||||
stats_tir.text = tirCalculator.stats()
|
||||
stats_activity.text = activityMonitor.stats()
|
||||
binding.tdds.text = tddCalculator.stats()
|
||||
binding.tir.text = tirCalculator.stats()
|
||||
binding.activity.text = activityMonitor.stats()
|
||||
|
||||
ok.setOnClickListener { finish() }
|
||||
stats_reset.setOnClickListener {
|
||||
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.doyouwantresetstats), Runnable {
|
||||
binding.ok.setOnClickListener { finish() }
|
||||
binding.reset.setOnClickListener {
|
||||
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.doyouwantresetstats)) {
|
||||
uel.log("STATS RESET")
|
||||
activityMonitor.reset()
|
||||
recreate()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ 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.databinding.ActivitySurveyBinding
|
||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
|
@ -16,15 +17,13 @@ import info.nightscout.androidaps.utils.DateUtil
|
|||
import info.nightscout.androidaps.utils.InstanceId
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
||||
import info.nightscout.androidaps.utils.stats.TirCalculator
|
||||
import kotlinx.android.synthetic.main.activity_survey.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class SurveyActivity : NoSplashAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var tddCalculator: TddCalculator
|
||||
@Inject lateinit var tirCalculator: TirCalculator
|
||||
|
@ -32,24 +31,27 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
|||
@Inject lateinit var activityMonitor: ActivityMonitor
|
||||
@Inject lateinit var defaultProfile: DefaultProfile
|
||||
|
||||
private lateinit var binding: ActivitySurveyBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_survey)
|
||||
binding = ActivitySurveyBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
survey_id.text = InstanceId.instanceId()
|
||||
binding.id.text = InstanceId.instanceId()
|
||||
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
val profileList = profileStore?.getProfileList() ?: return
|
||||
survey_spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
||||
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
||||
|
||||
survey_tdds.text = tddCalculator.stats()
|
||||
survey_tir.text = tirCalculator.stats()
|
||||
survey_activity.text = activityMonitor.stats()
|
||||
binding.tdds.text = tddCalculator.stats()
|
||||
binding.tir.text = tirCalculator.stats()
|
||||
binding.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())
|
||||
binding.profile.setOnClickListener {
|
||||
val age = SafeParse.stringToDouble(binding.age.text.toString())
|
||||
val weight = SafeParse.stringToDouble(binding.weight.text.toString())
|
||||
val tdd = SafeParse.stringToDouble(binding.tdd.text.toString())
|
||||
if (age < 1 || age > 120) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidage)
|
||||
return@setOnClickListener
|
||||
|
@ -78,11 +80,11 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
survey_submit.setOnClickListener {
|
||||
binding.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())
|
||||
r.age = SafeParse.stringToInt(binding.age.text.toString())
|
||||
r.weight = SafeParse.stringToInt(binding.weight.text.toString())
|
||||
if (r.age < 1 || r.age > 120) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidage)
|
||||
return@setOnClickListener
|
||||
|
@ -92,9 +94,9 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
|||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (survey_spinner.selectedItem == null)
|
||||
if (binding.spinner.selectedItem == null)
|
||||
return@setOnClickListener
|
||||
val profileName = survey_spinner.selectedItem.toString()
|
||||
val profileName = binding.spinner.selectedItem.toString()
|
||||
val specificProfile = profileStore.getSpecificProfile(profileName)
|
||||
|
||||
r.profileJson = specificProfile.toString()
|
||||
|
@ -121,6 +123,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
|
||||
inner class FirebaseRecord {
|
||||
|
||||
var id = ""
|
||||
var age: Int = 0
|
||||
var weight: Int = 0
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package info.nightscout.androidaps.db
|
||||
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||
import info.nightscout.androidaps.database.interfaces.TraceableDBEntry
|
||||
import info.nightscout.androidaps.events.EventNewBG
|
||||
import info.nightscout.androidaps.events.EventTempTargetChange
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||
import io.reactivex.disposables.Disposable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class CompatDBHelper @Inject constructor(
|
||||
val aapsLogger: AAPSLogger,
|
||||
val repository: AppRepository,
|
||||
val rxBus: RxBusWrapper
|
||||
) {
|
||||
|
||||
fun dbChangeDisposable(): Disposable = repository
|
||||
.changeObservable()
|
||||
.doOnSubscribe {
|
||||
rxBus.send(EventNewBG(null))
|
||||
}
|
||||
.subscribe {
|
||||
it.filterIsInstance<GlucoseValue>().firstOrNull()?.let {
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventNewHistoryData")
|
||||
rxBus.send(EventNewHistoryData(it.timestamp))
|
||||
}
|
||||
it.filterIsInstance<GlucoseValue>().lastOrNull()?.let {
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg")
|
||||
rxBus.send(EventNewBG(it))
|
||||
}
|
||||
it.filterIsInstance<TemporaryTarget>().firstOrNull()?.let {
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange")
|
||||
rxBus.send(EventTempTargetChange())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,13 +33,11 @@ import java.util.concurrent.TimeUnit;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.dana.comm.RecordTypes;
|
||||
import info.nightscout.androidaps.data.NonOverlappingIntervals;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.events.EventCareportalEventChange;
|
||||
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventProfileNeedsUpdate;
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||
import info.nightscout.androidaps.events.EventReloadProfileSwitchData;
|
||||
|
@ -54,9 +52,7 @@ import info.nightscout.androidaps.logging.AAPSLogger;
|
|||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryBgData;
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData;
|
||||
import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID;
|
||||
import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset;
|
||||
|
@ -64,7 +60,6 @@ import info.nightscout.androidaps.plugins.pump.insight.database.InsightPumpID;
|
|||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.utils.JsonHelper;
|
||||
import info.nightscout.androidaps.utils.PercentageSplitter;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
/**
|
||||
* This Helper contains all resource to provide a central DB management functionality. Only methods handling
|
||||
|
@ -81,7 +76,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
@Inject OpenHumansUploader openHumansUploader;
|
||||
|
||||
public static final String DATABASE_NAME = "AndroidAPSDb";
|
||||
public static final String DATABASE_BGREADINGS = "BgReadings";
|
||||
public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals";
|
||||
public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses";
|
||||
public static final String DATABASE_TEMPTARGETS = "TempTargets";
|
||||
|
@ -101,10 +95,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
private static final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledBgPost = null;
|
||||
|
||||
private static final ScheduledExecutorService bgHistoryWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledBgHistoryPost = null;
|
||||
private static long oldestBgHistoryChange = 0;
|
||||
|
||||
private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledTemBasalsPost = null;
|
||||
|
||||
|
@ -135,7 +125,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
try {
|
||||
aapsLogger.info(LTag.DATABASE, "onCreate");
|
||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||
//TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
|
||||
|
@ -167,7 +157,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
if (oldVersion < 7) {
|
||||
aapsLogger.info(LTag.DATABASE, "onUpgrade");
|
||||
TableUtils.dropTable(connectionSource, TempTarget.class, true);
|
||||
TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||
//TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
|
||||
TableUtils.dropTable(connectionSource, DbRequest.class, true);
|
||||
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
|
||||
|
@ -217,7 +207,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
public void resetDatabases() {
|
||||
try {
|
||||
TableUtils.dropTable(connectionSource, TempTarget.class, true);
|
||||
TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||
//TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
|
||||
TableUtils.dropTable(connectionSource, DbRequest.class, true);
|
||||
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
|
||||
|
@ -227,7 +217,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
TableUtils.dropTable(connectionSource, TDD.class, true);
|
||||
TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||
//TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
|
||||
|
@ -241,7 +231,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
virtualPumpPlugin.setFakingStatus(true);
|
||||
scheduleBgChange(null); // trigger refresh
|
||||
scheduleTemporaryBasalChange();
|
||||
scheduleExtendedBolusChange();
|
||||
scheduleTemporaryTargetChange();
|
||||
|
@ -326,10 +315,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return getDao(TempTarget.class);
|
||||
}
|
||||
|
||||
private Dao<BgReading, Long> getDaoBgReadings() throws SQLException {
|
||||
return getDao(BgReading.class);
|
||||
}
|
||||
|
||||
private Dao<DanaRHistoryRecord, String> getDaoDanaRHistory() throws SQLException {
|
||||
return getDao(DanaRHistoryRecord.class);
|
||||
}
|
||||
|
@ -384,144 +369,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
aapsLogger.debug(LTag.DATABASE, "Rounding " + date + " to " + rounded);
|
||||
return rounded;
|
||||
}
|
||||
// ------------------- BgReading handling -----------------------
|
||||
|
||||
public boolean createIfNotExists(BgReading bgReading, String from) {
|
||||
try {
|
||||
bgReading.date = roundDateToSec(bgReading.date);
|
||||
BgReading old = getDaoBgReadings().queryForId(bgReading.date);
|
||||
if (old == null) {
|
||||
getDaoBgReadings().create(bgReading);
|
||||
openHumansUploader.enqueueBGReading(bgReading);
|
||||
aapsLogger.debug(LTag.DATABASE, "BG: New record from: " + from + " " + bgReading.toString());
|
||||
scheduleBgChange(bgReading);
|
||||
return true;
|
||||
}
|
||||
if (!old.isEqual(bgReading)) {
|
||||
aapsLogger.debug(LTag.DATABASE, "BG: Similiar found: " + old.toString());
|
||||
old.copyFrom(bgReading);
|
||||
getDaoBgReadings().update(old);
|
||||
openHumansUploader.enqueueBGReading(old);
|
||||
aapsLogger.debug(LTag.DATABASE, "BG: Updating record from: " + from + " New data: " + old.toString());
|
||||
scheduleBgHistoryChange(old.date); // trigger cache invalidation
|
||||
return false;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void update(BgReading bgReading) {
|
||||
bgReading.date = roundDateToSec(bgReading.date);
|
||||
try {
|
||||
getDaoBgReadings().update(bgReading);
|
||||
openHumansUploader.enqueueBGReading(bgReading);
|
||||
aapsLogger.debug(LTag.DATABASE, "BG: Updating record from: "+ bgReading.toString());
|
||||
scheduleBgHistoryChange(bgReading.date); // trigger cache invalidation
|
||||
} catch (SQLException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleBgChange(@Nullable final BgReading bgReading) {
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg");
|
||||
rxBus.send(new EventNewBG(bgReading));
|
||||
scheduledBgPost = null;
|
||||
}
|
||||
}
|
||||
// prepare task for execution in 1 sec
|
||||
// cancel waiting task to prevent sending multiple posts
|
||||
if (scheduledBgPost != null)
|
||||
scheduledBgPost.cancel(false);
|
||||
Runnable task = new PostRunnable();
|
||||
final int sec = 1;
|
||||
scheduledBgPost = bgWorker.schedule(task, sec, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
private void scheduleBgHistoryChange(@Nullable final long timestamp) {
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg");
|
||||
rxBus.send(new EventNewHistoryBgData(oldestBgHistoryChange));
|
||||
scheduledBgHistoryPost = null;
|
||||
oldestBgHistoryChange = 0;
|
||||
}
|
||||
}
|
||||
// prepare task for execution in 1 sec
|
||||
// cancel waiting task to prevent sending multiple posts
|
||||
if (scheduledBgHistoryPost != null)
|
||||
scheduledBgHistoryPost.cancel(false);
|
||||
Runnable task = new PostRunnable();
|
||||
final int sec = 3;
|
||||
if (oldestBgHistoryChange == 0 || oldestBgHistoryChange > timestamp)
|
||||
oldestBgHistoryChange = timestamp;
|
||||
scheduledBgHistoryPost = bgHistoryWorker.schedule(task, sec, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
public List<BgReading> getBgreadingsDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
|
||||
List<BgReading> bgReadings;
|
||||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("date", mills).and().ge("value", 39).and().eq("isValid", true);
|
||||
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||
bgReadings = daoBgreadings.query(preparedQuery);
|
||||
return bgReadings;
|
||||
} catch (SQLException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<BgReading> getBgreadingsDataFromTime(long start, long end, boolean ascending) {
|
||||
try {
|
||||
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
|
||||
List<BgReading> bgReadings;
|
||||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.between("date", start, end).and().ge("value", 39).and().eq("isValid", true);
|
||||
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||
bgReadings = daoBgreadings.query(preparedQuery);
|
||||
return bgReadings;
|
||||
} catch (SQLException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<BgReading> getAllBgreadingsDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
|
||||
List<BgReading> bgReadings;
|
||||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("date", mills);
|
||||
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||
bgReadings = daoBgreadings.query(preparedQuery);
|
||||
return bgReadings;
|
||||
} catch (SQLException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<BgReading>();
|
||||
}
|
||||
|
||||
public List<BgReading> getAllBgReadings() {
|
||||
try {
|
||||
return getDaoBgReadings().queryForAll();
|
||||
} catch (SQLException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// ------------------- TDD handling -----------------------
|
||||
public void createOrUpdateTDD(TDD tdd) {
|
||||
|
@ -1672,6 +1519,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProfileSwitch getLastProfileSwitchWithoutDuration() {
|
||||
try {
|
||||
|
@ -2010,7 +1858,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Copied from xDrip+
|
||||
/*
|
||||
TODO implement again for database branch // Copied from xDrip+
|
||||
String calculateDirection(BgReading bgReading) {
|
||||
// Rework to get bgreaings from internal DB and calculate on that base
|
||||
|
||||
|
@ -2056,7 +1905,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
// aapsLogger.error(LTag.GLUCOSE, "Direction set to: " + arrow);
|
||||
return arrow;
|
||||
}
|
||||
|
||||
*/
|
||||
// ---------------- Open Humans Queue handling ---------------
|
||||
|
||||
public void clearOpenHumansQueue() {
|
||||
|
@ -2109,8 +1958,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
public long getCountOfAllRows() {
|
||||
try {
|
||||
return getDaoBgReadings().countOf()
|
||||
+ getDaoCareportalEvents().countOf()
|
||||
return getDaoCareportalEvents().countOf()
|
||||
+ getDaoExtendedBolus().countOf()
|
||||
+ getDaoCareportalEvents().countOf()
|
||||
+ getDaoProfileSwitch().countOf()
|
||||
|
|
|
@ -20,10 +20,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
|
|||
@Inject DatabaseHelperProvider() {
|
||||
}
|
||||
|
||||
@NotNull @Override public List<BgReading> getAllBgreadingsDataFromTime(long mills, boolean ascending) {
|
||||
return MainApp.getDbHelper().getAllBgreadingsDataFromTime(mills, ascending);
|
||||
}
|
||||
|
||||
@Override public void createOrUpdate(@NotNull CareportalEvent careportalEvent) {
|
||||
MainApp.getDbHelper().createOrUpdate(careportalEvent);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import info.nightscout.androidaps.MainActivity
|
|||
import info.nightscout.androidaps.activities.*
|
||||
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansLoginActivity
|
||||
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity
|
||||
|
@ -40,7 +39,6 @@ abstract class ActivitiesModule {
|
|||
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
|
||||
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
|
||||
@ContributesAndroidInjector abstract fun contributesDefaultProfileActivity(): ProfileHelperActivity
|
||||
@ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity
|
||||
@ContributesAndroidInjector abstract fun contributesOpenHumansLoginActivity(): OpenHumansLoginActivity
|
||||
|
||||
}
|
|
@ -9,14 +9,16 @@ import info.nightscout.androidaps.core.di.CoreModule
|
|||
import info.nightscout.androidaps.dana.di.DanaModule
|
||||
import info.nightscout.androidaps.danar.di.DanaRModule
|
||||
import info.nightscout.androidaps.danars.di.DanaRSModule
|
||||
import info.nightscout.androidaps.database.DatabaseModule
|
||||
import info.nightscout.androidaps.plugins.pump.common.dagger.RileyLinkModule
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dagger.OmnipodModule
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.eros.dagger.OmnipodErosModule
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Component(
|
||||
modules = [
|
||||
AndroidInjectionModule::class,
|
||||
DatabaseModule::class,
|
||||
PluginsModule::class,
|
||||
SkinsModule::class,
|
||||
ActivitiesModule::class,
|
||||
|
@ -30,7 +32,7 @@ import javax.inject.Singleton
|
|||
WizardModule::class,
|
||||
RileyLinkModule::class,
|
||||
MedtronicModule::class,
|
||||
OmnipodModule::class,
|
||||
OmnipodErosModule::class,
|
||||
APSModule::class,
|
||||
PreferencesModule::class,
|
||||
OverviewModule::class,
|
||||
|
@ -41,6 +43,7 @@ import javax.inject.Singleton
|
|||
DanaModule::class,
|
||||
DanaRModule::class,
|
||||
DanaRSModule::class,
|
||||
WorkersModule::class,
|
||||
OHUploaderModule::class
|
||||
]
|
||||
)
|
||||
|
|
|
@ -12,10 +12,13 @@ import info.nightscout.androidaps.db.DatabaseHelperProvider
|
|||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.queue.CommandQueue
|
||||
import info.nightscout.androidaps.utils.androidNotification.NotificationHolder
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.rx.DefaultAapsSchedulers
|
||||
import info.nightscout.androidaps.utils.storage.FileStorage
|
||||
import info.nightscout.androidaps.utils.storage.Storage
|
||||
import javax.inject.Singleton
|
||||
|
@ -45,6 +48,10 @@ open class AppModule {
|
|||
return FileStorage()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
internal fun provideSchedulers(): AapsSchedulers = DefaultAapsSchedulers()
|
||||
|
||||
@Module
|
||||
interface AppBindings {
|
||||
|
||||
|
@ -58,5 +65,6 @@ open class AppModule {
|
|||
@Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface
|
||||
@Binds fun bindUploadQueueInterface(uploadQueue: UploadQueue): UploadQueueInterface
|
||||
@Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolder): NotificationHolderInterface
|
||||
@Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefs): ImportExportPrefsInterface
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,9 @@ package info.nightscout.androidaps.dependencyInjection
|
|||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.*
|
||||
import info.nightscout.androidaps.interfaces.ProfileStore
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.db.DatabaseHelper
|
||||
import info.nightscout.androidaps.plugins.general.food.FoodService
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentService
|
||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
||||
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
||||
|
|
|
@ -36,7 +36,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyL
|
|||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightFragment
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicFragment
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.dialog.RileyLinkStatusDeviceMedtronic
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.ui.OmnipodOverviewFragment
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.eros.ui.OmnipodOverviewFragment
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpFragment
|
||||
import info.nightscout.androidaps.plugins.source.BGSourceFragment
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsFragment
|
||||
|
@ -77,18 +77,13 @@ abstract class FragmentsModule {
|
|||
|
||||
@ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsCareportalFragment(): TreatmentsCareportalFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsProfileSwitchFragment(): TreatmentsProfileSwitchFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsCareportalFragment(): TreatmentsCareportalFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsProfileSwitchFragment(): TreatmentsProfileSwitchFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsUserEntryFragment(): TreatmentsUserEntryFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesVirtualPumpFragment(): VirtualPumpFragment
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
|
|||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
|
@ -160,7 +160,7 @@ abstract class PluginsModule {
|
|||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(155)
|
||||
abstract fun bindOmnipodPumpPlugin(plugin: OmnipodPumpPlugin): PluginBase
|
||||
abstract fun bindOmnipodPumpPlugin(plugin: OmnipodErosPumpPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
|
@ -205,7 +205,7 @@ abstract class PluginsModule {
|
|||
abstract fun bindLocalProfilePlugin(plugin: LocalProfilePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(250)
|
||||
abstract fun bindAutomationPlugin(plugin: AutomationPlugin): PluginBase
|
||||
|
|
|
@ -2,7 +2,6 @@ package info.nightscout.androidaps.dependencyInjection
|
|||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat
|
||||
|
@ -13,7 +12,6 @@ import info.nightscout.androidaps.utils.CryptoUtil
|
|||
abstract class PreferencesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun cryptoUtilInjector(): CryptoUtil
|
||||
@ContributesAndroidInjector abstract fun importExportPrefsInjector(): ImportExportPrefs
|
||||
@ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat
|
||||
@ContributesAndroidInjector abstract fun classicPrefsFormatInjector(): ClassicPrefsFormat
|
||||
@ContributesAndroidInjector abstract fun prefImportListProviderInjector(): PrefFileListProvider
|
||||
|
|
|
@ -12,6 +12,7 @@ import info.nightscout.androidaps.receivers.*
|
|||
@Suppress("unused")
|
||||
abstract class ReceiversModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesAutoStartReceiver(): AutoStartReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
|
||||
|
|
|
@ -10,9 +10,8 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley
|
|||
import info.nightscout.androidaps.plugins.pump.insight.InsightAlertService
|
||||
import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.service.RileyLinkOmnipodService
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.eros.rileylink.service.RileyLinkOmnipodService
|
||||
import info.nightscout.androidaps.services.AlarmSoundService
|
||||
import info.nightscout.androidaps.services.DataService
|
||||
import info.nightscout.androidaps.services.LocationService
|
||||
|
||||
@Module
|
||||
|
@ -20,7 +19,6 @@ import info.nightscout.androidaps.services.LocationService
|
|||
abstract class ServicesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesAlarmSoundService(): AlarmSoundService
|
||||
@ContributesAndroidInjector abstract fun contributesDataService(): DataService
|
||||
@ContributesAndroidInjector abstract fun contributesDismissNotificationService(): DismissNotificationService
|
||||
@ContributesAndroidInjector abstract fun contributesDummyService(): DummyService
|
||||
@ContributesAndroidInjector abstract fun contributesLocationService(): LocationService
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientWorker
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.source.*
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class WorkersModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesXdripWorker(): XdripPlugin.XdripWorker
|
||||
@ContributesAndroidInjector abstract fun contributesDexcomWorker(): DexcomPlugin.DexcomWorker
|
||||
@ContributesAndroidInjector abstract fun contributesMM640gWorker(): MM640gPlugin.MM640gWorker
|
||||
@ContributesAndroidInjector abstract fun contributesGlimpWorker(): GlimpPlugin.GlimpWorker
|
||||
@ContributesAndroidInjector abstract fun contributesPoctechWorker(): PoctechPlugin.PoctechWorker
|
||||
@ContributesAndroidInjector abstract fun contributesTomatoWorker(): TomatoPlugin.TomatoWorker
|
||||
@ContributesAndroidInjector abstract fun contributesEversenseWorker(): EversensePlugin.EversenseWorker
|
||||
@ContributesAndroidInjector abstract fun contributesNSClientSourceWorker(): NSClientSourcePlugin.NSClientSourceWorker
|
||||
@ContributesAndroidInjector abstract fun contributesNSProfileWorker(): NSProfilePlugin.NSProfileWorker
|
||||
@ContributesAndroidInjector abstract fun contributesSmsCommunicatorWorker(): SmsCommunicatorPlugin.SmsCommunicatorWorker
|
||||
@ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientWorker
|
||||
}
|
|
@ -9,14 +9,14 @@ import dagger.android.HasAndroidInjector
|
|||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.databinding.DialogCalibrationBinding
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.XdripCalibrations
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_calibration.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
@ -27,16 +27,24 @@ class CalibrationDialog : DialogFragmentWithDate() {
|
|||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var xdripCalibrations: XdripCalibrations
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private var _binding: DialogCalibrationBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_calibration_bg", overview_calibration_bg.value)
|
||||
savedInstanceState.putDouble("bg", binding.bg.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_calibration, container, false)
|
||||
_binding = DialogCalibrationBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@ -46,24 +54,30 @@ class CalibrationDialog : DialogFragmentWithDate() {
|
|||
val bg = Profile.fromMgdlToUnits(GlucoseStatus(injector).glucoseStatusData?.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)
|
||||
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
||||
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.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) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
||||
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
binding.units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
if (_binding == null) return false
|
||||
val units = profileFunction.getUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val bg = overview_calibration_bg?.value ?: return false
|
||||
val bg = binding.bg.value ?: return false
|
||||
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, bg) + " " + unitLabel)
|
||||
if (bg > 0) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: CALIBRATION $bg")
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
uel.log("CALIBRATION", d1 = bg)
|
||||
xdripCalibrations.sendIntent(bg)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,11 +11,13 @@ 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.databinding.DialogCarbsBinding
|
||||
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.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
|
@ -29,15 +31,13 @@ import info.nightscout.androidaps.utils.ToastUtils
|
|||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
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 javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
||||
class CarbsDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
|
@ -47,8 +47,10 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||
@Inject lateinit var nsUpload: NSUpload
|
||||
@Inject lateinit var carbsGenerator: CarbsGenerator
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
companion object {
|
||||
|
||||
private const val FAV1_DEFAULT = 5
|
||||
private const val FAV2_DEFAULT = 10
|
||||
private const val FAV3_DEFAULT = 20
|
||||
|
@ -65,92 +67,105 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
|
||||
private fun validateInputs() {
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
val time = overview_carbs_time.value.toInt()
|
||||
val time = binding.time.value.toInt()
|
||||
if (time > 12 * 60 || time < -12 * 60) {
|
||||
overview_carbs_time.value = 0.0
|
||||
binding.time.value = 0.0
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_carbs_duration.value > 10) {
|
||||
overview_carbs_duration.value = 0.0
|
||||
if (binding.duration.value > 10) {
|
||||
binding.duration.value = 0.0
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_carbs_carbs.value.toInt() > maxCarbs) {
|
||||
overview_carbs_carbs.value = 0.0
|
||||
if (binding.carbs.value.toInt() > maxCarbs) {
|
||||
binding.carbs.value = 0.0
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
private var _binding: DialogCarbsBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
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)
|
||||
savedInstanceState.putDouble("time", binding.time.value)
|
||||
savedInstanceState.putDouble("duration", binding.duration.value)
|
||||
savedInstanceState.putDouble("carbs", binding.carbs.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_carbs, container, false)
|
||||
_binding = DialogCarbsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
overview_carbs_time.setParams(savedInstanceState?.getDouble("overview_carbs_time")
|
||||
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
binding.time.setParams(savedInstanceState?.getDouble("time")
|
||||
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
|
||||
|
||||
overview_carbs_duration.setParams(savedInstanceState?.getDouble("overview_carbs_duration")
|
||||
?: 0.0, 0.0, 10.0, 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||
?: 0.0, 0.0, 10.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
|
||||
|
||||
overview_carbs_carbs.setParams(savedInstanceState?.getDouble("overview_carbs_carbs")
|
||||
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
binding.carbs.setParams(savedInstanceState?.getDouble("carbs")
|
||||
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.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
|
||||
binding.plus1.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
|
||||
binding.plus1.setOnClickListener {
|
||||
binding.carbs.value = max(0.0, binding.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
|
||||
binding.plus2.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
|
||||
binding.plus2.setOnClickListener {
|
||||
binding.carbs.value = max(0.0, binding.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
|
||||
binding.plus3.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
binding.plus3.setOnClickListener {
|
||||
binding.carbs.value = max(0.0, binding.carbs.value
|
||||
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
iobCobCalculatorPlugin.actualBg()?.let { bgReading ->
|
||||
if (bgReading.value < 72)
|
||||
overview_carbs_hypo_tt.isChecked = true
|
||||
binding.hypoTt.isChecked = true
|
||||
}
|
||||
overview_carbs_hypo_tt.setOnClickListener {
|
||||
overview_carbs_activity_tt.isChecked = false
|
||||
overview_carbs_eating_soon_tt.isChecked = false
|
||||
binding.hypoTt.setOnClickListener {
|
||||
binding.activityTt.isChecked = false
|
||||
binding.eatingSoonTt.isChecked = false
|
||||
}
|
||||
overview_carbs_activity_tt.setOnClickListener {
|
||||
overview_carbs_hypo_tt.isChecked = false
|
||||
overview_carbs_eating_soon_tt.isChecked = false
|
||||
binding.activityTt.setOnClickListener {
|
||||
binding.hypoTt.isChecked = false
|
||||
binding.eatingSoonTt.isChecked = false
|
||||
}
|
||||
overview_carbs_eating_soon_tt.setOnClickListener {
|
||||
overview_carbs_hypo_tt.isChecked = false
|
||||
overview_carbs_activity_tt.isChecked = false
|
||||
binding.eatingSoonTt.setOnClickListener {
|
||||
binding.hypoTt.isChecked = false
|
||||
binding.activityTt.isChecked = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
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() ?: return false
|
||||
if (_binding == null) return false
|
||||
val carbs = binding.carbs.value?.toInt() ?: return false
|
||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
||||
val units = profileFunction.getUnits()
|
||||
val activityTTDuration = defaultValueHelper.determineActivityTTDuration()
|
||||
|
@ -162,22 +177,22 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
val actions: LinkedList<String?> = LinkedList()
|
||||
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
|
||||
val activitySelected = overview_carbs_activity_tt.isChecked
|
||||
val activitySelected = binding.activityTt.isChecked
|
||||
if (activitySelected)
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, activityTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
val eatingSoonSelected = overview_carbs_eating_soon_tt.isChecked
|
||||
val eatingSoonSelected = binding.eatingSoonTt.isChecked
|
||||
if (eatingSoonSelected)
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, eatingSoonTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
val hypoSelected = overview_carbs_hypo_tt.isChecked
|
||||
val hypoSelected = binding.hypoTt.isChecked
|
||||
if (hypoSelected)
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, hypoTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
|
||||
val timeOffset = overview_carbs_time.value.toInt()
|
||||
val timeOffset = binding.time.value.toInt()
|
||||
eventTime -= eventTime % 1000
|
||||
val time = eventTime + timeOffset * 1000 * 60
|
||||
if (timeOffset != 0)
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(time))
|
||||
val duration = overview_carbs_duration.value.toInt()
|
||||
val duration = binding.duration.value.toInt()
|
||||
if (duration > 0)
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + duration + resourceHelper.gs(R.string.shorthour))
|
||||
if (carbsAfterConstraints > 0) {
|
||||
|
@ -185,7 +200,7 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
if (carbsAfterConstraints != carbs)
|
||||
actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.carbsconstraintapplied) + "</font>")
|
||||
}
|
||||
val notes = notes.text.toString()
|
||||
val notes = binding.notesLayout.notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
|
||||
|
@ -194,10 +209,10 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
|
||||
if (carbsAfterConstraints > 0 || activitySelected || eatingSoonSelected || hypoSelected) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
when {
|
||||
activitySelected -> {
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET ACTIVITY $activityTT duration: $activityTTDuration")
|
||||
uel.log("TT ACTIVITY", d1 = activityTT, i1 = activityTTDuration)
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(activityTTDuration)
|
||||
|
@ -209,7 +224,7 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
|
||||
eatingSoonSelected -> {
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
|
||||
uel.log("TT EATING SOON", d1 = eatingSoonTT, i1 = eatingSoonTTDuration)
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(eatingSoonTTDuration)
|
||||
|
@ -221,7 +236,7 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
|
||||
hypoSelected -> {
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET HYPO $hypoTT duration: $hypoTTDuration")
|
||||
uel.log("TT HYPO", d1 = hypoTT, i1 = hypoTTDuration)
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(hypoTTDuration)
|
||||
|
@ -234,10 +249,10 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
if (carbsAfterConstraints > 0) {
|
||||
if (duration == 0) {
|
||||
aapsLogger.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time")
|
||||
uel.log("CARBS", d1 = carbsAfterConstraints.toDouble(), i1 = timeOffset)
|
||||
carbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes)
|
||||
} else {
|
||||
aapsLogger.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time duration: $duration")
|
||||
uel.log("CARBS", d1 = carbsAfterConstraints.toDouble(), i1 = timeOffset, i2 = duration)
|
||||
carbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
|
||||
nsUpload.uploadEvent(CareportalEvent.NOTE, DateUtil.now() - 2000, resourceHelper.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))
|
||||
}
|
||||
|
|
|
@ -13,9 +13,11 @@ 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.databinding.DialogCareBinding
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
|
@ -23,21 +25,20 @@ import info.nightscout.androidaps.utils.HtmlHelper
|
|||
import info.nightscout.androidaps.utils.Translator
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
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.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class CareDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var nsUpload: NSUpload
|
||||
@Inject lateinit var translator: Translator
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
enum class EventType {
|
||||
BGCHECK,
|
||||
|
@ -60,18 +61,25 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
return this
|
||||
}
|
||||
|
||||
private var _binding: DialogCareBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
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)
|
||||
savedInstanceState.putDouble("bg", binding.bg.value)
|
||||
savedInstanceState.putDouble("duration", binding.duration.value)
|
||||
savedInstanceState.putInt("event", event)
|
||||
savedInstanceState.putInt("options", options.ordinal)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_care, container, false)
|
||||
_binding = DialogCareBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@ -82,7 +90,7 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
options = EventType.values()[savedInstanceState.getInt("options", 0)]
|
||||
}
|
||||
|
||||
actions_care_icon.setImageResource(when (options) {
|
||||
binding.icon.setImageResource(when (options) {
|
||||
EventType.BGCHECK -> R.drawable.ic_cp_bgcheck
|
||||
EventType.SENSOR_INSERT -> R.drawable.ic_cp_cgm_insert
|
||||
EventType.BATTERY_CHANGE -> R.drawable.ic_cp_pump_battery
|
||||
|
@ -91,7 +99,7 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
EventType.QUESTION -> R.drawable.ic_cp_question
|
||||
EventType.ANNOUNCEMENT -> R.drawable.ic_cp_announcement
|
||||
})
|
||||
actions_care_title.text = resourceHelper.gs(when (options) {
|
||||
binding.title.text = resourceHelper.gs(when (options) {
|
||||
EventType.BGCHECK -> R.string.careportal_bgcheck
|
||||
EventType.SENSOR_INSERT -> R.string.careportal_cgmsensorinsert
|
||||
EventType.BATTERY_CHANGE -> R.string.careportal_pumpbatterychange
|
||||
|
@ -104,21 +112,21 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
when (options) {
|
||||
EventType.QUESTION,
|
||||
EventType.ANNOUNCEMENT,
|
||||
EventType.BGCHECK -> {
|
||||
action_care_duration_layout.visibility = View.GONE
|
||||
EventType.BGCHECK -> {
|
||||
binding.durationLayout.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
|
||||
binding.bgLayout.visibility = View.GONE
|
||||
binding.bgsource.visibility = View.GONE
|
||||
binding.durationLayout.visibility = View.GONE
|
||||
}
|
||||
|
||||
EventType.NOTE,
|
||||
EventType.EXERCISE -> {
|
||||
action_care_bg_layout.visibility = View.GONE
|
||||
actions_care_bgsource.visibility = View.GONE
|
||||
EventType.EXERCISE -> {
|
||||
binding.bgLayout.visibility = View.GONE
|
||||
binding.bgsource.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,23 +136,28 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
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 (binding.sensor.isChecked) binding.meter.isChecked = true
|
||||
}
|
||||
}
|
||||
|
||||
if (profileFunction.getUnits() == Constants.MMOL) {
|
||||
actions_care_bgunits.text = resourceHelper.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)
|
||||
binding.bgunits.text = resourceHelper.gs(R.string.mmol)
|
||||
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
||||
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok, bgTextWatcher)
|
||||
} else {
|
||||
actions_care_bgunits.text = resourceHelper.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)
|
||||
binding.bgunits.text = resourceHelper.gs(R.string.mgdl)
|
||||
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
||||
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.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 || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT)
|
||||
notes_layout?.visibility = View.VISIBLE // independent to preferences
|
||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
|
||||
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
|
@ -156,20 +169,20 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
if (options == EventType.BGCHECK || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT) {
|
||||
val type =
|
||||
when {
|
||||
actions_care_meter.isChecked -> CareportalEvent.FINGER
|
||||
actions_care_sensor.isChecked -> CareportalEvent.SENSOR
|
||||
else -> CareportalEvent.MANUAL
|
||||
binding.meter.isChecked -> CareportalEvent.FINGER
|
||||
binding.sensor.isChecked -> CareportalEvent.SENSOR
|
||||
else -> CareportalEvent.MANUAL
|
||||
}
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + translator.translate(type))
|
||||
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, actions_care_bg.value) + " " + resourceHelper.gs(unitResId))
|
||||
json.put("glucose", actions_care_bg.value)
|
||||
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, binding.bg.value) + " " + resourceHelper.gs(unitResId))
|
||||
json.put("glucose", binding.bg.value)
|
||||
json.put("glucoseType", type)
|
||||
}
|
||||
if (options == EventType.NOTE || options == EventType.EXERCISE) {
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_duration_label) + ": " + resourceHelper.gs(R.string.format_mins, actions_care_duration.value.toInt()))
|
||||
json.put("duration", actions_care_duration.value.toInt())
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_duration_label) + ": " + resourceHelper.gs(R.string.format_mins, binding.duration.value.toInt()))
|
||||
json.put("duration", binding.duration.value.toInt())
|
||||
}
|
||||
val notes = notes.text.toString()
|
||||
val notes = binding.notesLayout.notes.text.toString()
|
||||
if (notes.isNotEmpty()) {
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
json.put("notes", notes)
|
||||
|
@ -195,7 +208,7 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
json.put("enteredBy", enteredBy)
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
val careportalEvent = CareportalEvent(injector)
|
||||
careportalEvent.date = eventTime
|
||||
careportalEvent.source = Source.USER
|
||||
|
@ -209,7 +222,7 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
EventType.ANNOUNCEMENT -> CareportalEvent.ANNOUNCEMENT
|
||||
}
|
||||
careportalEvent.json = json.toString()
|
||||
aapsLogger.debug("USER ENTRY: CAREPORTAL ${careportalEvent.eventType} json: ${careportalEvent.json}")
|
||||
uel.log("CAREPORTAL", careportalEvent.eventType)
|
||||
MainApp.getDbHelper().createOrUpdate(careportalEvent)
|
||||
nsUpload.uploadCareportalEntryToNS(json)
|
||||
}, null)
|
||||
|
|
|
@ -8,6 +8,8 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import dagger.android.support.DaggerDialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
|
@ -16,9 +18,6 @@ import info.nightscout.androidaps.logging.LTag
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import kotlinx.android.synthetic.main.datetime.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -58,10 +57,14 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
|
|||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val eventDateView = view.findViewById(R.id.eventdate) as TextView?
|
||||
val eventTimeView = view.findViewById(R.id.eventtime) as TextView?
|
||||
|
||||
eventTime = savedInstanceState?.getLong("eventTime") ?: DateUtil.now()
|
||||
eventTimeChanged = savedInstanceState?.getBoolean("eventTimeChanged") ?: false
|
||||
overview_eventdate?.text = DateUtil.dateString(eventTime)
|
||||
overview_eventtime?.text = dateUtil.timeString(eventTime)
|
||||
|
||||
eventDateView?.text = DateUtil.dateString(eventTime)
|
||||
eventTimeView?.text = dateUtil.timeString(eventTime)
|
||||
|
||||
// create an OnDateSetListener
|
||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
|
@ -72,10 +75,10 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
|
|||
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
eventTime = cal.timeInMillis
|
||||
eventTimeChanged = true
|
||||
overview_eventdate?.text = DateUtil.dateString(eventTime)
|
||||
eventDateView?.text = DateUtil.dateString(eventTime)
|
||||
}
|
||||
|
||||
overview_eventdate?.setOnClickListener {
|
||||
eventDateView?.setOnClickListener {
|
||||
context?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = eventTime
|
||||
|
@ -96,10 +99,10 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
|
|||
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)
|
||||
eventTimeView?.text = dateUtil.timeString(eventTime)
|
||||
}
|
||||
|
||||
overview_eventtime?.setOnClickListener {
|
||||
eventTimeView?.setOnClickListener {
|
||||
context?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = eventTime
|
||||
|
@ -111,9 +114,9 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
notes_layout?.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
(view.findViewById(R.id.notes_layout) as View?)?.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
|
||||
ok.setOnClickListener {
|
||||
(view.findViewById(R.id.ok) as Button?)?.setOnClickListener {
|
||||
synchronized(okClicked) {
|
||||
if (okClicked) {
|
||||
aapsLogger.warn(LTag.UI, "guarding: ok already clicked")
|
||||
|
@ -124,7 +127,7 @@ abstract class DialogFragmentWithDate : DaggerDialogFragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
(view.findViewById(R.id.cancel) as Button?)?.setOnClickListener { dismiss() }
|
||||
}
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
|
|
|
@ -1,48 +1,56 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.Context
|
||||
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.databinding.DialogExtendedbolusBinding
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_extendedbolus.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private var _binding: DialogExtendedbolusBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
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)
|
||||
savedInstanceState.putDouble("insulin", binding.insulin.value)
|
||||
savedInstanceState.putDouble("duration", binding.duration.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_extendedbolus, container, false)
|
||||
_binding = DialogExtendedbolusBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@ -52,18 +60,24 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
|||
|
||||
val maxInsulin = constraintChecker.getMaxExtendedBolusAllowed().value()
|
||||
val extendedStep = pumpDescription.extendedBolusStep
|
||||
actions_extendedbolus_insulin.setParams(savedInstanceState?.getDouble("actions_extendedbolus_insulin")
|
||||
?: extendedStep, extendedStep, maxInsulin, extendedStep, DecimalFormat("0.00"), false, ok)
|
||||
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
|
||||
?: extendedStep, extendedStep, maxInsulin, extendedStep, DecimalFormat("0.00"), false, binding.okcancel.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)
|
||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin?.text ?: return false)
|
||||
val durationInMinutes = actions_extendedbolus_duration.value.toInt()
|
||||
if (_binding == null) return false
|
||||
val insulin = SafeParse.stringToDouble(binding.insulin.text ?: return false)
|
||||
val durationInMinutes = binding.duration.value.toInt()
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val insulinAfterConstraint = constraintChecker.applyExtendedBolusConstraints(Constraint(insulin)).value()
|
||||
actions.add(resourceHelper.gs(R.string.formatinsulinunits, insulinAfterConstraint))
|
||||
|
@ -72,17 +86,12 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
|||
actions.add(resourceHelper.gs(R.string.constraintapllied).formatColor(resourceHelper, R.color.warning))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: EXTENDED BOLUS $insulinAfterConstraint duration: $durationInMinutes")
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
uel.log("EXTENDED BOLUS", d1 = insulinAfterConstraint, i1 = durationInMinutes)
|
||||
commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(mainApp, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
mainApp.startActivity(i)
|
||||
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -10,11 +9,13 @@ import com.google.common.base.Joiner
|
|||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.databinding.DialogFillBinding
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
|
@ -24,30 +25,36 @@ import info.nightscout.androidaps.utils.SafeParse
|
|||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_fill.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class FillDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var nsUpload: NSUpload
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private var _binding: DialogFillBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("fill_insulin_amount", fill_insulinamount.value)
|
||||
savedInstanceState.putDouble("fill_insulin_amount", binding.fillInsulinamount.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_fill, container, false)
|
||||
_binding = DialogFillBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@ -55,37 +62,43 @@ class FillDialog : DialogFragmentWithDate() {
|
|||
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
val bolusStep = activePlugin.activePump.pumpDescription.bolusStep
|
||||
fill_insulinamount.setParams(savedInstanceState?.getDouble("fill_insulin_amount")
|
||||
?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), true, ok)
|
||||
binding.fillInsulinamount.setParams(savedInstanceState?.getDouble("fill_insulin_amount")
|
||||
?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), true, binding.okcancel.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, activePlugin.activePump) // + "U");
|
||||
fill_preset_button1.setOnClickListener { fill_insulinamount.value = amount1 }
|
||||
binding.fillPresetButton1.visibility = View.VISIBLE
|
||||
binding.fillPresetButton1.text = DecimalFormatter.toPumpSupportedBolus(amount1, activePlugin.activePump) // + "U");
|
||||
binding.fillPresetButton1.setOnClickListener { binding.fillInsulinamount.value = amount1 }
|
||||
} else {
|
||||
fill_preset_button1.visibility = View.GONE
|
||||
binding.fillPresetButton1.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, activePlugin.activePump) // + "U");
|
||||
fill_preset_button2.setOnClickListener { fill_insulinamount.value = amount2 }
|
||||
binding.fillPresetButton2.visibility = View.VISIBLE
|
||||
binding.fillPresetButton2.text = DecimalFormatter.toPumpSupportedBolus(amount2, activePlugin.activePump) // + "U");
|
||||
binding.fillPresetButton2.setOnClickListener { binding.fillInsulinamount.value = amount2 }
|
||||
} else {
|
||||
fill_preset_button2.visibility = View.GONE
|
||||
binding.fillPresetButton2.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, activePlugin.activePump) // + "U");
|
||||
fill_preset_button3.setOnClickListener { fill_insulinamount.value = amount3 }
|
||||
binding.fillPresetButton3.visibility = View.VISIBLE
|
||||
binding.fillPresetButton3.text = DecimalFormatter.toPumpSupportedBolus(amount3, activePlugin.activePump) // + "U");
|
||||
binding.fillPresetButton3.setOnClickListener { binding.fillInsulinamount.value = amount3 }
|
||||
} else {
|
||||
fill_preset_button3.visibility = View.GONE
|
||||
binding.fillPresetButton3.visibility = View.GONE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val insulin = SafeParse.stringToDouble(fill_insulinamount?.text ?: return false)
|
||||
if (_binding == null) return false
|
||||
val insulin = SafeParse.stringToDouble(binding.fillInsulinamount.text ?: return false)
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
|
||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
||||
|
@ -96,13 +109,13 @@ class FillDialog : DialogFragmentWithDate() {
|
|||
if (abs(insulinAfterConstraints - insulin) > 0.01)
|
||||
actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(resourceHelper, R.color.warning))
|
||||
}
|
||||
val siteChange = fill_catheter_change.isChecked
|
||||
val siteChange = binding.fillCatheterChange.isChecked
|
||||
if (siteChange)
|
||||
actions.add(resourceHelper.gs(R.string.record_pump_site_change).formatColor(resourceHelper, R.color.actionsConfirm))
|
||||
val insulinChange = fill_cartridge_change.isChecked
|
||||
val insulinChange = binding.fillCartridgeChange.isChecked
|
||||
if (insulinChange)
|
||||
actions.add(resourceHelper.gs(R.string.record_insulin_cartridge_change).formatColor(resourceHelper, R.color.actionsConfirm))
|
||||
val notes = notes.text.toString()
|
||||
val notes = binding.notesLayout.notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
eventTime -= eventTime % 1000
|
||||
|
@ -110,20 +123,20 @@ class FillDialog : DialogFragmentWithDate() {
|
|||
if (eventTimeChanged)
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
if (insulinAfterConstraints > 0 || fill_catheter_change.isChecked || fill_cartridge_change.isChecked) {
|
||||
if (insulinAfterConstraints > 0 || binding.fillCatheterChange.isChecked || binding.fillCartridgeChange.isChecked) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
if (insulinAfterConstraints > 0) {
|
||||
aapsLogger.debug("USER ENTRY: PRIME BOLUS $insulinAfterConstraints")
|
||||
uel.log("PRIME BOLUS", d1 = insulinAfterConstraints)
|
||||
requestPrimeBolus(insulinAfterConstraints, notes)
|
||||
}
|
||||
if (siteChange) {
|
||||
aapsLogger.debug("USER ENTRY: SITE CHANGE")
|
||||
uel.log("SITE CHANGE")
|
||||
nsUpload.generateCareportalEvent(CareportalEvent.SITECHANGE, eventTime, notes)
|
||||
}
|
||||
if (insulinChange) {
|
||||
// add a second for case of both checked
|
||||
aapsLogger.debug("USER ENTRY: INSULIN CHANGE")
|
||||
uel.log("INSULIN CHANGE")
|
||||
nsUpload.generateCareportalEvent(CareportalEvent.INSULINCHANGE, eventTime + 1000, notes)
|
||||
}
|
||||
}, null)
|
||||
|
@ -147,12 +160,7 @@ class FillDialog : DialogFragmentWithDate() {
|
|||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
ctx.startActivity(i)
|
||||
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
|
@ -15,14 +14,17 @@ 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.database.AppRepository
|
||||
import info.nightscout.androidaps.databinding.DialogInsulinBinding
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.db.TempTarget
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
|
@ -30,9 +32,6 @@ import info.nightscout.androidaps.utils.extensions.formatColor
|
|||
import info.nightscout.androidaps.utils.extensions.toSignedString
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_insulin.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
@ -40,6 +39,7 @@ import kotlin.math.abs
|
|||
import kotlin.math.max
|
||||
|
||||
class InsulinDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
|
@ -47,9 +47,12 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var repository: AppRepository
|
||||
@Inject lateinit var config: Config
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
companion object {
|
||||
|
||||
private const val PLUS1_DEFAULT = 0.5
|
||||
private const val PLUS2_DEFAULT = 1.0
|
||||
private const val PLUS3_DEFAULT = 2.0
|
||||
|
@ -64,78 +67,91 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
}
|
||||
|
||||
private var _binding: DialogInsulinBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private fun validateInputs() {
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
if (abs(overview_insulin_time.value.toInt()) > 12 * 60) {
|
||||
overview_insulin_time.value = 0.0
|
||||
if (abs(binding.time.value.toInt()) > 12 * 60) {
|
||||
binding.time.value = 0.0
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_insulin_amount.value > maxInsulin) {
|
||||
overview_insulin_amount.value = 0.0
|
||||
if (binding.amount.value > maxInsulin) {
|
||||
binding.amount.value = 0.0
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.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)
|
||||
savedInstanceState.putDouble("time", binding.time.value)
|
||||
savedInstanceState.putDouble("amount", binding.amount.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_insulin, container, false)
|
||||
_binding = DialogInsulinBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (config.NSCLIENT) {
|
||||
overview_insulin_record_only.isChecked = true
|
||||
overview_insulin_record_only.isEnabled = false
|
||||
binding.recordOnly.isChecked = true
|
||||
binding.recordOnly.isEnabled = false
|
||||
}
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
|
||||
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, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
|
||||
binding.time.setParams(savedInstanceState?.getDouble("time")
|
||||
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
|
||||
binding.amount.setParams(savedInstanceState?.getDouble("amount")
|
||||
?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
||||
|
||||
overview_insulin_plus05.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
overview_insulin_plus05.setOnClickListener {
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
binding.plus05.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
binding.plus05.setOnClickListener {
|
||||
binding.amount.value = max(0.0, binding.amount.value
|
||||
+ sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
overview_insulin_plus10.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
overview_insulin_plus10.setOnClickListener {
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
binding.plus10.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
binding.plus10.setOnClickListener {
|
||||
binding.amount.value = max(0.0, binding.amount.value
|
||||
+ sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
overview_insulin_plus20.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
overview_insulin_plus20.setOnClickListener {
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
binding.plus20.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
binding.plus20.setOnClickListener {
|
||||
binding.amount.value = max(0.0, binding.amount.value
|
||||
+ sp.getDouble(resourceHelper.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()
|
||||
binding.timeLayout.visibility = View.GONE
|
||||
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
|
||||
binding.timeLayout.visibility = isChecked.toVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
if (_binding == null) return false
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
val insulin = SafeParse.stringToDouble(overview_insulin_amount?.text ?: return false)
|
||||
val insulin = SafeParse.stringToDouble(binding.amount.text ?: return false)
|
||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val units = profileFunction.getUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
val recordOnlyChecked = overview_insulin_record_only.isChecked
|
||||
val eatingSoonChecked = overview_insulin_start_eating_soon_tt.isChecked
|
||||
val recordOnlyChecked = binding.recordOnly.isChecked
|
||||
val eatingSoonChecked = binding.startEatingSoonTt.isChecked
|
||||
|
||||
if (insulinAfterConstraints > 0) {
|
||||
actions.add(resourceHelper.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, resourceHelper).formatColor(resourceHelper, R.color.bolus))
|
||||
|
@ -149,20 +165,20 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
if (eatingSoonChecked)
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, eatingSoonTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
|
||||
val timeOffset = overview_insulin_time.value.toInt()
|
||||
val timeOffset = binding.time.value.toInt()
|
||||
val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs()
|
||||
if (timeOffset != 0)
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(time))
|
||||
|
||||
val notes = notes.text.toString()
|
||||
val notes = binding.notesLayout.notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
|
||||
if (insulinAfterConstraints > 0 || eatingSoonChecked) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
if (eatingSoonChecked) {
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
|
||||
uel.log("TT EATING SOON", d1 = eatingSoonTT, i1 = eatingSoonTTDuration)
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(eatingSoonTTDuration)
|
||||
|
@ -180,21 +196,16 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
detailedBolusInfo.source = Source.USER
|
||||
detailedBolusInfo.notes = notes
|
||||
if (recordOnlyChecked) {
|
||||
aapsLogger.debug("USER ENTRY: BOLUS RECORD ONLY $insulinAfterConstraints")
|
||||
uel.log("BOLUS RECORD", d1 = insulinAfterConstraints, i1 = timeOffset)
|
||||
detailedBolusInfo.date = time
|
||||
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
|
||||
} else {
|
||||
aapsLogger.debug("USER ENTRY: BOLUS $insulinAfterConstraints")
|
||||
uel.log("BOLUS", d1 = insulinAfterConstraints)
|
||||
detailedBolusInfo.date = DateUtil.now()
|
||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
ctx.startActivity(i)
|
||||
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -9,7 +10,6 @@ import android.view.Window
|
|||
import android.view.WindowManager
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import dagger.android.support.DaggerDialogFragment
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.databinding.DialogLoopBinding
|
||||
|
@ -17,8 +17,8 @@ import info.nightscout.androidaps.events.EventPreferenceChange
|
|||
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
|
@ -30,14 +30,12 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
|||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoopDialog : DaggerDialogFragment() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
|
@ -49,11 +47,12 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
|
||||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private var showOkCancel: Boolean = true
|
||||
private var _binding: DialogLoopBinding? = null
|
||||
private var loopHandler = Handler()
|
||||
private var refreshDialog: Runnable? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
|
@ -107,21 +106,33 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
// cancel button
|
||||
binding.cancel.setOnClickListener { dismiss() }
|
||||
|
||||
// bus
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventNewOpenLoopNotification::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
activity?.runOnUiThread { updateGUI("EventNewOpenLoopNotification") }
|
||||
}, fabricPrivacy::logException)
|
||||
)
|
||||
refreshDialog = Runnable {
|
||||
scheduleUpdateGUI("refreshDialog")
|
||||
loopHandler.postDelayed(refreshDialog, 15 * 1000L)
|
||||
}
|
||||
loopHandler.postDelayed(refreshDialog, 15 * 1000L)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
disposable.clear()
|
||||
_binding = null
|
||||
loopHandler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
|
||||
var task: Runnable? = null
|
||||
|
||||
private fun scheduleUpdateGUI(from: String) {
|
||||
class UpdateRunnable : Runnable {
|
||||
|
||||
override fun run() {
|
||||
updateGUI(from)
|
||||
task = null
|
||||
}
|
||||
}
|
||||
view?.removeCallbacks(task)
|
||||
task = UpdateRunnable()
|
||||
view?.postDelayed(task, 500)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -190,14 +201,14 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
|
||||
if (profile == null || profileStore == null) {
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofile))
|
||||
ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofile))
|
||||
dismiss()
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun onClickOkCancelEnabled(v: View): Boolean {
|
||||
private fun onClickOkCancelEnabled(v: View): Boolean {
|
||||
var description = ""
|
||||
when (v.id) {
|
||||
R.id.overview_closeloop -> description = resourceHelper.gs(R.string.closedloop)
|
||||
|
@ -229,25 +240,28 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
val profile = profileFunction.getProfile() ?: return true
|
||||
when (v.id) {
|
||||
R.id.overview_closeloop -> {
|
||||
uel.log("CLOSED LOOP MODE")
|
||||
sp.putString(R.string.key_aps_mode, "closed")
|
||||
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.closedloop)))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_lgsloop -> {
|
||||
uel.log("LGS LOOP MODE")
|
||||
sp.putString(R.string.key_aps_mode, "lgs")
|
||||
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_openloop -> {
|
||||
uel.log("OPEN LOOP MODE")
|
||||
sp.putString(R.string.key_aps_mode, "open")
|
||||
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_disable -> {
|
||||
aapsLogger.debug("USER ENTRY: LOOP DISABLED")
|
||||
uel.log("LOOP DISABLED")
|
||||
loopPlugin.setPluginEnabled(PluginType.LOOP, false)
|
||||
loopPlugin.setFragmentVisible(PluginType.LOOP, false)
|
||||
configBuilderPlugin.storeSettings("DisablingLoop")
|
||||
|
@ -255,7 +269,7 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
commandQueue.cancelTempBasal(true, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.tempbasaldeliveryerror))
|
||||
ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.tempbasaldeliveryerror))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -264,7 +278,7 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
}
|
||||
|
||||
R.id.overview_enable -> {
|
||||
aapsLogger.debug("USER ENTRY: LOOP ENABLED")
|
||||
uel.log("LOOP ENABLED")
|
||||
loopPlugin.setPluginEnabled(PluginType.LOOP, true)
|
||||
loopPlugin.setFragmentVisible(PluginType.LOOP, true)
|
||||
configBuilderPlugin.storeSettings("EnablingLoop")
|
||||
|
@ -274,18 +288,13 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
}
|
||||
|
||||
R.id.overview_resume, R.id.overview_reconnect -> {
|
||||
aapsLogger.debug("USER ENTRY: RESUME")
|
||||
uel.log("RESUME")
|
||||
loopPlugin.suspendTo(0L)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
commandQueue.cancelTempBasal(true, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(context, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context?.startActivity(i)
|
||||
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -295,49 +304,49 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
}
|
||||
|
||||
R.id.overview_suspend_1h -> {
|
||||
aapsLogger.debug("USER ENTRY: SUSPEND 1h")
|
||||
uel.log("SUSPEND 1h")
|
||||
loopPlugin.suspendLoop(60)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_suspend_2h -> {
|
||||
aapsLogger.debug("USER ENTRY: SUSPEND 2h")
|
||||
uel.log("SUSPEND 2h")
|
||||
loopPlugin.suspendLoop(120)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_suspend_3h -> {
|
||||
aapsLogger.debug("USER ENTRY: SUSPEND 3h")
|
||||
uel.log("SUSPEND 3h")
|
||||
loopPlugin.suspendLoop(180)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_suspend_10h -> {
|
||||
aapsLogger.debug("USER ENTRY: SUSPEND 10h")
|
||||
uel.log("SUSPEND 10h")
|
||||
loopPlugin.suspendLoop(600)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_disconnect_15m -> {
|
||||
aapsLogger.debug("USER ENTRY: DISCONNECT 15m")
|
||||
uel.log("DISCONNECT 15m")
|
||||
loopPlugin.disconnectPump(15, profile)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_disconnect_30m -> {
|
||||
aapsLogger.debug("USER ENTRY: DISCONNECT 30m")
|
||||
uel.log("DISCONNECT 30m")
|
||||
loopPlugin.disconnectPump(30, profile)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_disconnect_1h -> {
|
||||
aapsLogger.debug("USER ENTRY: DISCONNECT 1h")
|
||||
uel.log("DISCONNECT 1h")
|
||||
loopPlugin.disconnectPump(60, profile)
|
||||
sp.putBoolean(R.string.key_objectiveusedisconnect, true)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
|
@ -345,14 +354,14 @@ class LoopDialog : DaggerDialogFragment() {
|
|||
}
|
||||
|
||||
R.id.overview_disconnect_2h -> {
|
||||
aapsLogger.debug("USER ENTRY: DISCONNECT 2h")
|
||||
uel.log("DISCONNECT 2h")
|
||||
loopPlugin.disconnectPump(120, profile)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.overview_disconnect_3h -> {
|
||||
aapsLogger.debug("USER ENTRY: DISCONNECT 3h")
|
||||
uel.log("DISCONNECT 3h")
|
||||
loopPlugin.disconnectPump(180, profile)
|
||||
rxBus.send(EventRefreshOverview("suspendmenu"))
|
||||
return true
|
||||
|
|
|
@ -8,53 +8,61 @@ import android.widget.ArrayAdapter
|
|||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.DialogProfileswitchBinding
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_profileswitch.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
var profileIndex: Int? = null
|
||||
private var profileIndex: Int? = null
|
||||
|
||||
private var _binding: DialogProfileswitchBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
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)
|
||||
savedInstanceState.putDouble("duration", binding.duration.value)
|
||||
savedInstanceState.putDouble("percentage", binding.percentage.value)
|
||||
savedInstanceState.putDouble("timeshift", binding.timeshift.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
arguments?.let { bundle ->
|
||||
profileIndex = bundle.getInt("profileIndex", 0)
|
||||
}
|
||||
return inflater.inflate(R.layout.dialog_profileswitch, container, false)
|
||||
_binding = DialogProfileswitchBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
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(), 5.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)
|
||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
binding.percentage.setParams(savedInstanceState?.getDouble("percentage")
|
||||
?: 100.0, Constants.CPP_MIN_PERCENTAGE.toDouble(), Constants.CPP_MAX_PERCENTAGE.toDouble(), 5.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
binding.timeshift.setParams(savedInstanceState?.getDouble("timeshift")
|
||||
?: 0.0, Constants.CPP_MIN_TIMESHIFT.toDouble(), Constants.CPP_MAX_TIMESHIFT.toDouble(), 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
|
||||
// profile
|
||||
context?.let { context ->
|
||||
|
@ -62,55 +70,61 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
|||
?: return
|
||||
val profileList = profileStore.getProfileList()
|
||||
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
|
||||
overview_profileswitch_profile.adapter = adapter
|
||||
binding.profile.adapter = adapter
|
||||
// set selected to actual profile
|
||||
if (profileIndex != null)
|
||||
overview_profileswitch_profile.setSelection(profileIndex as Int)
|
||||
binding.profile.setSelection(profileIndex as Int)
|
||||
else
|
||||
for (p in profileList.indices)
|
||||
if (profileList[p] == profileFunction.getProfileName(false))
|
||||
overview_profileswitch_profile.setSelection(p)
|
||||
binding.profile.setSelection(p)
|
||||
} ?: return
|
||||
|
||||
treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now())?.let { ps ->
|
||||
if (ps.isCPP) {
|
||||
overview_profileswitch_reuselayout.visibility = View.VISIBLE
|
||||
overview_profileswitch_reusebutton.text = resourceHelper.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()
|
||||
binding.reuselayout.visibility = View.VISIBLE
|
||||
binding.reusebutton.text = resourceHelper.gs(R.string.reuse_profile_pct_hours, ps.percentage, ps.timeshift)
|
||||
binding.reusebutton.setOnClickListener {
|
||||
binding.percentage.value = ps.percentage.toDouble()
|
||||
binding.timeshift.value = ps.timeshift.toDouble()
|
||||
}
|
||||
} else {
|
||||
overview_profileswitch_reuselayout.visibility = View.GONE
|
||||
binding.reuselayout.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
if (_binding == null) return false
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
?: return false
|
||||
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val duration = overview_profileswitch_duration?.value?.toInt() ?: return false
|
||||
val duration = binding.duration.value?.toInt() ?: return false
|
||||
if (duration > 0)
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration))
|
||||
val profile = overview_profileswitch_profile.selectedItem.toString()
|
||||
val profile = binding.profile.selectedItem.toString()
|
||||
actions.add(resourceHelper.gs(R.string.profile) + ": " + profile)
|
||||
val percent = overview_profileswitch_percentage.value.toInt()
|
||||
val percent = binding.percentage.value.toInt()
|
||||
if (percent != 100)
|
||||
actions.add(resourceHelper.gs(R.string.percent) + ": " + percent + "%")
|
||||
val timeShift = overview_profileswitch_timeshift.value.toInt()
|
||||
val timeShift = binding.timeshift.value.toInt()
|
||||
if (timeShift != 0)
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_timeshift_label) + ": " + resourceHelper.gs(R.string.format_hours, timeShift.toDouble()))
|
||||
val notes = notes.text.toString()
|
||||
val notes = binding.notesLayout.notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
if (eventTimeChanged)
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: PROFILE SWITCH $profile percent: $percent timeshift: $timeShift duration: $duration")
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
uel.log("PROFILE SWITCH", d1 = percent.toDouble(), i1 = timeShift, i2 = duration)
|
||||
treatmentsPlugin.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -9,46 +8,55 @@ import android.view.ViewGroup
|
|||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.databinding.DialogTempbasalBinding
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_tempbasal.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class TempBasalDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private var isPercentPump = true
|
||||
|
||||
private var _binding: DialogTempbasalBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
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)
|
||||
savedInstanceState.putDouble("duration", binding.duration.value)
|
||||
savedInstanceState.putDouble("basalpercentinput", binding.basalpercentinput.value)
|
||||
savedInstanceState.putDouble("basalabsoluteinput", binding.basalabsoluteinput.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_tempbasal, container, false)
|
||||
_binding = DialogTempbasalBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@ -60,41 +68,47 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
|||
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)
|
||||
binding.basalpercentinput.setParams(savedInstanceState?.getDouble("basalpercentinput")
|
||||
?: 100.0, 0.0, maxTempPercent, tempPercentStep, DecimalFormat("0"), true, binding.okcancel.ok)
|
||||
|
||||
actions_tempbasal_basalabsoluteinput.setParams(savedInstanceState?.getDouble("actions_tempbasal_basalabsoluteinput")
|
||||
?: profile.basal, 0.0, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, DecimalFormat("0.00"), true, ok)
|
||||
binding.basalabsoluteinput.setParams(savedInstanceState?.getDouble("basalabsoluteinput")
|
||||
?: profile.basal, 0.0, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, DecimalFormat("0.00"), true, binding.okcancel.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)
|
||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||
?: tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, DecimalFormat("0"), false, binding.okcancel.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
|
||||
binding.percentLayout.visibility = View.VISIBLE
|
||||
binding.absoluteLayout.visibility = View.GONE
|
||||
} else {
|
||||
actions_tempbasal_percent_layout.visibility = View.GONE
|
||||
actions_tempbasal_absolute_layout.visibility = View.VISIBLE
|
||||
binding.percentLayout.visibility = View.GONE
|
||||
binding.absoluteLayout.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
if (_binding == null) return false
|
||||
var percent = 0
|
||||
var absolute = 0.0
|
||||
val durationInMinutes = actions_tempbasal_duration?.value?.toInt() ?: return false
|
||||
val durationInMinutes = binding.duration.value?.toInt() ?: return false
|
||||
val profile = profileFunction.getProfile() ?: return false
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
if (isPercentPump) {
|
||||
val basalPercentInput = SafeParse.stringToInt(actions_tempbasal_basalpercentinput.text)
|
||||
val basalPercentInput = SafeParse.stringToInt(binding.basalpercentinput.text)
|
||||
percent = constraintChecker.applyBasalPercentConstraints(Constraint(basalPercentInput), profile).value()
|
||||
actions.add(resourceHelper.gs(R.string.tempbasal_label) + ": $percent%")
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
|
||||
if (percent != basalPercentInput) actions.add(resourceHelper.gs(R.string.constraintapllied))
|
||||
} else {
|
||||
val basalAbsoluteInput = SafeParse.stringToDouble(actions_tempbasal_basalabsoluteinput.text)
|
||||
val basalAbsoluteInput = SafeParse.stringToDouble(binding.basalabsoluteinput.text)
|
||||
absolute = constraintChecker.applyBasalConstraints(Constraint(basalAbsoluteInput), profile).value()
|
||||
actions.add(resourceHelper.gs(R.string.tempbasal_label) + ": " + resourceHelper.gs(R.string.pump_basebasalrate, absolute))
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
|
||||
|
@ -102,24 +116,19 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
|||
actions.add(resourceHelper.gs(R.string.constraintapllied).formatColor(resourceHelper, R.color.warning))
|
||||
}
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
val callback: Callback = object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
ctx.startActivity(i)
|
||||
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPercentPump) {
|
||||
aapsLogger.debug("USER ENTRY: TEMP BASAL $percent% duration: $durationInMinutes")
|
||||
uel.log("TEMP BASAL", d1 = percent.toDouble(), i1 = durationInMinutes)
|
||||
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
|
||||
} else {
|
||||
aapsLogger.debug("USER ENTRY: TEMP BASAL $absolute duration: $durationInMinutes")
|
||||
uel.log("TEMP BASAL", d1 = absolute, i1 = durationInMinutes)
|
||||
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -4,77 +4,85 @@ 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.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.databinding.DialogTemptargetBinding
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.db.TempTarget
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_temptarget.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class TempTargetDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
lateinit var reasonList: List<String>
|
||||
private lateinit var reasonList: List<String>
|
||||
|
||||
private var _binding: DialogTemptargetBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
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)
|
||||
savedInstanceState.putDouble("duration", binding.duration.value)
|
||||
savedInstanceState.putDouble("temptarget", binding.temptarget.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_temptarget, container, false)
|
||||
_binding = DialogTemptargetBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
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)
|
||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
|
||||
if (profileFunction.getUnits() == 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)
|
||||
binding.temptarget.setParams(
|
||||
savedInstanceState?.getDouble("temptarget")
|
||||
?: 8.0,
|
||||
Constants.MIN_TT_MMOL, Constants.MAX_TT_MMOL, 0.1, DecimalFormat("0.0"), false, binding.okcancel.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)
|
||||
binding.temptarget.setParams(
|
||||
savedInstanceState?.getDouble("temptarget")
|
||||
?: 144.0,
|
||||
Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||
|
||||
val units = profileFunction.getUnits()
|
||||
overview_temptarget_units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
binding.units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
|
||||
// temp target
|
||||
context?.let { context ->
|
||||
if (activePlugin.activeTreatments.tempTargetFromHistory != null)
|
||||
overview_temptarget_cancel?.visibility = View.VISIBLE
|
||||
binding.targetCancel.visibility = View.VISIBLE
|
||||
else
|
||||
overview_temptarget_cancel?.visibility = View.GONE
|
||||
binding.targetCancel.visibility = View.GONE
|
||||
|
||||
reasonList = Lists.newArrayList(
|
||||
resourceHelper.gs(R.string.manual),
|
||||
|
@ -83,59 +91,67 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
|||
resourceHelper.gs(R.string.hypo)
|
||||
)
|
||||
val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList)
|
||||
overview_temptarget_reason.adapter = adapterReason
|
||||
binding.reason.adapter = adapterReason
|
||||
|
||||
overview_temptarget_cancel?.setOnClickListener { shortClick(it) }
|
||||
overview_temptarget_eating_soon?.setOnClickListener { shortClick(it) }
|
||||
overview_temptarget_activity?.setOnClickListener { shortClick(it) }
|
||||
overview_temptarget_hypo?.setOnClickListener { shortClick(it) }
|
||||
binding.targetCancel.setOnClickListener { shortClick(it) }
|
||||
binding.eatingSoon.setOnClickListener { shortClick(it) }
|
||||
binding.activity.setOnClickListener { shortClick(it) }
|
||||
binding.hypo.setOnClickListener { shortClick(it) }
|
||||
|
||||
overview_temptarget_eating_soon?.setOnLongClickListener {
|
||||
binding.eatingSoon.setOnLongClickListener {
|
||||
longClick(it)
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
overview_temptarget_activity?.setOnLongClickListener {
|
||||
binding.activity.setOnLongClickListener {
|
||||
longClick(it)
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
overview_temptarget_hypo?.setOnLongClickListener {
|
||||
binding.hypo.setOnLongClickListener {
|
||||
longClick(it)
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shortClick(v:View){
|
||||
private fun shortClick(v: View) {
|
||||
v.performLongClick()
|
||||
if (submit()) dismiss()
|
||||
}
|
||||
|
||||
private fun longClick(v:View) {
|
||||
private fun longClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.overview_temptarget_eating_soon -> {
|
||||
overview_temptarget_temptarget.value = defaultValueHelper.determineEatingSoonTT()
|
||||
overview_temptarget_duration.value = defaultValueHelper.determineEatingSoonTTDuration().toDouble()
|
||||
overview_temptarget_reason.setSelection(reasonList.indexOf( resourceHelper.gs(R.string.eatingsoon)))
|
||||
R.id.eating_soon -> {
|
||||
binding.temptarget.value = defaultValueHelper.determineEatingSoonTT()
|
||||
binding.duration.value = defaultValueHelper.determineEatingSoonTTDuration().toDouble()
|
||||
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.eatingsoon)))
|
||||
}
|
||||
R.id.overview_temptarget_activity -> {
|
||||
overview_temptarget_temptarget.value = defaultValueHelper.determineActivityTT()
|
||||
overview_temptarget_duration.value = defaultValueHelper.determineActivityTTDuration().toDouble()
|
||||
overview_temptarget_reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.activity)))
|
||||
|
||||
R.id.activity -> {
|
||||
binding.temptarget.value = defaultValueHelper.determineActivityTT()
|
||||
binding.duration.value = defaultValueHelper.determineActivityTTDuration().toDouble()
|
||||
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.activity)))
|
||||
}
|
||||
R.id.overview_temptarget_hypo -> {
|
||||
overview_temptarget_temptarget.value = defaultValueHelper.determineHypoTT()
|
||||
overview_temptarget_duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
|
||||
overview_temptarget_reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo)))
|
||||
|
||||
R.id.hypo -> {
|
||||
binding.temptarget.value = defaultValueHelper.determineHypoTT()
|
||||
binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
|
||||
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
if (_binding == null) return false
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val reason = overview_temptarget_reason?.selectedItem?.toString() ?: return false
|
||||
val reason = binding.reason.selectedItem?.toString() ?: return false
|
||||
val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||
val target = overview_temptarget_temptarget.value
|
||||
val duration = overview_temptarget_duration.value.toInt()
|
||||
val target = binding.temptarget.value
|
||||
val duration = binding.duration.value.toInt()
|
||||
if (target != 0.0 && duration != 0) {
|
||||
actions.add(resourceHelper.gs(R.string.reason) + ": " + reason)
|
||||
actions.add(resourceHelper.gs(R.string.target_label) + ": " + Profile.toCurrentUnitsString(profileFunction, target) + " " + resourceHelper.gs(unitResId))
|
||||
|
@ -147,8 +163,8 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
|||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: TEMP TARGET $target duration: $duration")
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
uel.log("TT", d1 = target, i1 = duration)
|
||||
if (target == 0.0 || duration == 0) {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
|
@ -13,35 +12,36 @@ import info.nightscout.androidaps.Config
|
|||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.databinding.DialogTreatmentBinding
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_insulin.*
|
||||
import kotlinx.android.synthetic.main.dialog_treatment.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class TreatmentDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var config: Config
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
|
@ -54,49 +54,62 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
|||
private fun validateInputs() {
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
if (SafeParse.stringToInt(overview_treatment_carbs.text) > maxCarbs) {
|
||||
overview_treatment_carbs.value = 0.0
|
||||
if (SafeParse.stringToInt(binding.carbs.text) > maxCarbs) {
|
||||
binding.carbs.value = 0.0
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.carbsconstraintapplied))
|
||||
}
|
||||
if (SafeParse.stringToDouble(overview_treatment_insulin.text) > maxInsulin) {
|
||||
overview_treatment_insulin.value = 0.0
|
||||
if (SafeParse.stringToDouble(binding.insulin.text) > maxInsulin) {
|
||||
binding.insulin.value = 0.0
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.bolusconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
private var _binding: DialogTreatmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
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)
|
||||
savedInstanceState.putDouble("carbs", binding.carbs.value)
|
||||
savedInstanceState.putDouble("insulin", binding.insulin.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
onCreateViewGeneral()
|
||||
return inflater.inflate(R.layout.dialog_treatment, container, false)
|
||||
_binding = DialogTreatmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (config.NSCLIENT) {
|
||||
overview_treatment_record_only.isChecked = true
|
||||
overview_treatment_record_only.isEnabled = false
|
||||
binding.recordOnly.isChecked = true
|
||||
binding.recordOnly.isEnabled = false
|
||||
}
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
overview_treatment_carbs.setParams(savedInstanceState?.getDouble("overview_treatment_carbs")
|
||||
?: 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(activePlugin.activePump), false, ok, textWatcher)
|
||||
binding.carbs.setParams(savedInstanceState?.getDouble("carbs")
|
||||
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
|
||||
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
|
||||
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
if (_binding == null) return false
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
val insulin = SafeParse.stringToDouble(overview_treatment_insulin?.text ?: return false)
|
||||
val carbs = SafeParse.stringToInt(overview_treatment_carbs.text)
|
||||
val recordOnlyChecked = overview_treatment_record_only.isChecked
|
||||
val insulin = SafeParse.stringToDouble(binding.insulin.text ?: return false)
|
||||
val carbs = SafeParse.stringToInt(binding.carbs.text)
|
||||
val recordOnlyChecked = binding.recordOnly.isChecked
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
||||
|
@ -115,8 +128,8 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: BOLUS insulin $insulin carbs: $carbs")
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||
uel.log("TREATMENT", d1 = insulin, i1 = carbs)
|
||||
val detailedBolusInfo = DetailedBolusInfo()
|
||||
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION
|
||||
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
|
||||
|
@ -128,12 +141,7 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
|||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
ctx.startActivity(i)
|
||||
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -13,12 +13,13 @@ import android.widget.AdapterView.OnItemSelectedListener
|
|||
import android.widget.ArrayAdapter
|
||||
import android.widget.CompoundButton
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import dagger.android.HasAndroidInjector
|
||||
import dagger.android.support.DaggerDialogFragment
|
||||
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.BgReading
|
||||
import info.nightscout.androidaps.databinding.DialogWizardBinding
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
|
@ -35,11 +36,11 @@ import info.nightscout.androidaps.utils.SafeParse
|
|||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import info.nightscout.androidaps.utils.valueToUnits
|
||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.dialog_wizard.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
@ -47,7 +48,9 @@ import kotlin.math.abs
|
|||
|
||||
class WizardDialog : DaggerDialogFragment() {
|
||||
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var sp: SP
|
||||
|
@ -72,8 +75,23 @@ class WizardDialog : DaggerDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private val timeTextWatcher = 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()
|
||||
binding.alarm.isChecked = binding.carbTimeInput.value > 0
|
||||
}
|
||||
}
|
||||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
private var _binding: DialogWizardBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
@ -81,49 +99,50 @@ class WizardDialog : DaggerDialogFragment() {
|
|||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("treatments_wizard_bg_input", treatments_wizard_bg_input.value)
|
||||
savedInstanceState.putDouble("treatments_wizard_carbs_input", treatments_wizard_carbs_input.value)
|
||||
savedInstanceState.putDouble("treatments_wizard_correction_input", treatments_wizard_correction_input.value)
|
||||
savedInstanceState.putDouble("treatments_wizard_carb_time_input", treatments_wizard_carb_time_input.value)
|
||||
savedInstanceState.putDouble("bg_input", binding.bgInput.value)
|
||||
savedInstanceState.putDouble("carbs_input", binding.carbsInput.value)
|
||||
savedInstanceState.putDouble("correction_input", binding.correctionInput.value)
|
||||
savedInstanceState.putDouble("carb_time_input", binding.carbTimeInput.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
isCancelable = true
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
|
||||
return inflater.inflate(R.layout.dialog_wizard, container, false)
|
||||
_binding = DialogWizardBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
loadCheckedStates()
|
||||
processCobCheckBox()
|
||||
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()
|
||||
binding.sbcheckbox.visibility = sp.getBoolean(R.string.key_usesuperbolus, false).toVisibility()
|
||||
binding.notesLayout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value()
|
||||
val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
|
||||
|
||||
if (profileFunction.getUnits() == Constants.MGDL)
|
||||
treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input")
|
||||
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input")
|
||||
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher)
|
||||
else
|
||||
treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input")
|
||||
?: 0.0, 0.0, 30.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)
|
||||
binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input")
|
||||
?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.ok, textWatcher)
|
||||
binding.carbsInput.setParams(savedInstanceState?.getDouble("carbs_input")
|
||||
?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.ok, textWatcher)
|
||||
val bolusStep = activePlugin.activePump.pumpDescription.bolusStep
|
||||
treatments_wizard_correction_input.setParams(savedInstanceState?.getDouble("treatments_wizard_correction_input")
|
||||
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
|
||||
treatments_wizard_carb_time_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carb_time_input")
|
||||
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
binding.correctionInput.setParams(savedInstanceState?.getDouble("correction_input")
|
||||
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.ok, textWatcher)
|
||||
binding.carbTimeInput.setParams(savedInstanceState?.getDouble("carb_time_input")
|
||||
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher)
|
||||
initDialog()
|
||||
|
||||
treatments_wizard_percent_used.text = resourceHelper.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
|
||||
binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
|
||||
// ok button
|
||||
ok.setOnClickListener {
|
||||
binding.ok.setOnClickListener {
|
||||
if (okClicked) {
|
||||
aapsLogger.debug(LTag.UI, "guarding: ok already clicked")
|
||||
} else {
|
||||
|
@ -136,46 +155,46 @@ class WizardDialog : DaggerDialogFragment() {
|
|||
dismiss()
|
||||
}
|
||||
// cancel button
|
||||
cancel.setOnClickListener { dismiss() }
|
||||
binding.cancel.setOnClickListener { dismiss() }
|
||||
// checkboxes
|
||||
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)
|
||||
binding.bgcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
binding.ttcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
binding.cobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
binding.basaliobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
binding.bolusiobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
binding.bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
binding.sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
|
||||
val showCalc = sp.getBoolean(R.string.key_wizard_calculation_visible, false)
|
||||
treatments_wizard_delimiter.visibility = showCalc.toVisibility()
|
||||
treatments_wizard_resulttable.visibility = showCalc.toVisibility()
|
||||
treatments_wizard_calculationcheckbox.isChecked = showCalc
|
||||
treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.delimiter.visibility = showCalc.toVisibility()
|
||||
binding.resulttable.visibility = showCalc.toVisibility()
|
||||
binding.calculationcheckbox.isChecked = showCalc
|
||||
binding.calculationcheckbox.setOnCheckedChangeListener { _, isChecked ->
|
||||
run {
|
||||
sp.putBoolean(resourceHelper.gs(R.string.key_wizard_calculation_visible), isChecked)
|
||||
treatments_wizard_delimiter.visibility = isChecked.toVisibility()
|
||||
treatments_wizard_resulttable.visibility = isChecked.toVisibility()
|
||||
binding.delimiter.visibility = isChecked.toVisibility()
|
||||
binding.resulttable.visibility = isChecked.toVisibility()
|
||||
}
|
||||
}
|
||||
// profile spinner
|
||||
treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener {
|
||||
binding.profile.onItemSelectedListener = object : OnItemSelectedListener {
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofileselected))
|
||||
ok.visibility = View.GONE
|
||||
binding.ok.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
calculateInsulin()
|
||||
ok.visibility = View.VISIBLE
|
||||
binding.ok.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
// bus
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
activity?.runOnUiThread { calculateInsulin() }
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
}, fabricPrivacy::logException)
|
||||
)
|
||||
|
||||
}
|
||||
|
@ -183,38 +202,43 @@ class WizardDialog : DaggerDialogFragment() {
|
|||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
disposable.clear()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
|
||||
saveCheckedStates()
|
||||
treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && treatmentsPlugin.tempTargetFromHistory != null
|
||||
if (buttonView.id == treatments_wizard_cobcheckbox.id)
|
||||
binding.ttcheckbox.isEnabled = binding.bgcheckbox.isChecked && treatmentsPlugin.tempTargetFromHistory != null
|
||||
if (buttonView.id == binding.cobcheckbox.id)
|
||||
processCobCheckBox()
|
||||
calculateInsulin()
|
||||
}
|
||||
|
||||
private fun processCobCheckBox() {
|
||||
if (treatments_wizard_cobcheckbox.isChecked) {
|
||||
treatments_wizard_bolusiobcheckbox.isEnabled = false
|
||||
treatments_wizard_basaliobcheckbox.isEnabled = false
|
||||
treatments_wizard_bolusiobcheckbox.isChecked = true
|
||||
treatments_wizard_basaliobcheckbox.isChecked = true
|
||||
if (binding.cobcheckbox.isChecked) {
|
||||
binding.bolusiobcheckbox.isEnabled = false
|
||||
binding.basaliobcheckbox.isEnabled = false
|
||||
binding.bolusiobcheckbox.isChecked = true
|
||||
binding.basaliobcheckbox.isChecked = true
|
||||
} else {
|
||||
treatments_wizard_bolusiobcheckbox.isEnabled = true
|
||||
treatments_wizard_basaliobcheckbox.isEnabled = true
|
||||
binding.bolusiobcheckbox.isEnabled = true
|
||||
binding.basaliobcheckbox.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveCheckedStates() {
|
||||
sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked)
|
||||
sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked)
|
||||
sp.putBoolean(R.string.key_wizard_include_cob, binding.cobcheckbox.isChecked)
|
||||
sp.putBoolean(R.string.key_wizard_include_trend_bg, binding.bgtrendcheckbox.isChecked)
|
||||
}
|
||||
|
||||
private fun loadCheckedStates() {
|
||||
treatments_wizard_bgtrendcheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_trend_bg, false)
|
||||
treatments_wizard_cobcheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_cob, false)
|
||||
binding.bgtrendcheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_trend_bg, false)
|
||||
binding.cobcheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_cob, false)
|
||||
}
|
||||
|
||||
private fun valueToUnitsToString(value: Double, units: String): String =
|
||||
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(value)
|
||||
else DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL)
|
||||
|
||||
private fun initDialog() {
|
||||
val profile = profileFunction.getProfile()
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
|
@ -225,30 +249,29 @@ class WizardDialog : DaggerDialogFragment() {
|
|||
return
|
||||
}
|
||||
|
||||
val profileList: ArrayList<CharSequence>
|
||||
profileList = profileStore.getProfileList()
|
||||
val profileList: ArrayList<CharSequence> = profileStore.getProfileList()
|
||||
profileList.add(0, resourceHelper.gs(R.string.active))
|
||||
context?.let { context ->
|
||||
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
|
||||
treatments_wizard_profile.adapter = adapter
|
||||
binding.profile.adapter = adapter
|
||||
} ?: return
|
||||
|
||||
val units = profileFunction.getUnits()
|
||||
treatments_wizard_bgunits.text = units
|
||||
binding.bgunits.text = units
|
||||
if (units == Constants.MGDL)
|
||||
treatments_wizard_bg_input.setStep(1.0)
|
||||
binding.bgInput.setStep(1.0)
|
||||
else
|
||||
treatments_wizard_bg_input.setStep(0.1)
|
||||
binding.bgInput.setStep(0.1)
|
||||
|
||||
// Set BG if not old
|
||||
val lastBg = iobCobCalculatorPlugin.actualBg()
|
||||
|
||||
if (lastBg != null) {
|
||||
treatments_wizard_bg_input.value = lastBg.valueToUnits(units)
|
||||
binding.bgInput.value = lastBg.valueToUnits(units)
|
||||
} else {
|
||||
treatments_wizard_bg_input.value = 0.0
|
||||
binding.bgInput.value = 0.0
|
||||
}
|
||||
treatments_wizard_ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null
|
||||
binding.ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null
|
||||
|
||||
// IOB calculation
|
||||
treatmentsPlugin.updateTotalIOBTreatments()
|
||||
|
@ -256,19 +279,19 @@ class WizardDialog : DaggerDialogFragment() {
|
|||
treatmentsPlugin.updateTotalIOBTempBasals()
|
||||
val basalIob = treatmentsPlugin.lastCalculationTempBasals.round()
|
||||
|
||||
treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob)
|
||||
treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob)
|
||||
binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob)
|
||||
binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob)
|
||||
|
||||
calculateInsulin()
|
||||
|
||||
treatments_wizard_percent_used.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility()
|
||||
binding.percentUsed.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility()
|
||||
}
|
||||
|
||||
private fun calculateInsulin() {
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
if (treatments_wizard_profile?.selectedItem == null || profileStore == null)
|
||||
if (binding.profile.selectedItem == null || profileStore == null)
|
||||
return // not initialized yet
|
||||
var profileName = treatments_wizard_profile.selectedItem.toString()
|
||||
var profileName = binding.profile.selectedItem.toString()
|
||||
val specificProfile: Profile?
|
||||
if (profileName == resourceHelper.gs(R.string.active)) {
|
||||
specificProfile = profileFunction.getProfile()
|
||||
|
@ -279,82 +302,83 @@ class WizardDialog : DaggerDialogFragment() {
|
|||
if (specificProfile == null) return
|
||||
|
||||
// Entered values
|
||||
var bg = SafeParse.stringToDouble(treatments_wizard_bg_input.text)
|
||||
val carbs = SafeParse.stringToInt(treatments_wizard_carbs_input.text)
|
||||
val correction = SafeParse.stringToDouble(treatments_wizard_correction_input.text)
|
||||
var bg = SafeParse.stringToDouble(binding.bgInput.text)
|
||||
val carbs = SafeParse.stringToInt(binding.carbsInput.text)
|
||||
val correction = SafeParse.stringToDouble(binding.correctionInput.text)
|
||||
val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
||||
if (abs(carbs - carbsAfterConstraint) > 0.01) {
|
||||
treatments_wizard_carbs_input.value = 0.0
|
||||
binding.carbsInput.value = 0.0
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied))
|
||||
return
|
||||
}
|
||||
|
||||
bg = if (treatments_wizard_bgcheckbox.isChecked) bg else 0.0
|
||||
val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) treatmentsPlugin.tempTargetFromHistory else null
|
||||
bg = if (binding.bgcheckbox.isChecked) bg else 0.0
|
||||
val tempTarget = if (binding.ttcheckbox.isChecked) treatmentsPlugin.tempTargetFromHistory else null
|
||||
|
||||
// COB
|
||||
var cob = 0.0
|
||||
if (treatments_wizard_cobcheckbox.isChecked) {
|
||||
if (binding.cobcheckbox.isChecked) {
|
||||
val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Wizard COB")
|
||||
cobInfo.displayCob?.let { cob = it }
|
||||
}
|
||||
|
||||
val carbTime = SafeParse.stringToInt(treatments_wizard_carb_time_input.text)
|
||||
val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text)
|
||||
|
||||
wizard = BolusWizard(mainApp).doCalc(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)
|
||||
binding.bgcheckbox.isChecked,
|
||||
binding.cobcheckbox.isChecked,
|
||||
binding.bolusiobcheckbox.isChecked,
|
||||
binding.basaliobcheckbox.isChecked,
|
||||
binding.sbcheckbox.isChecked,
|
||||
binding.ttcheckbox.isChecked,
|
||||
binding.bgtrendcheckbox.isChecked,
|
||||
binding.alarm.isChecked,
|
||||
binding.notes.text.toString(), carbTime)
|
||||
|
||||
wizard?.let { wizard ->
|
||||
treatments_wizard_bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens)
|
||||
treatments_wizard_bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
|
||||
binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits()), wizard.sens)
|
||||
binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
|
||||
|
||||
treatments_wizard_carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)
|
||||
treatments_wizard_carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs)
|
||||
binding.carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)
|
||||
binding.carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs)
|
||||
|
||||
treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB)
|
||||
treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBasalsIOB)
|
||||
binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB)
|
||||
binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBasalIOB)
|
||||
|
||||
treatments_wizard_correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCorrection)
|
||||
binding.correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCorrection)
|
||||
|
||||
// Superbolus
|
||||
treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) resourceHelper.gs(R.string.twohours) else ""
|
||||
treatments_wizard_sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromSuperBolus)
|
||||
binding.sb.text = if (binding.sbcheckbox.isChecked) resourceHelper.gs(R.string.twohours) else ""
|
||||
binding.sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromSuperBolus)
|
||||
|
||||
// Trend
|
||||
if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) {
|
||||
treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "")
|
||||
if (binding.bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) {
|
||||
binding.bgtrend.text = ((if (wizard.trend > 0) "+" else "")
|
||||
+ Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, profileFunction.getUnits())
|
||||
+ " " + profileFunction.getUnits())
|
||||
} else {
|
||||
treatments_wizard_bgtrend.text = ""
|
||||
binding.bgtrend.text = ""
|
||||
}
|
||||
treatments_wizard_bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromTrend)
|
||||
binding.bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromTrend)
|
||||
|
||||
// COB
|
||||
if (treatments_wizard_cobcheckbox.isChecked) {
|
||||
treatments_wizard_cob.text = String.format(resourceHelper.gs(R.string.format_cob_ic), cob, wizard.ic)
|
||||
treatments_wizard_cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCOB)
|
||||
if (binding.cobcheckbox.isChecked) {
|
||||
binding.cob.text = String.format(resourceHelper.gs(R.string.format_cob_ic), cob, wizard.ic)
|
||||
binding.cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCOB)
|
||||
} else {
|
||||
treatments_wizard_cob.text = ""
|
||||
treatments_wizard_cobinsulin.text = ""
|
||||
binding.cob.text = ""
|
||||
binding.cobinsulin.text = ""
|
||||
}
|
||||
|
||||
if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) {
|
||||
val insulinText = if (wizard.calculatedTotalInsulin > 0.0) resourceHelper.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin) else ""
|
||||
val carbsText = if (carbsAfterConstraint > 0.0) resourceHelper.gs(R.string.format_carbs, carbsAfterConstraint) else ""
|
||||
treatments_wizard_total.text = resourceHelper.gs(R.string.result_insulin_carbs, insulinText, carbsText)
|
||||
ok.visibility = View.VISIBLE
|
||||
binding.total.text = resourceHelper.gs(R.string.result_insulin_carbs, insulinText, carbsText)
|
||||
binding.ok.visibility = View.VISIBLE
|
||||
} else {
|
||||
treatments_wizard_total.text = resourceHelper.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt())
|
||||
ok.visibility = View.INVISIBLE
|
||||
binding.total.text = resourceHelper.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt())
|
||||
binding.ok.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,15 +9,16 @@ import android.view.WindowManager
|
|||
import dagger.android.support.DaggerDialogFragment
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.DialogWizardinfoBinding
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_wizardinfo.*
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
|
||||
class WizardInfoDialog : DaggerDialogFragment() {
|
||||
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
|
||||
|
@ -27,62 +28,74 @@ class WizardInfoDialog : DaggerDialogFragment() {
|
|||
this.json = json
|
||||
}
|
||||
|
||||
private var _binding: DialogWizardinfoBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
isCancelable = true
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
return inflater.inflate(R.layout.dialog_wizardinfo, container, false)
|
||||
_binding = DialogWizardinfoBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
close.setOnClickListener { dismiss() }
|
||||
binding.close.setOnClickListener { dismiss() }
|
||||
val units = profileFunction.getUnits()
|
||||
val bgString =
|
||||
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "bg"))
|
||||
else DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg"))
|
||||
// BG
|
||||
treatments_wizard_bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, JsonHelper.safeGetDouble(json, "isf"))
|
||||
treatments_wizard_bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinbg"))
|
||||
treatments_wizard_bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused")
|
||||
treatments_wizard_ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused")
|
||||
binding.bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, JsonHelper.safeGetDouble(json, "isf"))
|
||||
binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinbg"))
|
||||
binding.bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused")
|
||||
binding.ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused")
|
||||
// Trend
|
||||
treatments_wizard_bgtrend.text = JsonHelper.safeGetString(json, "trend")
|
||||
treatments_wizard_bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulintrend"))
|
||||
treatments_wizard_bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused")
|
||||
binding.bgtrend.text = JsonHelper.safeGetString(json, "trend")
|
||||
binding.bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulintrend"))
|
||||
binding.bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused")
|
||||
// COB
|
||||
treatments_wizard_cob.text = resourceHelper.gs(R.string.format_cob_ic, JsonHelper.safeGetDouble(json, "cob"), JsonHelper.safeGetDouble(json, "ic"))
|
||||
treatments_wizard_cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincob"))
|
||||
treatments_wizard_cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused")
|
||||
binding.cob.text = resourceHelper.gs(R.string.format_cob_ic, JsonHelper.safeGetDouble(json, "cob"), JsonHelper.safeGetDouble(json, "ic"))
|
||||
binding.cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincob"))
|
||||
binding.cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused")
|
||||
// Bolus IOB
|
||||
treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "bolusiob"))
|
||||
treatments_wizard_bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused")
|
||||
binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "bolusiob"))
|
||||
binding.bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused")
|
||||
// Basal IOB
|
||||
treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "basaliob"))
|
||||
treatments_wizard_basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused")
|
||||
binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "basaliob"))
|
||||
binding.basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused")
|
||||
// Superbolus
|
||||
treatments_wizard_sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinsuperbolus"))
|
||||
treatments_wizard_sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused")
|
||||
binding.sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinsuperbolus"))
|
||||
binding.sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused")
|
||||
// Carbs
|
||||
treatments_wizard_carbs.text = resourceHelper.gs(R.string.format_carbs_ic, JsonHelper.safeGetDouble(json, "carbs"), JsonHelper.safeGetDouble(json, "ic"))
|
||||
treatments_wizard_carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincarbs"))
|
||||
binding.carbs.text = resourceHelper.gs(R.string.format_carbs_ic, JsonHelper.safeGetDouble(json, "carbs"), JsonHelper.safeGetDouble(json, "ic"))
|
||||
binding.carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincarbs"))
|
||||
// Correction
|
||||
treatments_wizard_correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "othercorrection"))
|
||||
binding.correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "othercorrection"))
|
||||
// Profile
|
||||
treatments_wizard_profile.text = JsonHelper.safeGetString(json, "profile")
|
||||
binding.profile.text = JsonHelper.safeGetString(json, "profile")
|
||||
// Notes
|
||||
treatments_wizard_notes.text = JsonHelper.safeGetString(json, "notes")
|
||||
binding.notes.text = JsonHelper.safeGetString(json, "notes")
|
||||
// Percentage
|
||||
treatments_wizard_percent_used.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "percentageCorrection", 100.0)) + "%"
|
||||
binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, (JsonHelper.safeGetInt(json, "percentageCorrection", 100)))
|
||||
// Total
|
||||
treatments_wizard_totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulin"))
|
||||
binding.totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulin"))
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import info.nightscout.androidaps.db.BgReading
|
||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||
|
||||
class EventNewBG(val bgReading: BgReading?) : EventLoop()
|
||||
class EventNewBG(val glucoseValue: GlucoseValue?) : EventLoop()
|
|
@ -13,6 +13,7 @@ import com.jjoe64.graphview.GraphView
|
|||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||
import info.nightscout.androidaps.databinding.ActivityHistorybrowseBinding
|
||||
import info.nightscout.androidaps.events.EventCustomCalculationFinished
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
|
@ -31,12 +32,9 @@ import info.nightscout.androidaps.utils.FabricPrivacy
|
|||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.activity_historybrowse.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -44,11 +42,12 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
|
||||
class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory
|
||||
|
@ -68,21 +67,27 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
private var rangeToDisplay = 24 // for graph
|
||||
private var start: Long = 0
|
||||
|
||||
private val graphLock = Object()
|
||||
|
||||
private var eventCustomCalculationFinished = EventCustomCalculationFinished()
|
||||
|
||||
private lateinit var binding: ActivityHistorybrowseBinding
|
||||
private var destroyed = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_historybrowse)
|
||||
binding = ActivityHistorybrowseBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
historybrowse_left.setOnClickListener {
|
||||
binding.left.setOnClickListener {
|
||||
start -= T.hours(rangeToDisplay.toLong()).msecs()
|
||||
runCalculation("onClickLeft")
|
||||
}
|
||||
historybrowse_right.setOnClickListener {
|
||||
binding.right.setOnClickListener {
|
||||
start += T.hours(rangeToDisplay.toLong()).msecs()
|
||||
runCalculation("onClickRight")
|
||||
}
|
||||
historybrowse_end.setOnClickListener {
|
||||
binding.end.setOnClickListener {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = System.currentTimeMillis()
|
||||
calendar[Calendar.MILLISECOND] = 0
|
||||
|
@ -92,12 +97,12 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
start = calendar.timeInMillis
|
||||
runCalculation("onClickEnd")
|
||||
}
|
||||
historybrowse_zoom.setOnClickListener {
|
||||
binding.zoom.setOnClickListener {
|
||||
rangeToDisplay += 6
|
||||
rangeToDisplay = if (rangeToDisplay > 24) 6 else rangeToDisplay
|
||||
updateGUI("rangeChange", false)
|
||||
}
|
||||
historybrowse_zoom.setOnLongClickListener {
|
||||
binding.zoom.setOnLongClickListener {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = start
|
||||
calendar[Calendar.MILLISECOND] = 0
|
||||
|
@ -121,11 +126,11 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
cal[Calendar.MINUTE] = 0
|
||||
cal[Calendar.HOUR_OF_DAY] = 0
|
||||
start = cal.timeInMillis
|
||||
historybrowse_date?.text = dateUtil.dateAndTimeString(start)
|
||||
binding.date.text = dateUtil.dateAndTimeString(start)
|
||||
runCalculation("onClickDate")
|
||||
}
|
||||
|
||||
historybrowse_date.setOnClickListener {
|
||||
binding.date.setOnClickListener {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = start
|
||||
DatePickerDialog(this, dateSetListener,
|
||||
|
@ -139,12 +144,12 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
windowManager?.defaultDisplay?.getMetrics(dm)
|
||||
|
||||
axisWidth = if (dm.densityDpi <= 120) 3 else if (dm.densityDpi <= 160) 10 else if (dm.densityDpi <= 320) 35 else if (dm.densityDpi <= 420) 50 else if (dm.densityDpi <= 560) 70 else 80
|
||||
historybrowse_bggraph?.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid)
|
||||
historybrowse_bggraph?.gridLabelRenderer?.reloadStyles()
|
||||
historybrowse_bggraph?.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||
binding.bggraph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid)
|
||||
binding.bggraph.gridLabelRenderer?.reloadStyles()
|
||||
binding.bggraph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||
|
||||
overviewMenus.setupChartMenu(overview_chartMenuButton)
|
||||
prepareGraphs()
|
||||
overviewMenus.setupChartMenu(binding.chartMenuButton)
|
||||
prepareGraphsIfNeeded(overviewMenus.setting.size)
|
||||
savedInstanceState?.let { bundle ->
|
||||
rangeToDisplay = bundle.getInt("rangeToDisplay", 0)
|
||||
start = bundle.getLong("start", 0)
|
||||
|
@ -158,42 +163,47 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
iobCobCalculatorPluginHistory.stopCalculation("onPause")
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onDestroy() {
|
||||
destroyed = true
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
// catch only events from iobCobCalculatorPluginHistory
|
||||
if (it.cause is EventCustomCalculationFinished) {
|
||||
updateGUI("EventAutosensCalculationFinished", bgOnly = false)
|
||||
}
|
||||
}, fabricPrivacy::logException )
|
||||
}, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensBgLoaded::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({
|
||||
// catch only events from iobCobCalculatorPluginHistory
|
||||
if (it.cause is EventCustomCalculationFinished) {
|
||||
updateGUI("EventAutosensCalculationFinished", bgOnly = true)
|
||||
}
|
||||
}, fabricPrivacy::logException )
|
||||
}, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventIobCalculationProgress::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ overview_iobcalculationprogess?.text = it.progress }, fabricPrivacy::logException )
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({ binding.overviewIobcalculationprogess.text = it.progress }, fabricPrivacy::logException)
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventRefreshOverview::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
if (it.now) {
|
||||
prepareGraphs()
|
||||
updateGUI("EventRefreshOverview", bgOnly = false)
|
||||
}
|
||||
}, fabricPrivacy::logException )
|
||||
}, fabricPrivacy::logException)
|
||||
)
|
||||
if (start == 0L) {
|
||||
// set start of current day
|
||||
|
@ -217,42 +227,41 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
|
||||
}
|
||||
|
||||
private fun prepareGraphs() {
|
||||
val numOfGraphs = overviewMenus.setting.size
|
||||
private fun prepareGraphsIfNeeded(numOfGraphs: Int) {
|
||||
synchronized(graphLock) {
|
||||
if (numOfGraphs != secondaryGraphs.size - 1) {
|
||||
//aapsLogger.debug("New secondary graph count ${numOfGraphs-1}")
|
||||
// rebuild needed
|
||||
secondaryGraphs.clear()
|
||||
secondaryGraphsLabel.clear()
|
||||
binding.iobGraph.removeAllViews()
|
||||
for (i in 1 until numOfGraphs) {
|
||||
val relativeLayout = RelativeLayout(this)
|
||||
relativeLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
if (numOfGraphs != secondaryGraphs.size - 1) {
|
||||
//aapsLogger.debug("New secondary graph count ${numOfGraphs-1}")
|
||||
// rebuild needed
|
||||
secondaryGraphs.clear()
|
||||
secondaryGraphsLabel.clear()
|
||||
history_iobgraph.removeAllViews()
|
||||
for (i in 1 until numOfGraphs) {
|
||||
val relativeLayout = RelativeLayout(this)
|
||||
relativeLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
val graph = GraphView(this)
|
||||
graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resourceHelper.dpToPx(100)).also { it.setMargins(0, resourceHelper.dpToPx(15), 0, resourceHelper.dpToPx(10)) }
|
||||
graph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid)
|
||||
graph.gridLabelRenderer?.reloadStyles()
|
||||
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
|
||||
graph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||
graph.gridLabelRenderer?.numVerticalLabels = 3
|
||||
graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray
|
||||
relativeLayout.addView(graph)
|
||||
|
||||
val graph = GraphView(this)
|
||||
graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resourceHelper.dpToPx(100)).also { it.setMargins(0, resourceHelper.dpToPx(15), 0, resourceHelper.dpToPx(10)) }
|
||||
graph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid)
|
||||
graph.gridLabelRenderer?.reloadStyles()
|
||||
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
|
||||
graph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||
graph.gridLabelRenderer?.numVerticalLabels = 3
|
||||
graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray
|
||||
relativeLayout.addView(graph)
|
||||
val label = TextView(this)
|
||||
val layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { it.setMargins(resourceHelper.dpToPx(30), resourceHelper.dpToPx(25), 0, 0) }
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP)
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
|
||||
label.layoutParams = layoutParams
|
||||
relativeLayout.addView(label)
|
||||
secondaryGraphsLabel.add(label)
|
||||
|
||||
val label = TextView(this)
|
||||
val layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { it.setMargins(resourceHelper.dpToPx(30), resourceHelper.dpToPx(25), 0, 0) }
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP)
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
|
||||
label.layoutParams = layoutParams
|
||||
relativeLayout.addView(label)
|
||||
secondaryGraphsLabel.add(label)
|
||||
|
||||
history_iobgraph.addView(relativeLayout)
|
||||
secondaryGraphs.add(graph)
|
||||
binding.iobGraph.addView(relativeLayout)
|
||||
secondaryGraphs.add(graph)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun runCalculation(from: String) {
|
||||
|
@ -265,7 +274,10 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun updateGUI(from: String, bgOnly: Boolean) {
|
||||
val menuChartSettings = overviewMenus.setting
|
||||
prepareGraphsIfNeeded(menuChartSettings.size)
|
||||
aapsLogger.debug(LTag.UI, "updateGUI from: $from")
|
||||
val pump = activePlugin.activePump
|
||||
val profile = profileFunction.getProfile()
|
||||
|
@ -274,13 +286,13 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
val highLine = defaultValueHelper.determineHighLine()
|
||||
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
historybrowse_noprofile?.visibility = (profile == null).toVisibility()
|
||||
binding.noprofile.visibility = (profile == null).toVisibility()
|
||||
profile ?: return@launch
|
||||
|
||||
historybrowse_bggraph ?: return@launch
|
||||
historybrowse_date?.text = dateUtil.dateAndTimeString(start)
|
||||
historybrowse_zoom?.text = rangeToDisplay.toString()
|
||||
val graphData = GraphData(injector, historybrowse_bggraph, iobCobCalculatorPluginHistory, treatmentsPluginHistory)
|
||||
if (destroyed) return@launch
|
||||
binding.date.text = dateUtil.dateAndTimeString(start)
|
||||
binding.zoom.text = rangeToDisplay.toString()
|
||||
val graphData = GraphData(injector, binding.bggraph, iobCobCalculatorPluginHistory, treatmentsPluginHistory)
|
||||
val secondaryGraphsData: ArrayList<GraphData> = ArrayList()
|
||||
|
||||
// do preparation in different thread
|
||||
|
@ -296,9 +308,6 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
// **** BG ****
|
||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
graphData.formatAxis(fromTime, toTime)
|
||||
|
||||
// add target line
|
||||
graphData.addTargetLine(fromTime, toTime, profile, null)
|
||||
|
||||
|
@ -308,63 +317,74 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
|||
if (!bgOnly) {
|
||||
// Treatments
|
||||
graphData.addTreatments(fromTime, toTime)
|
||||
if (overviewMenus.setting[0][OverviewMenus.CharType.ACT.ordinal])
|
||||
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
|
||||
graphData.addActivity(fromTime, toTime, false, 0.8)
|
||||
|
||||
// add basal data
|
||||
if (pump.pumpDescription.isTempBasalCapable && overviewMenus.setting[0][OverviewMenus.CharType.BAS.ordinal]) {
|
||||
if (pump.pumpDescription.isTempBasalCapable && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal]) {
|
||||
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2)
|
||||
}
|
||||
// ------------------ 2nd graph
|
||||
for (g in 0 until secondaryGraphs.size) {
|
||||
val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPluginHistory, treatmentsPluginHistory)
|
||||
var useIobForScale = false
|
||||
var useCobForScale = false
|
||||
var useDevForScale = false
|
||||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useIAForScale = false
|
||||
var useABSForScale = false
|
||||
when {
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
synchronized(graphLock) {
|
||||
for (g in 0 until secondaryGraphs.size) {
|
||||
val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPluginHistory, treatmentsPluginHistory)
|
||||
var useIobForScale = false
|
||||
var useCobForScale = false
|
||||
var useDevForScale = false
|
||||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useBGIForScale = false
|
||||
var useABSForScale = false
|
||||
when {
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
}
|
||||
|
||||
var alignIobScale = menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]
|
||||
var alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
|
||||
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal], alignIobScale)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0, alignDevBgiScale)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]) secondGraphData.addMinusBGI(fromTime, toTime, useBGIForScale, if (alignDevBgiScale) 1.0 else 0.8, alignDevBgiScale)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(fromTime, toTime)
|
||||
secondGraphData.addNowLine(pointer)
|
||||
secondaryGraphsData.add(secondGraphData)
|
||||
}
|
||||
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, overviewMenus.setting[g + 1][OverviewMenus.CharType.PRE.ordinal])
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(fromTime, toTime)
|
||||
secondGraphData.addNowLine(pointer)
|
||||
secondaryGraphsData.add(secondGraphData)
|
||||
}
|
||||
}
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
graphData.setNumVerticalLables()
|
||||
graphData.formatAxis(fromTime, toTime)
|
||||
}
|
||||
// finally enforce drawing of graphs in UI thread
|
||||
graphData.performUpdate()
|
||||
if (!bgOnly)
|
||||
for (g in 0 until secondaryGraphs.size) {
|
||||
secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1)
|
||||
secondaryGraphs[g].visibility = (!bgOnly && (
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
|
||||
)).toVisibility()
|
||||
secondaryGraphsData[g].performUpdate()
|
||||
synchronized(graphLock) {
|
||||
for (g in 0 until secondaryGraphs.size) {
|
||||
secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1)
|
||||
secondaryGraphs[g].visibility = (!bgOnly && (
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
|
||||
)).toVisibility()
|
||||
secondaryGraphsData[g].performUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.historyBrowser
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.database.AppRepository
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
|
@ -12,6 +13,7 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAverage
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -20,6 +22,7 @@ import javax.inject.Singleton
|
|||
class IobCobCalculatorPluginHistory @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
aapsSchedulers: AapsSchedulers,
|
||||
rxBus: RxBusWrapper,
|
||||
sp: SP,
|
||||
resourceHelper: ResourceHelper,
|
||||
|
@ -30,9 +33,10 @@ class IobCobCalculatorPluginHistory @Inject constructor(
|
|||
sensitivityAAPSPlugin: SensitivityAAPSPlugin,
|
||||
sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin,
|
||||
fabricPrivacy: FabricPrivacy,
|
||||
dateUtil: DateUtil
|
||||
) : IobCobCalculatorPlugin(injector, aapsLogger, rxBus, sp, resourceHelper, profileFunction,
|
||||
activePlugin, treatmentsPluginHistory, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil) {
|
||||
dateUtil: DateUtil,
|
||||
repository: AppRepository
|
||||
) : IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction,
|
||||
activePlugin, treatmentsPluginHistory, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) {
|
||||
|
||||
override fun onStart() { // do not attach to rxbus
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -21,6 +22,7 @@ import javax.inject.Singleton
|
|||
class TreatmentsPluginHistory @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
aapsSchedulers: AapsSchedulers,
|
||||
rxBus: RxBusWrapper,
|
||||
resourceHelper: ResourceHelper,
|
||||
context: Context,
|
||||
|
@ -31,7 +33,7 @@ class TreatmentsPluginHistory @Inject constructor(
|
|||
fabricPrivacy: FabricPrivacy,
|
||||
dateUtil: DateUtil,
|
||||
uploadQueue: UploadQueue
|
||||
) : TreatmentsPlugin(injector, aapsLogger, rxBus, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue) {
|
||||
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue) {
|
||||
|
||||
init {
|
||||
onStart()
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.logger;
|
||||
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import info.nightscout.androidaps.db.StaticInjector;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
|
||||
/**
|
||||
* Created by adrian on 15/10/17.
|
||||
*/
|
||||
|
||||
|
||||
public class LoggerCallback extends ScriptableObject {
|
||||
|
||||
@Inject
|
||||
AAPSLogger aapsLogger;
|
||||
|
||||
private static StringBuffer errorBuffer = new StringBuffer();
|
||||
private static StringBuffer logBuffer = new StringBuffer();
|
||||
|
||||
|
||||
public LoggerCallback() {
|
||||
//empty constructor needed for Rhino
|
||||
errorBuffer = new StringBuffer();
|
||||
logBuffer = new StringBuffer();
|
||||
StaticInjector.Companion.getInstance().androidInjector().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return "LoggerCallback";
|
||||
}
|
||||
|
||||
public void jsConstructor() {
|
||||
//empty constructor on JS site; could work as setter
|
||||
}
|
||||
|
||||
public void jsFunction_log(Object obj1) {
|
||||
aapsLogger.debug(LTag.APS, obj1.toString().trim());
|
||||
logBuffer.append(obj1.toString());
|
||||
}
|
||||
|
||||
public void jsFunction_error(Object obj1) {
|
||||
aapsLogger.error(LTag.APS, obj1.toString().trim());
|
||||
errorBuffer.append(obj1.toString());
|
||||
}
|
||||
|
||||
|
||||
public static String getScriptDebug() {
|
||||
String ret = "";
|
||||
if (errorBuffer.length() > 0) {
|
||||
ret += "e:\n" + errorBuffer.toString();
|
||||
}
|
||||
if (ret.length() > 0 && logBuffer.length() > 0) ret += '\n';
|
||||
if (logBuffer.length() > 0) {
|
||||
ret += "d:\n" + logBuffer.toString();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package info.nightscout.androidaps.plugins.aps.logger
|
||||
|
||||
import info.nightscout.androidaps.db.StaticInjector
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import org.mozilla.javascript.ScriptableObject
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("unused", "FunctionName")
|
||||
class LoggerCallback : ScriptableObject() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
|
||||
override fun getClassName(): String = "LoggerCallback"
|
||||
|
||||
fun jsConstructor() {
|
||||
//empty constructor on JS site; could work as setter
|
||||
}
|
||||
|
||||
fun jsFunction_log(obj1: Any) {
|
||||
aapsLogger.debug(LTag.APS, obj1.toString().trim { it <= ' ' })
|
||||
logBuffer.append(obj1.toString())
|
||||
}
|
||||
|
||||
fun jsFunction_error(obj1: Any) {
|
||||
aapsLogger.error(LTag.APS, obj1.toString().trim { it <= ' ' })
|
||||
errorBuffer.append(obj1.toString())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private var errorBuffer = StringBuffer()
|
||||
private var logBuffer = StringBuffer()
|
||||
val scriptDebug: String
|
||||
get() {
|
||||
var ret = ""
|
||||
if (errorBuffer.isNotEmpty()) {
|
||||
ret += """
|
||||
e:
|
||||
$errorBuffer
|
||||
""".trimIndent()
|
||||
}
|
||||
if (ret.isNotEmpty() && logBuffer.isNotEmpty()) ret += '\n'
|
||||
if (logBuffer.isNotEmpty()) {
|
||||
ret += """
|
||||
d:
|
||||
$logBuffer
|
||||
""".trimIndent()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
//empty constructor needed for Rhino
|
||||
errorBuffer = StringBuffer()
|
||||
logBuffer = StringBuffer()
|
||||
@Suppress("DEPRECATION")
|
||||
StaticInjector.Companion.getInstance().androidInjector().inject(this)
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import dagger.android.support.DaggerFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.LoopFragmentBinding
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
|
||||
|
@ -14,16 +15,17 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.loop_fragment.*
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoopFragment : DaggerFragment() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
|
@ -33,16 +35,23 @@ class LoopFragment : DaggerFragment() {
|
|||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
private var _binding: LoopFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.loop_fragment, container, false)
|
||||
savedInstanceState: Bundle?): View {
|
||||
_binding = LoopFragmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
loop_run.setOnClickListener {
|
||||
loop_lastrun.text = resourceHelper.gs(R.string.executing)
|
||||
binding.run.setOnClickListener {
|
||||
binding.lastrun.text = resourceHelper.gs(R.string.executing)
|
||||
Thread { loopPlugin.invoke("Loop button", true) }.start()
|
||||
}
|
||||
}
|
||||
|
@ -52,18 +61,18 @@ class LoopFragment : DaggerFragment() {
|
|||
super.onResume()
|
||||
disposable += rxBus
|
||||
.toObservable(EventLoopUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
updateGUI()
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
}, fabricPrivacy::logException)
|
||||
|
||||
disposable += rxBus
|
||||
.toObservable(EventLoopSetLastRunGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
clearGUI()
|
||||
loop_lastrun?.text = it.text
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
binding.lastrun.text = it.text
|
||||
}, fabricPrivacy::logException)
|
||||
|
||||
updateGUI()
|
||||
sp.putBoolean(R.string.key_objectiveuseloop, true)
|
||||
|
@ -76,22 +85,28 @@ class LoopFragment : DaggerFragment() {
|
|||
}
|
||||
|
||||
@Synchronized
|
||||
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 = dateUtil.dateAndTimeString(it.lastAPSRun)
|
||||
?: ""
|
||||
loop_smbrequest_time?.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBRequest)
|
||||
loop_smbexecution_time?.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBEnact)
|
||||
loop_tbrrequest_time?.text = dateUtil.dateAndTimeAndSecondsString(it.lastTBRRequest)
|
||||
loop_tbrexecution_time?.text = dateUtil.dateAndTimeAndSecondsString(it.lastTBREnact)
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
loop_tbrsetbypump?.text = it.tbrSetByPump?.let { tbrSetByPump -> HtmlHelper.fromHtml(tbrSetByPump.toHtml()) }
|
||||
@Synchronized
|
||||
fun updateGUI() {
|
||||
if (_binding == null) return
|
||||
loopPlugin.lastRun?.let {
|
||||
binding.request.text = it.request?.toSpanned() ?: ""
|
||||
binding.constraintsprocessed.text = it.constraintsProcessed?.toSpanned() ?: ""
|
||||
binding.source.text = it.source ?: ""
|
||||
binding.lastrun.text = dateUtil.dateAndTimeString(it.lastAPSRun)
|
||||
?: ""
|
||||
loop_smbsetbypump?.text = it.smbSetByPump?.let { smbSetByPump -> HtmlHelper.fromHtml(smbSetByPump.toHtml()) }
|
||||
binding.smbrequestTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBRequest)
|
||||
binding.smbexecutionTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBEnact)
|
||||
binding.tbrrequestTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastTBRRequest)
|
||||
binding.tbrexecutionTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastTBREnact)
|
||||
|
||||
binding.tbrsetbypump.text = it.tbrSetByPump?.let { tbrSetByPump -> HtmlHelper.fromHtml(tbrSetByPump.toHtml()) }
|
||||
?: ""
|
||||
binding.smbsetbypump.text = it.smbSetByPump?.let { smbSetByPump -> HtmlHelper.fromHtml(smbSetByPump.toHtml()) }
|
||||
?: ""
|
||||
|
||||
val constraints =
|
||||
|
@ -101,22 +116,22 @@ class LoopFragment : DaggerFragment() {
|
|||
constraintsProcessed.smbConstraint?.let { smbConstraint -> allConstraints.copyReasons(smbConstraint) }
|
||||
allConstraints.getMostLimitedReasons(aapsLogger)
|
||||
} ?: ""
|
||||
loop_constraints?.text = constraints
|
||||
binding.constraints.text = constraints
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun clearGUI() {
|
||||
loop_request?.text = ""
|
||||
loop_constraints?.text = ""
|
||||
loop_constraintsprocessed?.text = ""
|
||||
loop_source?.text = ""
|
||||
loop_lastrun?.text = ""
|
||||
loop_smbrequest_time?.text = ""
|
||||
loop_smbexecution_time?.text = ""
|
||||
loop_tbrrequest_time?.text = ""
|
||||
loop_tbrexecution_time?.text = ""
|
||||
loop_tbrsetbypump?.text = ""
|
||||
loop_smbsetbypump?.text = ""
|
||||
binding.request.text = ""
|
||||
binding.constraints.text = ""
|
||||
binding.constraintsprocessed.text = ""
|
||||
binding.source.text = ""
|
||||
binding.lastrun.text = ""
|
||||
binding.smbrequestTime.text = ""
|
||||
binding.smbexecutionTime.text = ""
|
||||
binding.tbrrequestTime.text = ""
|
||||
binding.tbrexecutionTime.text = ""
|
||||
binding.tbrsetbypump.text = ""
|
||||
binding.smbsetbypump.text = ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,884 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.loop;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.TaskStackBuilder;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Lazy;
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainActivity;
|
||||
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.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventTempTargetChange;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.LoopInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.queue.commands.Command;
|
||||
import info.nightscout.androidaps.receivers.ReceiverStatusStore;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.HardLimits;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
@Singleton
|
||||
public class LoopPlugin extends PluginBase implements LoopInterface {
|
||||
private final HasAndroidInjector injector;
|
||||
private final SP sp;
|
||||
private final RxBusWrapper rxBus;
|
||||
private final ConstraintChecker constraintChecker;
|
||||
private final ResourceHelper resourceHelper;
|
||||
private final ProfileFunction profileFunction;
|
||||
private final Context context;
|
||||
private final CommandQueueProvider commandQueue;
|
||||
private final ActivePluginProvider activePlugin;
|
||||
private final TreatmentsPlugin treatmentsPlugin;
|
||||
private final VirtualPumpPlugin virtualPumpPlugin;
|
||||
private final Lazy<ActionStringHandler> actionStringHandler;
|
||||
private final IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
private final ReceiverStatusStore receiverStatusStore;
|
||||
private final FabricPrivacy fabricPrivacy;
|
||||
private final NSUpload nsUpload;
|
||||
private final HardLimits hardLimits;
|
||||
|
||||
private final CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
private static final String CHANNEL_ID = "AndroidAPS-Openloop";
|
||||
|
||||
private long lastBgTriggeredRun = 0;
|
||||
|
||||
private long loopSuspendedTill; // end of manual loop suspend
|
||||
private boolean isSuperBolus;
|
||||
private boolean isDisconnected;
|
||||
|
||||
private long carbsSuggestionsSuspendedUntil = 0;
|
||||
private int prevCarbsreq = 0;
|
||||
|
||||
@Nullable private LastRun lastRun = null;
|
||||
|
||||
@Nullable @Override public LastRun getLastRun() {
|
||||
return lastRun;
|
||||
}
|
||||
|
||||
@Override public void setLastRun(@Nullable LastRun lastRun) {
|
||||
this.lastRun = lastRun;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public LoopPlugin(
|
||||
HasAndroidInjector injector,
|
||||
AAPSLogger aapsLogger,
|
||||
RxBusWrapper rxBus,
|
||||
SP sp,
|
||||
Config config,
|
||||
ConstraintChecker constraintChecker,
|
||||
ResourceHelper resourceHelper,
|
||||
ProfileFunction profileFunction,
|
||||
Context context,
|
||||
CommandQueueProvider commandQueue,
|
||||
ActivePluginProvider activePlugin,
|
||||
TreatmentsPlugin treatmentsPlugin,
|
||||
VirtualPumpPlugin virtualPumpPlugin,
|
||||
Lazy<ActionStringHandler> actionStringHandler, // TODO Adrian use RxBus instead of Lazy
|
||||
IobCobCalculatorPlugin iobCobCalculatorPlugin,
|
||||
ReceiverStatusStore receiverStatusStore,
|
||||
FabricPrivacy fabricPrivacy,
|
||||
NSUpload nsUpload,
|
||||
HardLimits hardLimits
|
||||
) {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.LOOP)
|
||||
.fragmentClass(LoopFragment.class.getName())
|
||||
.pluginIcon(R.drawable.ic_loop_closed_white)
|
||||
.pluginName(R.string.loop)
|
||||
.shortName(R.string.loop_shortname)
|
||||
.preferencesId(R.xml.pref_loop)
|
||||
.enableByDefault(config.getAPS())
|
||||
.description(R.string.description_loop),
|
||||
aapsLogger, resourceHelper, injector
|
||||
);
|
||||
this.injector = injector;
|
||||
this.sp = sp;
|
||||
this.rxBus = rxBus;
|
||||
this.constraintChecker = constraintChecker;
|
||||
this.resourceHelper = resourceHelper;
|
||||
this.profileFunction = profileFunction;
|
||||
this.context = context;
|
||||
this.activePlugin = activePlugin;
|
||||
this.commandQueue = commandQueue;
|
||||
this.treatmentsPlugin = treatmentsPlugin;
|
||||
this.virtualPumpPlugin = virtualPumpPlugin;
|
||||
this.actionStringHandler = actionStringHandler;
|
||||
this.iobCobCalculatorPlugin = iobCobCalculatorPlugin;
|
||||
this.receiverStatusStore = receiverStatusStore;
|
||||
this.fabricPrivacy = fabricPrivacy;
|
||||
this.nsUpload = nsUpload;
|
||||
this.hardLimits = hardLimits;
|
||||
|
||||
loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L);
|
||||
isSuperBolus = sp.getBoolean("isSuperBolus", false);
|
||||
isDisconnected = sp.getBoolean("isDisconnected", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
createNotificationChannel();
|
||||
super.onStart();
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventTempTargetChange.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> invoke("EventTempTargetChange", true), fabricPrivacy::logException)
|
||||
);
|
||||
/**
|
||||
* This method is triggered once autosens calculation has completed, so the LoopPlugin
|
||||
* has current data to work with. However, autosens calculation can be triggered by multiple
|
||||
* sources and currently only a new BG should trigger a loop run. Hence we return early if
|
||||
* the event causing the calculation is not EventNewBg.
|
||||
* <p>
|
||||
*/
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished.class)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(event -> {
|
||||
// Autosens calculation not triggered by a new BG
|
||||
if (!(event.getCause() instanceof EventNewBG)) return;
|
||||
|
||||
BgReading bgReading = iobCobCalculatorPlugin.actualBg();
|
||||
// BG outdated
|
||||
if (bgReading == null) return;
|
||||
// already looped with that value
|
||||
if (bgReading.date <= lastBgTriggeredRun) return;
|
||||
|
||||
lastBgTriggeredRun = bgReading.date;
|
||||
invoke("AutosenseCalculation for " + bgReading, true);
|
||||
}, fabricPrivacy::logException)
|
||||
);
|
||||
}
|
||||
|
||||
private void createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
@SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
|
||||
CHANNEL_ID,
|
||||
NotificationManager.IMPORTANCE_HIGH);
|
||||
mNotificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
disposable.clear();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialEnableCondition() {
|
||||
try {
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
return pump.getPumpDescription().isTempBasalCapable;
|
||||
} catch (Exception ignored) {
|
||||
// may fail during initialization
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public long suspendedTo() {
|
||||
return loopSuspendedTill;
|
||||
}
|
||||
|
||||
public void suspendTo(long endTime) {
|
||||
loopSuspendedTill = endTime;
|
||||
isSuperBolus = false;
|
||||
isDisconnected = false;
|
||||
sp.putLong("loopSuspendedTill", loopSuspendedTill);
|
||||
sp.putBoolean("isSuperBolus", isSuperBolus);
|
||||
sp.putBoolean("isDisconnected", isDisconnected);
|
||||
}
|
||||
|
||||
public void superBolusTo(long endTime) {
|
||||
loopSuspendedTill = endTime;
|
||||
isSuperBolus = true;
|
||||
isDisconnected = false;
|
||||
sp.putLong("loopSuspendedTill", loopSuspendedTill);
|
||||
sp.putBoolean("isSuperBolus", isSuperBolus);
|
||||
sp.putBoolean("isDisconnected", isDisconnected);
|
||||
}
|
||||
|
||||
private void disconnectTo(long endTime) {
|
||||
loopSuspendedTill = endTime;
|
||||
isSuperBolus = false;
|
||||
isDisconnected = true;
|
||||
sp.putLong("loopSuspendedTill", loopSuspendedTill);
|
||||
sp.putBoolean("isSuperBolus", isSuperBolus);
|
||||
sp.putBoolean("isDisconnected", isDisconnected);
|
||||
}
|
||||
|
||||
public int minutesToEndOfSuspend() {
|
||||
if (loopSuspendedTill == 0)
|
||||
return 0;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
long msecDiff = loopSuspendedTill - now;
|
||||
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) (msecDiff / 60d / 1000d);
|
||||
}
|
||||
|
||||
public boolean isSuspended() {
|
||||
if (loopSuspendedTill == 0)
|
||||
return false;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isLGS() {
|
||||
Constraint<Boolean> closedLoopEnabled = constraintChecker.isClosedLoopAllowed();
|
||||
Double MaxIOBallowed = constraintChecker.getMaxIOBAllowed().value();
|
||||
String APSmode = sp.getString(R.string.key_aps_mode, "open");
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
boolean isLGS = false;
|
||||
|
||||
if (!isSuspended() && !pump.isSuspended())
|
||||
if (closedLoopEnabled.value())
|
||||
if ((MaxIOBallowed.equals(hardLimits.getMAXIOB_LGS())) || (APSmode.equals("lgs")))
|
||||
isLGS = true;
|
||||
|
||||
return isLGS;
|
||||
}
|
||||
|
||||
public boolean isSuperBolus() {
|
||||
if (loopSuspendedTill == 0)
|
||||
return false;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L);
|
||||
return false;
|
||||
}
|
||||
|
||||
return isSuperBolus;
|
||||
}
|
||||
|
||||
public boolean isDisconnected() {
|
||||
if (loopSuspendedTill == 0)
|
||||
return false;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L);
|
||||
return false;
|
||||
}
|
||||
return isDisconnected;
|
||||
}
|
||||
public boolean treatmentTimethreshold(int duartionMinutes) {
|
||||
long threshold = System.currentTimeMillis() + (duartionMinutes*60*1000);
|
||||
boolean bool = false;
|
||||
if (treatmentsPlugin.getLastBolusTime() > threshold || treatmentsPlugin.getLastCarbTime() > threshold)
|
||||
bool = true;
|
||||
|
||||
return bool;
|
||||
}
|
||||
|
||||
public synchronized void invoke(String initiator, boolean allowNotification) {
|
||||
invoke(initiator, allowNotification, false);
|
||||
}
|
||||
|
||||
public synchronized void invoke(String initiator, boolean allowNotification, boolean tempBasalFallback) {
|
||||
try {
|
||||
getAapsLogger().debug(LTag.APS, "invoke from " + initiator);
|
||||
Constraint<Boolean> loopEnabled = constraintChecker.isLoopInvocationAllowed();
|
||||
|
||||
if (!loopEnabled.value()) {
|
||||
String message = resourceHelper.gs(R.string.loopdisabled) + "\n" + loopEnabled.getReasons(getAapsLogger());
|
||||
getAapsLogger().debug(LTag.APS, message);
|
||||
rxBus.send(new EventLoopSetLastRunGui(message));
|
||||
return;
|
||||
}
|
||||
final PumpInterface pump = activePlugin.getActivePump();
|
||||
APSResult result = null;
|
||||
|
||||
if (!isEnabled(PluginType.LOOP))
|
||||
return;
|
||||
|
||||
Profile profile = profileFunction.getProfile();
|
||||
|
||||
if (profile == null || !profileFunction.isProfileValid("Loop")) {
|
||||
getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.noprofileselected));
|
||||
rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.noprofileselected)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if pump info is loaded
|
||||
if (pump.getBaseBasalRate() < 0.01d) return;
|
||||
|
||||
APSInterface usedAPS = activePlugin.getActiveAPS();
|
||||
if (((PluginBase) usedAPS).isEnabled(PluginType.APS)) {
|
||||
usedAPS.invoke(initiator, tempBasalFallback);
|
||||
result = usedAPS.getLastAPSResult();
|
||||
}
|
||||
|
||||
// Check if we have any result
|
||||
if (result == null) {
|
||||
rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.noapsselected)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare for pumps using % basals
|
||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT && allowPercentage()) {
|
||||
result.usePercent = true;
|
||||
}
|
||||
result.percent = (int) (result.rate / profile.getBasal() * 100);
|
||||
|
||||
// check rate for constraints
|
||||
final APSResult resultAfterConstraints = result.newAndClone(injector);
|
||||
resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate);
|
||||
resultAfterConstraints.rate = constraintChecker.applyBasalConstraints(resultAfterConstraints.rateConstraint, profile).value();
|
||||
|
||||
resultAfterConstraints.percentConstraint = new Constraint<>(resultAfterConstraints.percent);
|
||||
resultAfterConstraints.percent = constraintChecker.applyBasalPercentConstraints(resultAfterConstraints.percentConstraint, profile).value();
|
||||
|
||||
resultAfterConstraints.smbConstraint = new Constraint<>(resultAfterConstraints.smb);
|
||||
resultAfterConstraints.smb = constraintChecker.applyBolusConstraints(resultAfterConstraints.smbConstraint).value();
|
||||
|
||||
// safety check for multiple SMBs
|
||||
long lastBolusTime = treatmentsPlugin.getLastBolusTime();
|
||||
if (lastBolusTime != 0 && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) {
|
||||
getAapsLogger().debug(LTag.APS, "SMB requsted but still in 3 min interval");
|
||||
resultAfterConstraints.smb = 0;
|
||||
}
|
||||
|
||||
if (lastRun != null && lastRun.getConstraintsProcessed() != null) {
|
||||
prevCarbsreq = lastRun.getConstraintsProcessed().carbsReq;
|
||||
}
|
||||
|
||||
if (lastRun == null) lastRun = new LastRun();
|
||||
lastRun.setRequest(result);
|
||||
lastRun.setConstraintsProcessed(resultAfterConstraints);
|
||||
lastRun.setLastAPSRun(DateUtil.now());
|
||||
lastRun.setSource(((PluginBase) usedAPS).getName());
|
||||
lastRun.setTbrSetByPump(null);
|
||||
lastRun.setSmbSetByPump(null);
|
||||
lastRun.setLastTBREnact(0);
|
||||
lastRun.setLastTBRRequest(0);
|
||||
lastRun.setLastSMBEnact(0);
|
||||
lastRun.setLastSMBRequest(0);
|
||||
|
||||
nsUpload.uploadDeviceStatus(this, iobCobCalculatorPlugin, profileFunction, activePlugin.getActivePump(), receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
||||
|
||||
if (isSuspended()) {
|
||||
getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.loopsuspended));
|
||||
rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.loopsuspended)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pump.isSuspended()) {
|
||||
getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.pumpsuspended));
|
||||
rxBus.send(new EventLoopSetLastRunGui(resourceHelper.gs(R.string.pumpsuspended)));
|
||||
return;
|
||||
}
|
||||
|
||||
Constraint<Boolean> closedLoopEnabled = constraintChecker.isClosedLoopAllowed();
|
||||
|
||||
if (closedLoopEnabled.value()) {
|
||||
if (allowNotification) {
|
||||
if (resultAfterConstraints.isCarbsRequired()
|
||||
&& resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0)
|
||||
&& carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimethreshold(-15)) {
|
||||
|
||||
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local,true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false)) {
|
||||
Notification carbreqlocal = new Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.getCarbsRequiredText(), Notification.NORMAL);
|
||||
rxBus.send(new EventNewNotification(carbreqlocal));
|
||||
}
|
||||
if (sp.getBoolean(R.string.key_ns_create_announcements_from_carbs_req, false)) {
|
||||
nsUpload.uploadError(resultAfterConstraints.getCarbsRequiredText());
|
||||
}
|
||||
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local,true) && sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false)){
|
||||
Intent intentAction5m = new Intent(context, CarbSuggestionReceiver.class);
|
||||
intentAction5m.putExtra("ignoreDuration", 5);
|
||||
PendingIntent pendingIntent5m = PendingIntent.getBroadcast(context, 1, intentAction5m, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
NotificationCompat.Action actionIgnore5m = new
|
||||
NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore5m,"Ignore 5m"), pendingIntent5m);
|
||||
|
||||
Intent intentAction15m = new Intent(context, CarbSuggestionReceiver.class);
|
||||
intentAction15m.putExtra("ignoreDuration", 15);
|
||||
PendingIntent pendingIntent15m = PendingIntent.getBroadcast(context, 1, intentAction15m, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
NotificationCompat.Action actionIgnore15m = new
|
||||
NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore15m,"Ignore 15m"), pendingIntent15m);
|
||||
|
||||
Intent intentAction30m = new Intent(context, CarbSuggestionReceiver.class);
|
||||
intentAction30m.putExtra("ignoreDuration", 30);
|
||||
PendingIntent pendingIntent30m = PendingIntent.getBroadcast(context, 1, intentAction30m, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
NotificationCompat.Action actionIgnore30m = new
|
||||
NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore30m,"Ignore 30m"), pendingIntent30m);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
|
||||
builder.setSmallIcon(R.drawable.notif_icon)
|
||||
.setContentTitle(resourceHelper.gs(R.string.carbssuggestion))
|
||||
.setContentText(resultAfterConstraints.getCarbsRequiredText())
|
||||
.setAutoCancel(true)
|
||||
.setPriority(Notification.IMPORTANCE_HIGH)
|
||||
.setCategory(Notification.CATEGORY_ALARM)
|
||||
.addAction(actionIgnore5m)
|
||||
.addAction(actionIgnore15m)
|
||||
.addAction(actionIgnore30m)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
|
||||
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
// mId allows you to update the notification later on.
|
||||
mNotificationManager.notify(Constants.notificationID, builder.build());
|
||||
rxBus.send(new EventNewOpenLoopNotification());
|
||||
|
||||
//only send to wear if Native notifications are turned off
|
||||
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false)) {
|
||||
// Send to Wear
|
||||
actionStringHandler.get().handleInitiate("changeRequest");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
//If carbs were required previously, but are no longer needed, dismiss notifications
|
||||
if ( prevCarbsreq > 0 ) {
|
||||
dismissSuggestion();
|
||||
rxBus.send(new EventDismissNotification(Notification.CARBS_REQUIRED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resultAfterConstraints.isChangeRequested()
|
||||
&& !commandQueue.bolusInQueue()
|
||||
&& !commandQueue.isRunning(Command.CommandType.BOLUS)) {
|
||||
final PumpEnactResult waiting = new PumpEnactResult(getInjector());
|
||||
waiting.queued = true;
|
||||
if (resultAfterConstraints.tempBasalRequested)
|
||||
lastRun.setTbrSetByPump(waiting);
|
||||
if (resultAfterConstraints.bolusRequested)
|
||||
lastRun.setSmbSetByPump(waiting);
|
||||
rxBus.send(new EventLoopUpdateGui());
|
||||
fabricPrivacy.logCustom("APSRequest");
|
||||
applyTBRRequest(resultAfterConstraints, profile, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (result.enacted || result.success) {
|
||||
lastRun.setTbrSetByPump(result);
|
||||
lastRun.setLastTBRRequest(lastRun.getLastAPSRun());
|
||||
lastRun.setLastTBREnact(DateUtil.now());
|
||||
rxBus.send(new EventLoopUpdateGui());
|
||||
applySMBRequest(resultAfterConstraints, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Callback is only called if a bolus was actually requested
|
||||
if (result.enacted || result.success) {
|
||||
lastRun.setSmbSetByPump(result);
|
||||
lastRun.setLastSMBRequest(lastRun.getLastAPSRun());
|
||||
lastRun.setLastSMBEnact(DateUtil.now());
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
SystemClock.sleep(1000);
|
||||
invoke("tempBasalFallback", allowNotification, true);
|
||||
}).start();
|
||||
}
|
||||
rxBus.send(new EventLoopUpdateGui());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
lastRun.setTbrSetByPump(result);
|
||||
lastRun.setLastTBRRequest(lastRun.getLastAPSRun());
|
||||
}
|
||||
rxBus.send(new EventLoopUpdateGui());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
lastRun.setTbrSetByPump(null);
|
||||
lastRun.setSmbSetByPump(null);
|
||||
}
|
||||
} else {
|
||||
if (resultAfterConstraints.isChangeRequested() && allowNotification) {
|
||||
NotificationCompat.Builder builder =
|
||||
new NotificationCompat.Builder(context, CHANNEL_ID);
|
||||
builder.setSmallIcon(R.drawable.notif_icon)
|
||||
.setContentTitle(resourceHelper.gs(R.string.openloop_newsuggestion))
|
||||
.setContentText(resultAfterConstraints.toString())
|
||||
.setAutoCancel(true)
|
||||
.setPriority(Notification.IMPORTANCE_HIGH)
|
||||
.setCategory(Notification.CATEGORY_ALARM)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||
if (sp.getBoolean("wearcontrol", false)) {
|
||||
builder.setLocalOnly(true);
|
||||
}
|
||||
presentSuggestion(builder);
|
||||
} else if (allowNotification) {
|
||||
dismissSuggestion();
|
||||
}
|
||||
}
|
||||
|
||||
rxBus.send(new EventLoopUpdateGui());
|
||||
} finally {
|
||||
getAapsLogger().debug(LTag.APS, "invoke end");
|
||||
}
|
||||
}
|
||||
|
||||
public void disableCarbSuggestions(int duartionMinutes) {
|
||||
carbsSuggestionsSuspendedUntil = System.currentTimeMillis() + (duartionMinutes*60*1000);
|
||||
dismissSuggestion();
|
||||
}
|
||||
|
||||
private void presentSuggestion(NotificationCompat.Builder builder) {
|
||||
// Creates an explicit intent for an Activity in your app
|
||||
Intent resultIntent = new Intent(context, MainActivity.class);
|
||||
|
||||
// The stack builder object will contain an artificial back stack for the
|
||||
// started Activity.
|
||||
// This ensures that navigating backward from the Activity leads out of
|
||||
// your application to the Home screen.
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
|
||||
stackBuilder.addParentStack(MainActivity.class);
|
||||
// Adds the Intent that starts the Activity to the top of the stack
|
||||
stackBuilder.addNextIntent(resultIntent);
|
||||
PendingIntent resultPendingIntent =
|
||||
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentIntent(resultPendingIntent);
|
||||
builder.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
// mId allows you to update the notification later on.
|
||||
mNotificationManager.notify(Constants.notificationID, builder.build());
|
||||
rxBus.send(new EventNewOpenLoopNotification());
|
||||
|
||||
// Send to Wear
|
||||
actionStringHandler.get().handleInitiate("changeRequest");
|
||||
}
|
||||
|
||||
private void dismissSuggestion() {
|
||||
// dismiss notifications
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(Constants.notificationID);
|
||||
actionStringHandler.get().handleInitiate("cancelChangeRequest");
|
||||
}
|
||||
|
||||
public void acceptChangeRequest() {
|
||||
Profile profile = profileFunction.getProfile();
|
||||
final LoopPlugin lp = this;
|
||||
applyTBRRequest(lastRun.getConstraintsProcessed(), profile, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (result.enacted) {
|
||||
lastRun.setTbrSetByPump(result);
|
||||
lastRun.setLastTBRRequest(lastRun.getLastAPSRun());
|
||||
lastRun.setLastTBREnact(DateUtil.now());
|
||||
lastRun.setLastOpenModeAccept(DateUtil.now());
|
||||
nsUpload.uploadDeviceStatus(lp, iobCobCalculatorPlugin, profileFunction, activePlugin.getActivePump(), receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
||||
sp.incInt(R.string.key_ObjectivesmanualEnacts);
|
||||
}
|
||||
rxBus.send(new EventAcceptOpenLoopChange());
|
||||
}
|
||||
});
|
||||
fabricPrivacy.logCustom("AcceptTemp");
|
||||
}
|
||||
|
||||
/**
|
||||
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
||||
* TODO: update pump drivers to support APS request in %
|
||||
*/
|
||||
|
||||
private void applyTBRRequest(APSResult request, Profile profile, Callback callback) {
|
||||
|
||||
if (!request.tempBasalRequested) {
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).enacted(false).success(true).comment(resourceHelper.gs(R.string.nochangerequested))).run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
|
||||
if (!pump.isInitialized()) {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: " + resourceHelper.gs(R.string.pumpNotInitialized));
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (pump.isSuspended()) {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: " + resourceHelper.gs(R.string.pumpsuspended));
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpsuspended)).enacted(false).success(false)).run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: " + request.toString());
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(now);
|
||||
if (request.usePercent && allowPercentage()) {
|
||||
if (request.percent == 100 && request.duration == 0) {
|
||||
if (activeTemp != null) {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: cancelTempBasal()");
|
||||
commandQueue.cancelTempBasal(false, callback);
|
||||
} else {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: Basal set correctly");
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).percent(request.percent).duration(0)
|
||||
.enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly))).run();
|
||||
}
|
||||
}
|
||||
} else if (activeTemp != null
|
||||
&& activeTemp.getPlannedRemainingMinutes() > 5
|
||||
&& request.duration - activeTemp.getPlannedRemainingMinutes() < 30
|
||||
&& request.percent == activeTemp.percentRate) {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: Temp basal set correctly");
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).percent(request.percent)
|
||||
.enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes())
|
||||
.comment(resourceHelper.gs(R.string.let_temp_basal_run))).run();
|
||||
}
|
||||
} else {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: tempBasalPercent()");
|
||||
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, callback);
|
||||
}
|
||||
} else {
|
||||
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
|
||||
if (activeTemp != null) {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: cancelTempBasal()");
|
||||
commandQueue.cancelTempBasal(false, callback);
|
||||
} else {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: Basal set correctly");
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).absolute(request.rate).duration(0)
|
||||
.enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly))).run();
|
||||
}
|
||||
}
|
||||
} else if (activeTemp != null
|
||||
&& activeTemp.getPlannedRemainingMinutes() > 5
|
||||
&& request.duration - activeTemp.getPlannedRemainingMinutes() < 30
|
||||
&& Math.abs(request.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: Temp basal set correctly");
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).absolute(activeTemp.tempBasalConvertedToAbsolute(now, profile))
|
||||
.enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes())
|
||||
.comment(resourceHelper.gs(R.string.let_temp_basal_run))).run();
|
||||
}
|
||||
} else {
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()");
|
||||
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applySMBRequest(APSResult request, Callback callback) {
|
||||
if (!request.bolusRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
|
||||
long lastBolusTime = treatmentsPlugin.getLastBolusTime();
|
||||
if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||
getAapsLogger().debug(LTag.APS, "SMB requested but still in 3 min interval");
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector())
|
||||
.comment(resourceHelper.gs(R.string.smb_frequency_exceeded))
|
||||
.enacted(false).success(false)).run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pump.isInitialized()) {
|
||||
getAapsLogger().debug(LTag.APS, "applySMBRequest: " + resourceHelper.gs(R.string.pumpNotInitialized));
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (pump.isSuspended()) {
|
||||
getAapsLogger().debug(LTag.APS, "applySMBRequest: " + resourceHelper.gs(R.string.pumpsuspended));
|
||||
if (callback != null) {
|
||||
callback.result(new PumpEnactResult(getInjector()).comment(resourceHelper.gs(R.string.pumpsuspended)).enacted(false).success(false)).run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
getAapsLogger().debug(LTag.APS, "applySMBRequest: " + request.toString());
|
||||
|
||||
// deliver SMB
|
||||
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
|
||||
detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.getLastBolusTime();
|
||||
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
|
||||
detailedBolusInfo.insulin = request.smb;
|
||||
detailedBolusInfo.isSMB = true;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
detailedBolusInfo.deliverAt = request.deliverAt;
|
||||
getAapsLogger().debug(LTag.APS, "applyAPSRequest: bolus()");
|
||||
commandQueue.bolus(detailedBolusInfo, callback);
|
||||
}
|
||||
|
||||
private boolean allowPercentage() {
|
||||
return virtualPumpPlugin.isEnabled(PluginType.PUMP);
|
||||
}
|
||||
|
||||
public void disconnectPump(int durationInMinutes, Profile profile) {
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
|
||||
disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
|
||||
|
||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||
commandQueue.tempBasalAbsolute(0, durationInMinutes, true, profile, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(context, ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
commandQueue.tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(context, ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (pump.getPumpDescription().isExtendedBolusCapable && treatmentsPlugin.isInHistoryExtendedBoluslInProgress()) {
|
||||
commandQueue.cancelExtended(new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(context, ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", resourceHelper.gs(R.string.extendedbolusdeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
createOfflineEvent(durationInMinutes);
|
||||
}
|
||||
|
||||
public void suspendLoop(int durationInMinutes) {
|
||||
suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000);
|
||||
commandQueue.cancelTempBasal(true, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(context, ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
createOfflineEvent(durationInMinutes);
|
||||
}
|
||||
|
||||
public void createOfflineEvent(int durationInMinutes) {
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("eventType", CareportalEvent.OPENAPSOFFLINE);
|
||||
data.put("duration", durationInMinutes);
|
||||
} catch (JSONException e) {
|
||||
getAapsLogger().error("Unhandled exception", e);
|
||||
}
|
||||
CareportalEvent event = new CareportalEvent(getInjector());
|
||||
event.date = DateUtil.now();
|
||||
event.source = Source.USER;
|
||||
event.eventType = CareportalEvent.OPENAPSOFFLINE;
|
||||
event.json = data.toString();
|
||||
MainApp.getDbHelper().createOrUpdate(event);
|
||||
nsUpload.uploadOpenAPSOffline(event);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,674 @@
|
|||
package info.nightscout.androidaps.plugins.aps.loop
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.TaskStackBuilder
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.SystemClock
|
||||
import androidx.core.app.NotificationCompat
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.*
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.data.PumpEnactResult
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
||||
import info.nightscout.androidaps.events.EventNewBG
|
||||
import info.nightscout.androidaps.events.EventTempTargetChange
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.interfaces.LoopInterface.LastRun
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearDoAction
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.queue.commands.Command
|
||||
import info.nightscout.androidaps.receivers.ReceiverStatusStore
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.abs
|
||||
|
||||
@Singleton
|
||||
open class LoopPlugin @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger?,
|
||||
private val aapsSchedulers: AapsSchedulers,
|
||||
private val rxBus: RxBusWrapper,
|
||||
private val sp: SP,
|
||||
config: Config,
|
||||
private val constraintChecker: ConstraintChecker,
|
||||
resourceHelper: ResourceHelper,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val context: Context,
|
||||
private val commandQueue: CommandQueueProvider,
|
||||
private val activePlugin: ActivePluginProvider,
|
||||
private val treatmentsPlugin: TreatmentsPlugin,
|
||||
private val virtualPumpPlugin: VirtualPumpPlugin,
|
||||
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
|
||||
private val receiverStatusStore: ReceiverStatusStore,
|
||||
private val fabricPrivacy: FabricPrivacy,
|
||||
private val nsUpload: NSUpload,
|
||||
private val hardLimits: HardLimits
|
||||
) : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.LOOP)
|
||||
.fragmentClass(LoopFragment::class.java.name)
|
||||
.pluginIcon(R.drawable.ic_loop_closed_white)
|
||||
.pluginName(R.string.loop)
|
||||
.shortName(R.string.loop_shortname)
|
||||
.preferencesId(R.xml.pref_loop)
|
||||
.enableByDefault(config.APS)
|
||||
.description(R.string.description_loop),
|
||||
aapsLogger!!, resourceHelper, injector
|
||||
), LoopInterface {
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
private var lastBgTriggeredRun: Long = 0
|
||||
private var carbsSuggestionsSuspendedUntil: Long = 0
|
||||
private var prevCarbsreq = 0
|
||||
override var lastRun: LastRun? = null
|
||||
override fun onStart() {
|
||||
createNotificationChannel()
|
||||
super.onStart()
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventTempTargetChange::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ invoke("EventTempTargetChange", true) }, fabricPrivacy::logException)
|
||||
)
|
||||
/*
|
||||
This method is triggered once autosens calculation has completed, so the LoopPlugin
|
||||
has current data to work with. However, autosens calculation can be triggered by multiple
|
||||
sources and currently only a new BG should trigger a loop run. Hence we return early if
|
||||
the event causing the calculation is not EventNewBg.
|
||||
<p>
|
||||
*/
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ event: EventAutosensCalculationFinished ->
|
||||
// Autosens calculation not triggered by a new BG
|
||||
if (event.cause !is EventNewBG) return@subscribe
|
||||
val glucoseValue = iobCobCalculatorPlugin.actualBg() ?: return@subscribe
|
||||
// BG outdated
|
||||
// already looped with that value
|
||||
if (glucoseValue.timestamp <= lastBgTriggeredRun) return@subscribe
|
||||
lastBgTriggeredRun = glucoseValue.timestamp
|
||||
invoke("AutosenseCalculation for $glucoseValue", true)
|
||||
}, fabricPrivacy::logException)
|
||||
)
|
||||
}
|
||||
|
||||
private fun createNotificationChannel() {
|
||||
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
@SuppressLint("WrongConstant") val channel = NotificationChannel(CHANNEL_ID,
|
||||
CHANNEL_ID,
|
||||
NotificationManager.IMPORTANCE_HIGH)
|
||||
mNotificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
disposable.clear()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun specialEnableCondition(): Boolean {
|
||||
return try {
|
||||
val pump = activePlugin.activePump
|
||||
pump.pumpDescription.isTempBasalCapable
|
||||
} catch (ignored: Exception) {
|
||||
// may fail during initialization
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun suspendTo(endTime: Long) {
|
||||
sp.putLong("loopSuspendedTill", endTime)
|
||||
sp.putBoolean("isSuperBolus", false)
|
||||
sp.putBoolean("isDisconnected", false)
|
||||
}
|
||||
|
||||
fun superBolusTo(endTime: Long) {
|
||||
sp.putLong("loopSuspendedTill", endTime)
|
||||
sp.putBoolean("isSuperBolus", true)
|
||||
sp.putBoolean("isDisconnected", false)
|
||||
}
|
||||
|
||||
private fun disconnectTo(endTime: Long) {
|
||||
sp.putLong("loopSuspendedTill", endTime)
|
||||
sp.putBoolean("isSuperBolus", false)
|
||||
sp.putBoolean("isDisconnected", true)
|
||||
}
|
||||
|
||||
fun minutesToEndOfSuspend(): Int {
|
||||
val loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L)
|
||||
if (loopSuspendedTill == 0L) return 0
|
||||
val now = System.currentTimeMillis()
|
||||
val millisDiff = loopSuspendedTill - now
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L)
|
||||
return 0
|
||||
}
|
||||
return (millisDiff / 60.0 / 1000.0).toInt()
|
||||
}
|
||||
|
||||
// time exceeded
|
||||
val isSuspended: Boolean
|
||||
get() {
|
||||
val loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L)
|
||||
if (loopSuspendedTill == 0L) return false
|
||||
val now = System.currentTimeMillis()
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
val isLGS: Boolean
|
||||
get() {
|
||||
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
|
||||
val maxIobAllowed = constraintChecker.getMaxIOBAllowed().value()
|
||||
val apsMode = sp.getString(R.string.key_aps_mode, "open")
|
||||
val pump = activePlugin.activePump
|
||||
var isLGS = false
|
||||
if (!isSuspended && !pump.isSuspended) if (closedLoopEnabled.value()) if (maxIobAllowed == hardLimits.MAXIOB_LGS || apsMode == "lgs") isLGS = true
|
||||
return isLGS
|
||||
}
|
||||
|
||||
// time exceeded
|
||||
val isSuperBolus: Boolean
|
||||
get() {
|
||||
val loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L)
|
||||
if (loopSuspendedTill == 0L) return false
|
||||
val now = System.currentTimeMillis()
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L)
|
||||
return false
|
||||
}
|
||||
return sp.getBoolean("isSuperBolus", false)
|
||||
}
|
||||
|
||||
// time exceeded
|
||||
val isDisconnected: Boolean
|
||||
get() {
|
||||
val loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L)
|
||||
if (loopSuspendedTill == 0L) return false
|
||||
val now = System.currentTimeMillis()
|
||||
if (loopSuspendedTill <= now) { // time exceeded
|
||||
suspendTo(0L)
|
||||
return false
|
||||
}
|
||||
return sp.getBoolean("isDisconnected", false)
|
||||
}
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
private fun treatmentTimeThreshold(durationMinutes: Int): Boolean {
|
||||
val threshold = System.currentTimeMillis() + durationMinutes * 60 * 1000
|
||||
var bool = false
|
||||
if (treatmentsPlugin.lastBolusTime > threshold || treatmentsPlugin.lastCarbTime > threshold) bool = true
|
||||
return bool
|
||||
}
|
||||
|
||||
@Synchronized operator fun invoke(initiator: String, allowNotification: Boolean) {
|
||||
invoke(initiator, allowNotification, false)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
operator fun invoke(initiator: String, allowNotification: Boolean, tempBasalFallback: Boolean) {
|
||||
try {
|
||||
aapsLogger.debug(LTag.APS, "invoke from $initiator")
|
||||
val loopEnabled = constraintChecker.isLoopInvocationAllowed()
|
||||
if (!loopEnabled.value()) {
|
||||
val message = """
|
||||
${resourceHelper.gs(R.string.loopdisabled)}
|
||||
${loopEnabled.getReasons(aapsLogger)}
|
||||
""".trimIndent()
|
||||
aapsLogger.debug(LTag.APS, message)
|
||||
rxBus.send(EventLoopSetLastRunGui(message))
|
||||
return
|
||||
}
|
||||
val pump = activePlugin.activePump
|
||||
var apsResult: APSResult? = null
|
||||
if (!isEnabled(PluginType.LOOP)) return
|
||||
val profile = profileFunction.getProfile()
|
||||
if (profile == null || !profileFunction.isProfileValid("Loop")) {
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.noprofileselected))
|
||||
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.noprofileselected)))
|
||||
return
|
||||
}
|
||||
|
||||
// Check if pump info is loaded
|
||||
if (pump.baseBasalRate < 0.01) return
|
||||
val usedAPS = activePlugin.activeAPS
|
||||
if ((usedAPS as PluginBase).isEnabled(PluginType.APS)) {
|
||||
usedAPS.invoke(initiator, tempBasalFallback)
|
||||
apsResult = usedAPS.lastAPSResult
|
||||
}
|
||||
|
||||
// Check if we have any result
|
||||
if (apsResult == null) {
|
||||
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.noapsselected)))
|
||||
return
|
||||
}
|
||||
|
||||
// Prepare for pumps using % basals
|
||||
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT && allowPercentage()) {
|
||||
apsResult.usePercent = true
|
||||
}
|
||||
apsResult.percent = (apsResult.rate / profile.basal * 100).toInt()
|
||||
|
||||
// check rate for constraints
|
||||
val resultAfterConstraints = apsResult.newAndClone(injector)
|
||||
resultAfterConstraints.rateConstraint = Constraint(resultAfterConstraints.rate)
|
||||
resultAfterConstraints.rate = constraintChecker.applyBasalConstraints(resultAfterConstraints.rateConstraint!!, profile).value()
|
||||
resultAfterConstraints.percentConstraint = Constraint(resultAfterConstraints.percent)
|
||||
resultAfterConstraints.percent = constraintChecker.applyBasalPercentConstraints(resultAfterConstraints.percentConstraint!!, profile).value()
|
||||
resultAfterConstraints.smbConstraint = Constraint(resultAfterConstraints.smb)
|
||||
resultAfterConstraints.smb = constraintChecker.applyBolusConstraints(resultAfterConstraints.smbConstraint!!).value()
|
||||
|
||||
// safety check for multiple SMBs
|
||||
val lastBolusTime = treatmentsPlugin.lastBolusTime
|
||||
if (lastBolusTime != 0L && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) {
|
||||
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
|
||||
resultAfterConstraints.smb = 0.0
|
||||
}
|
||||
if (lastRun != null && lastRun!!.constraintsProcessed != null) {
|
||||
prevCarbsreq = lastRun!!.constraintsProcessed!!.carbsReq
|
||||
}
|
||||
if (lastRun == null) lastRun = LastRun()
|
||||
lastRun!!.request = apsResult
|
||||
lastRun!!.constraintsProcessed = resultAfterConstraints
|
||||
lastRun!!.lastAPSRun = DateUtil.now()
|
||||
lastRun!!.source = (usedAPS as PluginBase).name
|
||||
lastRun!!.tbrSetByPump = null
|
||||
lastRun!!.smbSetByPump = null
|
||||
lastRun!!.lastTBREnact = 0
|
||||
lastRun!!.lastTBRRequest = 0
|
||||
lastRun!!.lastSMBEnact = 0
|
||||
lastRun!!.lastSMBRequest = 0
|
||||
nsUpload.uploadDeviceStatus(this, iobCobCalculatorPlugin, profileFunction, activePlugin.activePump, receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)
|
||||
if (isSuspended) {
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.loopsuspended))
|
||||
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.loopsuspended)))
|
||||
return
|
||||
}
|
||||
if (pump.isSuspended) {
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.pumpsuspended))
|
||||
rxBus.send(EventLoopSetLastRunGui(resourceHelper.gs(R.string.pumpsuspended)))
|
||||
return
|
||||
}
|
||||
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
|
||||
if (closedLoopEnabled.value()) {
|
||||
if (allowNotification) {
|
||||
if (resultAfterConstraints.isCarbsRequired
|
||||
&& resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimeThreshold(-15)) {
|
||||
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
||||
val carbReqLocal = Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.carbsRequiredText, Notification.NORMAL)
|
||||
rxBus.send(EventNewNotification(carbReqLocal))
|
||||
}
|
||||
if (sp.getBoolean(R.string.key_ns_create_announcements_from_carbs_req, false)) {
|
||||
nsUpload.uploadError(resultAfterConstraints.carbsRequiredText)
|
||||
}
|
||||
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
||||
val intentAction5m = Intent(context, CarbSuggestionReceiver::class.java)
|
||||
intentAction5m.putExtra("ignoreDuration", 5)
|
||||
val pendingIntent5m = PendingIntent.getBroadcast(context, 1, intentAction5m, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val actionIgnore5m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore5m, "Ignore 5m"), pendingIntent5m)
|
||||
val intentAction15m = Intent(context, CarbSuggestionReceiver::class.java)
|
||||
intentAction15m.putExtra("ignoreDuration", 15)
|
||||
val pendingIntent15m = PendingIntent.getBroadcast(context, 1, intentAction15m, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val actionIgnore15m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore15m, "Ignore 15m"), pendingIntent15m)
|
||||
val intentAction30m = Intent(context, CarbSuggestionReceiver::class.java)
|
||||
intentAction30m.putExtra("ignoreDuration", 30)
|
||||
val pendingIntent30m = PendingIntent.getBroadcast(context, 1, intentAction30m, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val actionIgnore30m = NotificationCompat.Action(R.drawable.ic_notif_aaps, resourceHelper.gs(R.string.ignore30m, "Ignore 30m"), pendingIntent30m)
|
||||
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
builder.setSmallIcon(R.drawable.notif_icon)
|
||||
.setContentTitle(resourceHelper.gs(R.string.carbssuggestion))
|
||||
.setContentText(resultAfterConstraints.carbsRequiredText)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(Notification.IMPORTANCE_HIGH)
|
||||
.setCategory(Notification.CATEGORY_ALARM)
|
||||
.addAction(actionIgnore5m)
|
||||
.addAction(actionIgnore15m)
|
||||
.addAction(actionIgnore30m)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
|
||||
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
// mId allows you to update the notification later on.
|
||||
mNotificationManager.notify(Constants.notificationID, builder.build())
|
||||
rxBus.send(EventNewOpenLoopNotification())
|
||||
|
||||
//only send to wear if Native notifications are turned off
|
||||
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
||||
// Send to Wear
|
||||
rxBus.send(EventWearDoAction("changeRequest"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//If carbs were required previously, but are no longer needed, dismiss notifications
|
||||
if (prevCarbsreq > 0) {
|
||||
dismissSuggestion()
|
||||
rxBus.send(EventDismissNotification(Notification.CARBS_REQUIRED))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (resultAfterConstraints.isChangeRequested
|
||||
&& !commandQueue.bolusInQueue()
|
||||
&& !commandQueue.isRunning(Command.CommandType.BOLUS)) {
|
||||
val waiting = PumpEnactResult(injector)
|
||||
waiting.queued = true
|
||||
if (resultAfterConstraints.tempBasalRequested) lastRun!!.tbrSetByPump = waiting
|
||||
if (resultAfterConstraints.bolusRequested) lastRun!!.smbSetByPump = waiting
|
||||
rxBus.send(EventLoopUpdateGui())
|
||||
fabricPrivacy.logCustom("APSRequest")
|
||||
applyTBRRequest(resultAfterConstraints, profile, object : Callback() {
|
||||
override fun run() {
|
||||
if (result.enacted || result.success) {
|
||||
lastRun!!.tbrSetByPump = result
|
||||
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun
|
||||
lastRun!!.lastTBREnact = DateUtil.now()
|
||||
rxBus.send(EventLoopUpdateGui())
|
||||
applySMBRequest(resultAfterConstraints, object : Callback() {
|
||||
override fun run() {
|
||||
// Callback is only called if a bolus was actually requested
|
||||
if (result.enacted || result.success) {
|
||||
lastRun!!.smbSetByPump = result
|
||||
lastRun!!.lastSMBRequest = lastRun!!.lastAPSRun
|
||||
lastRun!!.lastSMBEnact = DateUtil.now()
|
||||
} else {
|
||||
Thread {
|
||||
SystemClock.sleep(1000)
|
||||
invoke("tempBasalFallback", allowNotification, true)
|
||||
}.start()
|
||||
}
|
||||
rxBus.send(EventLoopUpdateGui())
|
||||
}
|
||||
})
|
||||
} else {
|
||||
lastRun!!.tbrSetByPump = result
|
||||
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun
|
||||
}
|
||||
rxBus.send(EventLoopUpdateGui())
|
||||
}
|
||||
})
|
||||
} else {
|
||||
lastRun!!.tbrSetByPump = null
|
||||
lastRun!!.smbSetByPump = null
|
||||
}
|
||||
} else {
|
||||
if (resultAfterConstraints.isChangeRequested && allowNotification) {
|
||||
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
builder.setSmallIcon(R.drawable.notif_icon)
|
||||
.setContentTitle(resourceHelper.gs(R.string.openloop_newsuggestion))
|
||||
.setContentText(resultAfterConstraints.toString())
|
||||
.setAutoCancel(true)
|
||||
.setPriority(Notification.IMPORTANCE_HIGH)
|
||||
.setCategory(Notification.CATEGORY_ALARM)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
if (sp.getBoolean(R.string.key_wear_control, false)) {
|
||||
builder.setLocalOnly(true)
|
||||
}
|
||||
presentSuggestion(builder)
|
||||
} else if (allowNotification) {
|
||||
dismissSuggestion()
|
||||
}
|
||||
}
|
||||
rxBus.send(EventLoopUpdateGui())
|
||||
} finally {
|
||||
aapsLogger.debug(LTag.APS, "invoke end")
|
||||
}
|
||||
}
|
||||
|
||||
fun disableCarbSuggestions(durationMinutes: Int) {
|
||||
carbsSuggestionsSuspendedUntil = System.currentTimeMillis() + durationMinutes * 60 * 1000
|
||||
dismissSuggestion()
|
||||
}
|
||||
|
||||
private fun presentSuggestion(builder: NotificationCompat.Builder) {
|
||||
// Creates an explicit intent for an Activity in your app
|
||||
val resultIntent = Intent(context, MainActivity::class.java)
|
||||
|
||||
// The stack builder object will contain an artificial back stack for the
|
||||
// started Activity.
|
||||
// This ensures that navigating backward from the Activity leads out of
|
||||
// your application to the Home screen.
|
||||
val stackBuilder = TaskStackBuilder.create(context)
|
||||
stackBuilder.addParentStack(MainActivity::class.java)
|
||||
// Adds the Intent that starts the Activity to the top of the stack
|
||||
stackBuilder.addNextIntent(resultIntent)
|
||||
val resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
builder.setContentIntent(resultPendingIntent)
|
||||
builder.setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
|
||||
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// mId allows you to update the notification later on.
|
||||
mNotificationManager.notify(Constants.notificationID, builder.build())
|
||||
rxBus.send(EventNewOpenLoopNotification())
|
||||
|
||||
// Send to Wear
|
||||
rxBus.send(EventWearDoAction("changeRequest"))
|
||||
}
|
||||
|
||||
private fun dismissSuggestion() {
|
||||
// dismiss notifications
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.cancel(Constants.notificationID)
|
||||
rxBus.send(EventWearDoAction("cancelChangeRequest"))
|
||||
}
|
||||
|
||||
fun acceptChangeRequest() {
|
||||
val profile = profileFunction.getProfile()
|
||||
val lp = this
|
||||
applyTBRRequest(lastRun!!.constraintsProcessed, profile, object : Callback() {
|
||||
override fun run() {
|
||||
if (result.enacted) {
|
||||
lastRun!!.tbrSetByPump = result
|
||||
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun
|
||||
lastRun!!.lastTBREnact = DateUtil.now()
|
||||
lastRun!!.lastOpenModeAccept = DateUtil.now()
|
||||
nsUpload.uploadDeviceStatus(lp, iobCobCalculatorPlugin, profileFunction, activePlugin.activePump, receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)
|
||||
sp.incInt(R.string.key_ObjectivesmanualEnacts)
|
||||
}
|
||||
rxBus.send(EventAcceptOpenLoopChange())
|
||||
}
|
||||
})
|
||||
fabricPrivacy.logCustom("AcceptTemp")
|
||||
}
|
||||
|
||||
/**
|
||||
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
||||
* TODO: update pump drivers to support APS request in %
|
||||
*/
|
||||
private fun applyTBRRequest(request: APSResult?, profile: Profile?, callback: Callback?) {
|
||||
if (!request!!.tempBasalRequested) {
|
||||
callback?.result(PumpEnactResult(injector).enacted(false).success(true).comment(resourceHelper.gs(R.string.nochangerequested)))?.run()
|
||||
return
|
||||
}
|
||||
val pump = activePlugin.activePump
|
||||
if (!pump.isInitialized) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: " + resourceHelper.gs(R.string.pumpNotInitialized))
|
||||
callback?.result(PumpEnactResult(injector).comment(resourceHelper.gs(R.string.pumpNotInitialized)).enacted(false).success(false))?.run()
|
||||
return
|
||||
}
|
||||
if (pump.isSuspended) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: " + resourceHelper.gs(R.string.pumpsuspended))
|
||||
callback?.result(PumpEnactResult(injector).comment(resourceHelper.gs(R.string.pumpsuspended)).enacted(false).success(false))?.run()
|
||||
return
|
||||
}
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: $request")
|
||||
val now = System.currentTimeMillis()
|
||||
val activeTemp = treatmentsPlugin.getTempBasalFromHistory(now)
|
||||
if (request.usePercent && allowPercentage()) {
|
||||
if (request.percent == 100 && request.duration == 0) {
|
||||
if (activeTemp != null) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: cancelTempBasal()")
|
||||
commandQueue.cancelTempBasal(false, callback)
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).percent(request.percent).duration(0)
|
||||
.enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly)))?.run()
|
||||
}
|
||||
} else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.percentRate) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).percent(request.percent)
|
||||
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
||||
.comment(resourceHelper.gs(R.string.let_temp_basal_run)))?.run()
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()")
|
||||
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile!!, callback)
|
||||
}
|
||||
} else {
|
||||
if (request.rate == 0.0 && request.duration == 0 || abs(request.rate - pump.baseBasalRate) < pump.pumpDescription.basalStep) {
|
||||
if (activeTemp != null) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: cancelTempBasal()")
|
||||
commandQueue.cancelTempBasal(false, callback)
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).absolute(request.rate).duration(0)
|
||||
.enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly)))?.run()
|
||||
}
|
||||
} else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(request.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
||||
callback?.result(PumpEnactResult(injector).absolute(activeTemp.tempBasalConvertedToAbsolute(now, profile))
|
||||
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
||||
.comment(resourceHelper.gs(R.string.let_temp_basal_run)))?.run()
|
||||
} else {
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()")
|
||||
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile!!, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun applySMBRequest(request: APSResult, callback: Callback?) {
|
||||
if (!request.bolusRequested) {
|
||||
return
|
||||
}
|
||||
val pump = activePlugin.activePump
|
||||
val lastBolusTime = treatmentsPlugin.lastBolusTime
|
||||
if (lastBolusTime != 0L && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
|
||||
callback?.result(PumpEnactResult(injector)
|
||||
.comment(resourceHelper.gs(R.string.smb_frequency_exceeded))
|
||||
.enacted(false).success(false))?.run()
|
||||
return
|
||||
}
|
||||
if (!pump.isInitialized) {
|
||||
aapsLogger.debug(LTag.APS, "applySMBRequest: " + resourceHelper.gs(R.string.pumpNotInitialized))
|
||||
callback?.result(PumpEnactResult(injector).comment(resourceHelper.gs(R.string.pumpNotInitialized)).enacted(false).success(false))?.run()
|
||||
return
|
||||
}
|
||||
if (pump.isSuspended) {
|
||||
aapsLogger.debug(LTag.APS, "applySMBRequest: " + resourceHelper.gs(R.string.pumpsuspended))
|
||||
callback?.result(PumpEnactResult(injector).comment(resourceHelper.gs(R.string.pumpsuspended)).enacted(false).success(false))?.run()
|
||||
return
|
||||
}
|
||||
aapsLogger.debug(LTag.APS, "applySMBRequest: $request")
|
||||
|
||||
// deliver SMB
|
||||
val detailedBolusInfo = DetailedBolusInfo()
|
||||
detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.lastBolusTime
|
||||
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
|
||||
detailedBolusInfo.insulin = request.smb
|
||||
detailedBolusInfo.isSMB = true
|
||||
detailedBolusInfo.source = Source.USER
|
||||
detailedBolusInfo.deliverAt = request.deliverAt
|
||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: bolus()")
|
||||
commandQueue.bolus(detailedBolusInfo, callback)
|
||||
}
|
||||
|
||||
private fun allowPercentage(): Boolean {
|
||||
return virtualPumpPlugin.isEnabled(PluginType.PUMP)
|
||||
}
|
||||
|
||||
fun disconnectPump(durationInMinutes: Int, profile: Profile?) {
|
||||
val pump = activePlugin.activePump
|
||||
disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L)
|
||||
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||
commandQueue.tempBasalAbsolute(0.0, durationInMinutes, true, profile!!, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
commandQueue.tempBasalPercent(0, durationInMinutes, true, profile!!, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if (pump.pumpDescription.isExtendedBolusCapable && treatmentsPlugin.isInHistoryExtendedBoluslInProgress) {
|
||||
commandQueue.cancelExtended(object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.extendedbolusdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
createOfflineEvent(durationInMinutes)
|
||||
}
|
||||
|
||||
fun suspendLoop(durationInMinutes: Int) {
|
||||
suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000)
|
||||
commandQueue.cancelTempBasal(true, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
|
||||
}
|
||||
}
|
||||
})
|
||||
createOfflineEvent(durationInMinutes)
|
||||
}
|
||||
|
||||
fun createOfflineEvent(durationInMinutes: Int) {
|
||||
val data = JSONObject()
|
||||
try {
|
||||
data.put("eventType", CareportalEvent.OPENAPSOFFLINE)
|
||||
data.put("duration", durationInMinutes)
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
val event = CareportalEvent(injector)
|
||||
event.date = DateUtil.now()
|
||||
event.source = Source.USER
|
||||
event.eventType = CareportalEvent.OPENAPSOFFLINE
|
||||
event.json = data.toString()
|
||||
MainApp.getDbHelper().createOrUpdate(event)
|
||||
nsUpload.uploadOpenAPSOffline(event)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val CHANNEL_ID = "AndroidAPS-OpenLoop"
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.loop;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ScriptReader {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public ScriptReader(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public byte[] readFile(String fileName) throws IOException {
|
||||
|
||||
AssetManager assetManager = mContext.getAssets();
|
||||
InputStream is = assetManager.open(fileName);
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
int nRead;
|
||||
byte[] data = new byte[16384];
|
||||
|
||||
while ((nRead = is.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
|
||||
buffer.flush();
|
||||
|
||||
byte[] bytes = buffer.toByteArray();
|
||||
is.close();
|
||||
buffer.close();
|
||||
|
||||
|
||||
return bytes;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package info.nightscout.androidaps.plugins.aps.loop
|
||||
|
||||
import android.content.Context
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
|
||||
class ScriptReader(private val context: Context) {
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun readFile(fileName: String): ByteArray {
|
||||
val assetManager = context.assets
|
||||
val `is` = assetManager.open(fileName)
|
||||
val buffer = ByteArrayOutputStream()
|
||||
var nRead: Int
|
||||
val data = ByteArray(16384)
|
||||
while (`is`.read(data, 0, data.size).also { nRead = it } != -1) {
|
||||
buffer.write(data, 0, nRead)
|
||||
}
|
||||
buffer.flush()
|
||||
val bytes = buffer.toByteArray()
|
||||
`is`.close()
|
||||
buffer.close()
|
||||
return bytes
|
||||
}
|
||||
}
|
|
@ -1,299 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSAMA;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Function;
|
||||
import org.mozilla.javascript.NativeJSON;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
import org.mozilla.javascript.RhinoException;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
import org.mozilla.javascript.Undefined;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader;
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader;
|
||||
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
public class DetermineBasalAdapterAMAJS {
|
||||
private final HasAndroidInjector injector;
|
||||
@Inject AAPSLogger aapsLogger;
|
||||
@Inject ConstraintChecker constraintChecker;
|
||||
@Inject SP sp;
|
||||
@Inject ProfileFunction profileFunction;
|
||||
@Inject TreatmentsPlugin treatmentsPlugin;
|
||||
@Inject OpenHumansUploader openHumansUploader;
|
||||
|
||||
private final ScriptReader mScriptReader;
|
||||
|
||||
private JSONObject mProfile;
|
||||
private JSONObject mGlucoseStatus;
|
||||
private JSONArray mIobData;
|
||||
private JSONObject mMealData;
|
||||
private JSONObject mCurrentTemp;
|
||||
private JSONObject mAutosensData = null;
|
||||
|
||||
private String storedCurrentTemp = null;
|
||||
private String storedIobData = null;
|
||||
private String storedGlucoseStatus = null;
|
||||
private String storedProfile = null;
|
||||
private String storedMeal_data = null;
|
||||
private String storedAutosens_data = null;
|
||||
|
||||
private String scriptDebug = "";
|
||||
|
||||
DetermineBasalAdapterAMAJS(ScriptReader scriptReader, HasAndroidInjector injector) {
|
||||
injector.androidInjector().inject(this);
|
||||
mScriptReader = scriptReader;
|
||||
this.injector = injector;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DetermineBasalResultAMA invoke() {
|
||||
|
||||
aapsLogger.debug(LTag.APS, ">>> Invoking detemine_basal <<<");
|
||||
aapsLogger.debug(LTag.APS, "Glucose status: " + (storedGlucoseStatus = mGlucoseStatus.toString()));
|
||||
aapsLogger.debug(LTag.APS, "IOB data: " + (storedIobData = mIobData.toString()));
|
||||
aapsLogger.debug(LTag.APS, "Current temp: " + (storedCurrentTemp = mCurrentTemp.toString()));
|
||||
aapsLogger.debug(LTag.APS, "Profile: " + (storedProfile = mProfile.toString()));
|
||||
aapsLogger.debug(LTag.APS, "Meal data: " + (storedMeal_data = mMealData.toString()));
|
||||
if (mAutosensData != null)
|
||||
aapsLogger.debug(LTag.APS, "Autosens data: " + (storedAutosens_data = mAutosensData.toString()));
|
||||
else
|
||||
aapsLogger.debug(LTag.APS, "Autosens data: " + (storedAutosens_data = "undefined"));
|
||||
|
||||
|
||||
DetermineBasalResultAMA determineBasalResultAMA = null;
|
||||
|
||||
Context rhino = Context.enter();
|
||||
Scriptable scope = rhino.initStandardObjects();
|
||||
// Turn off optimization to make Rhino Android compatible
|
||||
rhino.setOptimizationLevel(-1);
|
||||
|
||||
try {
|
||||
|
||||
//register logger callback for console.log and console.error
|
||||
ScriptableObject.defineClass(scope, LoggerCallback.class);
|
||||
Scriptable myLogger = rhino.newObject(scope, "LoggerCallback", null);
|
||||
scope.put("console2", scope, myLogger);
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null);
|
||||
|
||||
//set module parent
|
||||
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null);
|
||||
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null);
|
||||
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null);
|
||||
|
||||
//generate functions "determine_basal" and "setTempBasal"
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/determine-basal.js"), "JavaScript", 0, null);
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/basal-set-temp.js"), "setTempBasal.js", 0, null);
|
||||
Object determineBasalObj = scope.get("determine_basal", scope);
|
||||
Object setTempBasalFunctionsObj = scope.get("tempBasalFunctions", scope);
|
||||
|
||||
//call determine-basal
|
||||
if (determineBasalObj instanceof Function && setTempBasalFunctionsObj instanceof NativeObject) {
|
||||
Function determineBasalJS = (Function) determineBasalObj;
|
||||
|
||||
//prepare parameters
|
||||
Object[] params = new Object[]{
|
||||
makeParam(mGlucoseStatus, rhino, scope),
|
||||
makeParam(mCurrentTemp, rhino, scope),
|
||||
makeParamArray(mIobData, rhino, scope),
|
||||
makeParam(mProfile, rhino, scope),
|
||||
makeParam(mAutosensData, rhino, scope),
|
||||
makeParam(mMealData, rhino, scope),
|
||||
setTempBasalFunctionsObj};
|
||||
|
||||
NativeObject jsResult = (NativeObject) determineBasalJS.call(rhino, scope, scope, params);
|
||||
scriptDebug = LoggerCallback.getScriptDebug();
|
||||
|
||||
// Parse the jsResult object to a JSON-String
|
||||
String result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString();
|
||||
aapsLogger.debug(LTag.APS, "Result: " + result);
|
||||
try {
|
||||
JSONObject resultJson = new JSONObject(result);
|
||||
openHumansUploader.enqueueAMAData(mProfile, mGlucoseStatus, mIobData, mMealData, mCurrentTemp, mAutosensData, resultJson);
|
||||
determineBasalResultAMA = new DetermineBasalResultAMA(injector, jsResult, resultJson);
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e);
|
||||
}
|
||||
} else {
|
||||
aapsLogger.error(LTag.APS, "Problem loading JS Functions");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
aapsLogger.error(LTag.APS, "IOException");
|
||||
} catch (RhinoException e) {
|
||||
aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString());
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||
aapsLogger.error(LTag.APS, e.toString());
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
|
||||
storedGlucoseStatus = mGlucoseStatus.toString();
|
||||
storedIobData = mIobData.toString();
|
||||
storedCurrentTemp = mCurrentTemp.toString();
|
||||
storedProfile = mProfile.toString();
|
||||
storedMeal_data = mMealData.toString();
|
||||
|
||||
return determineBasalResultAMA;
|
||||
|
||||
}
|
||||
|
||||
String getGlucoseStatusParam() {
|
||||
return storedGlucoseStatus;
|
||||
}
|
||||
|
||||
String getCurrentTempParam() {
|
||||
return storedCurrentTemp;
|
||||
}
|
||||
|
||||
String getIobDataParam() {
|
||||
return storedIobData;
|
||||
}
|
||||
|
||||
String getProfileParam() {
|
||||
return storedProfile;
|
||||
}
|
||||
|
||||
String getMealDataParam() {
|
||||
return storedMeal_data;
|
||||
}
|
||||
|
||||
String getAutosensDataParam() {
|
||||
return storedAutosens_data;
|
||||
}
|
||||
|
||||
String getScriptDebug() {
|
||||
return scriptDebug;
|
||||
}
|
||||
|
||||
public void setData(Profile profile,
|
||||
double maxIob,
|
||||
double maxBasal,
|
||||
double minBg,
|
||||
double maxBg,
|
||||
double targetBg,
|
||||
double basalrate,
|
||||
IobTotal[] iobArray,
|
||||
GlucoseStatus glucoseStatus,
|
||||
MealData mealData,
|
||||
double autosensDataRatio,
|
||||
boolean tempTargetSet) throws JSONException {
|
||||
|
||||
mProfile = new JSONObject();
|
||||
mProfile.put("max_iob", maxIob);
|
||||
mProfile.put("dia", Math.min(profile.getDia(), 3d));
|
||||
mProfile.put("type", "current");
|
||||
mProfile.put("max_daily_basal", profile.getMaxDailyBasal());
|
||||
mProfile.put("max_basal", maxBasal);
|
||||
mProfile.put("min_bg", minBg);
|
||||
mProfile.put("max_bg", maxBg);
|
||||
mProfile.put("target_bg", targetBg);
|
||||
mProfile.put("carb_ratio", profile.getIc());
|
||||
mProfile.put("sens", profile.getIsfMgdl());
|
||||
mProfile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
|
||||
mProfile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
|
||||
mProfile.put("skip_neutral_temps", true);
|
||||
mProfile.put("current_basal", basalrate);
|
||||
mProfile.put("temptargetSet", tempTargetSet);
|
||||
mProfile.put("autosens_adjust_targets", sp.getBoolean(R.string.key_openapsama_autosens_adjusttargets, true));
|
||||
//align with max-absorption model in AMA sensitivity
|
||||
if (mealData.usedMinCarbsImpact > 0) {
|
||||
mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact);
|
||||
} else {
|
||||
mProfile.put("min_5m_carbimpact", sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
|
||||
}
|
||||
|
||||
if (profileFunction.getUnits().equals(Constants.MMOL)) {
|
||||
mProfile.put("out_units", "mmol/L");
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now);
|
||||
|
||||
mCurrentTemp = new JSONObject();
|
||||
mCurrentTemp.put("temp", "absolute");
|
||||
mCurrentTemp.put("duration", tb != null ? tb.getPlannedRemainingMinutes() : 0);
|
||||
mCurrentTemp.put("rate", tb != null ? tb.tempBasalConvertedToAbsolute(now, profile) : 0d);
|
||||
|
||||
// as we have non default temps longer than 30 mintues
|
||||
TemporaryBasal tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis());
|
||||
if (tempBasal != null) {
|
||||
mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration());
|
||||
}
|
||||
|
||||
mIobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray);
|
||||
|
||||
mGlucoseStatus = new JSONObject();
|
||||
mGlucoseStatus.put("glucose", glucoseStatus.glucose);
|
||||
|
||||
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
|
||||
mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
|
||||
} else {
|
||||
mGlucoseStatus.put("delta", glucoseStatus.delta);
|
||||
}
|
||||
mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta);
|
||||
mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta);
|
||||
|
||||
mMealData = new JSONObject();
|
||||
mMealData.put("carbs", mealData.carbs);
|
||||
mMealData.put("boluses", mealData.boluses);
|
||||
mMealData.put("mealCOB", mealData.mealCOB);
|
||||
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
mAutosensData = new JSONObject();
|
||||
mAutosensData.put("ratio", autosensDataRatio);
|
||||
} else {
|
||||
mAutosensData = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
|
||||
|
||||
if (jsonObject == null) return Undefined.instance;
|
||||
|
||||
Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), (context, scriptable, scriptable1, objects) -> objects[1]);
|
||||
return param;
|
||||
}
|
||||
|
||||
private Object makeParamArray(JSONArray jsonArray, Context rhino, Scriptable scope) {
|
||||
//Object param = NativeJSON.parse(rhino, scope, "{myarray: " + jsonArray.toString() + " }", new Callable() {
|
||||
Object param = NativeJSON.parse(rhino, scope, jsonArray.toString(), (context, scriptable, scriptable1, objects) -> objects[1]);
|
||||
return param;
|
||||
}
|
||||
|
||||
private String readFile(String filename) throws IOException {
|
||||
byte[] bytes = mScriptReader.readFile(filename);
|
||||
String string = new String(bytes, StandardCharsets.UTF_8);
|
||||
if (string.startsWith("#!/usr/bin/env node")) {
|
||||
string = string.substring(20);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,238 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSAMA
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.IobTotal
|
||||
import info.nightscout.androidaps.data.MealData
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.mozilla.javascript.*
|
||||
import org.mozilla.javascript.Function
|
||||
import java.io.IOException
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.nio.charset.StandardCharsets
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.min
|
||||
|
||||
class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader, injector: HasAndroidInjector) {
|
||||
|
||||
private val injector: HasAndroidInjector
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var openHumansUploader: OpenHumansUploader
|
||||
|
||||
private val mScriptReader: ScriptReader
|
||||
private var profile = JSONObject()
|
||||
private var glucoseStatus = JSONObject()
|
||||
private var iobData: JSONArray? = null
|
||||
private var mealData = JSONObject()
|
||||
private var currentTemp = JSONObject()
|
||||
private var autosensData = JSONObject()
|
||||
|
||||
var currentTempParam: String? = null
|
||||
private set
|
||||
var iobDataParam: String? = null
|
||||
private set
|
||||
var glucoseStatusParam: String? = null
|
||||
private set
|
||||
var profileParam: String? = null
|
||||
private set
|
||||
var mealDataParam: String? = null
|
||||
private set
|
||||
var scriptDebug = ""
|
||||
private set
|
||||
|
||||
operator fun invoke(): DetermineBasalResultAMA? {
|
||||
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
|
||||
aapsLogger.debug(LTag.APS, "Glucose status: " + glucoseStatus.toString().also { glucoseStatusParam = it })
|
||||
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Current temp: " + currentTemp.toString().also { currentTempParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Profile: " + profile.toString().also { profileParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Meal data: " + mealData.toString().also { mealDataParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Autosens data: $autosensData")
|
||||
var determineBasalResultAMA: DetermineBasalResultAMA? = null
|
||||
val rhino = Context.enter()
|
||||
val scope: Scriptable = rhino.initStandardObjects()
|
||||
// Turn off optimization to make Rhino Android compatible
|
||||
rhino.optimizationLevel = -1
|
||||
try {
|
||||
|
||||
//register logger callback for console.log and console.error
|
||||
ScriptableObject.defineClass(scope, LoggerCallback::class.java)
|
||||
val myLogger = rhino.newObject(scope, "LoggerCallback", null)
|
||||
scope.put("console2", scope, myLogger)
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null)
|
||||
|
||||
//set module parent
|
||||
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null)
|
||||
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null)
|
||||
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null)
|
||||
|
||||
//generate functions "determine_basal" and "setTempBasal"
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/determine-basal.js"), "JavaScript", 0, null)
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/basal-set-temp.js"), "setTempBasal.js", 0, null)
|
||||
val determineBasalObj = scope["determine_basal", scope]
|
||||
val setTempBasalFunctionsObj = scope["tempBasalFunctions", scope]
|
||||
|
||||
//call determine-basal
|
||||
if (determineBasalObj is Function && setTempBasalFunctionsObj is NativeObject) {
|
||||
|
||||
//prepare parameters
|
||||
val params = arrayOf(
|
||||
makeParam(glucoseStatus, rhino, scope),
|
||||
makeParam(currentTemp, rhino, scope),
|
||||
makeParamArray(iobData, rhino, scope),
|
||||
makeParam(profile, rhino, scope),
|
||||
makeParam(autosensData, rhino, scope),
|
||||
makeParam(mealData, rhino, scope),
|
||||
setTempBasalFunctionsObj)
|
||||
val jsResult = determineBasalObj.call(rhino, scope, scope, params) as NativeObject
|
||||
scriptDebug = LoggerCallback.scriptDebug
|
||||
|
||||
// Parse the jsResult object to a JSON-String
|
||||
val result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString()
|
||||
aapsLogger.debug(LTag.APS, "Result: $result")
|
||||
try {
|
||||
val resultJson = JSONObject(result)
|
||||
openHumansUploader.enqueueAMAData(profile, glucoseStatus, iobData, mealData, currentTemp, autosensData, resultJson)
|
||||
determineBasalResultAMA = DetermineBasalResultAMA(injector, jsResult, resultJson)
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e)
|
||||
}
|
||||
} else {
|
||||
aapsLogger.error(LTag.APS, "Problem loading JS Functions")
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
aapsLogger.error(LTag.APS, "IOException")
|
||||
} catch (e: RhinoException) {
|
||||
aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString())
|
||||
} catch (e: IllegalAccessException) {
|
||||
aapsLogger.error(LTag.APS, e.toString())
|
||||
} catch (e: InstantiationException) {
|
||||
aapsLogger.error(LTag.APS, e.toString())
|
||||
} catch (e: InvocationTargetException) {
|
||||
aapsLogger.error(LTag.APS, e.toString())
|
||||
} finally {
|
||||
Context.exit()
|
||||
}
|
||||
glucoseStatusParam = glucoseStatus.toString()
|
||||
iobDataParam = iobData.toString()
|
||||
currentTempParam = currentTemp.toString()
|
||||
profileParam = profile.toString()
|
||||
mealDataParam = mealData.toString()
|
||||
return determineBasalResultAMA
|
||||
}
|
||||
|
||||
@Throws(JSONException::class) fun setData(profile: Profile,
|
||||
maxIob: Double,
|
||||
maxBasal: Double,
|
||||
minBg: Double,
|
||||
maxBg: Double,
|
||||
targetBg: Double,
|
||||
basalRate: Double,
|
||||
iobArray: Array<IobTotal?>?,
|
||||
glucoseStatus: GlucoseStatus,
|
||||
mealData: MealData,
|
||||
autosensDataRatio: Double,
|
||||
tempTargetSet: Boolean) {
|
||||
this.profile = JSONObject()
|
||||
this.profile.put("max_iob", maxIob)
|
||||
this.profile.put("dia", min(profile.dia, 3.0))
|
||||
this.profile.put("type", "current")
|
||||
this.profile.put("max_daily_basal", profile.maxDailyBasal)
|
||||
this.profile.put("max_basal", maxBasal)
|
||||
this.profile.put("min_bg", minBg)
|
||||
this.profile.put("max_bg", maxBg)
|
||||
this.profile.put("target_bg", targetBg)
|
||||
this.profile.put("carb_ratio", profile.ic)
|
||||
this.profile.put("sens", profile.isfMgdl)
|
||||
this.profile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3))
|
||||
this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
|
||||
this.profile.put("skip_neutral_temps", true)
|
||||
this.profile.put("current_basal", basalRate)
|
||||
this.profile.put("temptargetSet", tempTargetSet)
|
||||
this.profile.put("autosens_adjust_targets", sp.getBoolean(R.string.key_openapsama_autosens_adjusttargets, true))
|
||||
//align with max-absorption model in AMA sensitivity
|
||||
if (mealData.usedMinCarbsImpact > 0) {
|
||||
this.profile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact)
|
||||
} else {
|
||||
this.profile.put("min_5m_carbimpact", sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact))
|
||||
}
|
||||
if (profileFunction.getUnits() == Constants.MMOL) {
|
||||
this.profile.put("out_units", "mmol/L")
|
||||
}
|
||||
val now = System.currentTimeMillis()
|
||||
val tb = treatmentsPlugin.getTempBasalFromHistory(now)
|
||||
currentTemp = JSONObject()
|
||||
currentTemp.put("temp", "absolute")
|
||||
currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0)
|
||||
currentTemp.put("rate", tb?.tempBasalConvertedToAbsolute(now, profile) ?: 0.0)
|
||||
|
||||
// as we have non default temps longer than 30 minutes
|
||||
val tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis())
|
||||
if (tempBasal != null) {
|
||||
currentTemp.put("minutesrunning", tempBasal.realDuration)
|
||||
}
|
||||
iobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray)
|
||||
this.glucoseStatus = JSONObject()
|
||||
this.glucoseStatus.put("glucose", glucoseStatus.glucose)
|
||||
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
|
||||
this.glucoseStatus.put("delta", glucoseStatus.short_avgdelta)
|
||||
} else {
|
||||
this.glucoseStatus.put("delta", glucoseStatus.delta)
|
||||
}
|
||||
this.glucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta)
|
||||
this.glucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta)
|
||||
this.mealData = JSONObject()
|
||||
this.mealData.put("carbs", mealData.carbs)
|
||||
this.mealData.put("boluses", mealData.boluses)
|
||||
this.mealData.put("mealCOB", mealData.mealCOB)
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
autosensData.put("ratio", autosensDataRatio)
|
||||
} else {
|
||||
autosensData.put("ratio", 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeParam(jsonObject: JSONObject?, rhino: Context, scope: Scriptable): Any {
|
||||
return if (jsonObject == null) Undefined.instance else NativeJSON.parse(rhino, scope, jsonObject.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
|
||||
}
|
||||
|
||||
private fun makeParamArray(jsonArray: JSONArray?, rhino: Context, scope: Scriptable): Any {
|
||||
return NativeJSON.parse(rhino, scope, jsonArray.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
|
||||
}
|
||||
|
||||
@Throws(IOException::class) private fun readFile(filename: String): String {
|
||||
val bytes = mScriptReader.readFile(filename)
|
||||
var string = String(bytes, StandardCharsets.UTF_8)
|
||||
if (string.startsWith("#!/usr/bin/env node")) {
|
||||
string = string.substring(20)
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
init {
|
||||
injector.androidInjector().inject(this)
|
||||
mScriptReader = scriptReader
|
||||
this.injector = injector
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSAMA;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
|
||||
public class DetermineBasalResultAMA extends APSResult {
|
||||
private AAPSLogger aapsLogger;
|
||||
|
||||
private double eventualBG;
|
||||
private double snoozeBG;
|
||||
|
||||
DetermineBasalResultAMA(HasAndroidInjector injector, NativeObject result, JSONObject j) {
|
||||
this(injector);
|
||||
date = DateUtil.now();
|
||||
json = j;
|
||||
if (result.containsKey("error")) {
|
||||
reason = result.get("error").toString();
|
||||
tempBasalRequested = false;
|
||||
rate = -1;
|
||||
duration = -1;
|
||||
} else {
|
||||
reason = result.get("reason").toString();
|
||||
if (result.containsKey("eventualBG")) eventualBG = (Double) result.get("eventualBG");
|
||||
if (result.containsKey("snoozeBG")) snoozeBG = (Double) result.get("snoozeBG");
|
||||
if (result.containsKey("rate")) {
|
||||
rate = (Double) result.get("rate");
|
||||
if (rate < 0d) rate = 0d;
|
||||
tempBasalRequested = true;
|
||||
} else {
|
||||
rate = -1;
|
||||
tempBasalRequested = false;
|
||||
}
|
||||
if (result.containsKey("duration")) {
|
||||
duration = ((Double) result.get("duration")).intValue();
|
||||
//changeRequested as above
|
||||
} else {
|
||||
duration = -1;
|
||||
tempBasalRequested = false;
|
||||
}
|
||||
}
|
||||
bolusRequested = false;
|
||||
}
|
||||
|
||||
private DetermineBasalResultAMA(HasAndroidInjector injector) {
|
||||
super(injector);
|
||||
hasPredictions = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetermineBasalResultAMA newAndClone(HasAndroidInjector injector) {
|
||||
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA(injector);
|
||||
doClone(newResult);
|
||||
|
||||
newResult.eventualBG = eventualBG;
|
||||
newResult.snoozeBG = snoozeBG;
|
||||
return newResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject json() {
|
||||
try {
|
||||
JSONObject ret = new JSONObject(this.json.toString());
|
||||
return ret;
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSAMA
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.mozilla.javascript.NativeObject
|
||||
|
||||
class DetermineBasalResultAMA private constructor(injector: HasAndroidInjector) : APSResult(injector) {
|
||||
|
||||
private var eventualBG = 0.0
|
||||
private var snoozeBG = 0.0
|
||||
|
||||
internal constructor(injector: HasAndroidInjector, result: NativeObject, j: JSONObject) : this(injector) {
|
||||
date = DateUtil.now()
|
||||
json = j
|
||||
if (result.containsKey("error")) {
|
||||
reason = result["error"].toString()
|
||||
tempBasalRequested = false
|
||||
rate = (-1).toDouble()
|
||||
duration = -1
|
||||
} else {
|
||||
reason = result["reason"].toString()
|
||||
if (result.containsKey("eventualBG")) eventualBG = result["eventualBG"] as Double
|
||||
if (result.containsKey("snoozeBG")) snoozeBG = result["snoozeBG"] as Double
|
||||
if (result.containsKey("rate")) {
|
||||
rate = result["rate"] as Double
|
||||
if (rate < 0.0) rate = 0.0
|
||||
tempBasalRequested = true
|
||||
} else {
|
||||
rate = (-1).toDouble()
|
||||
tempBasalRequested = false
|
||||
}
|
||||
if (result.containsKey("duration")) {
|
||||
duration = (result["duration"] as Double).toInt()
|
||||
//changeRequested as above
|
||||
} else {
|
||||
duration = -1
|
||||
tempBasalRequested = false
|
||||
}
|
||||
}
|
||||
bolusRequested = false
|
||||
}
|
||||
|
||||
override fun newAndClone(injector: HasAndroidInjector): DetermineBasalResultAMA {
|
||||
val newResult = DetermineBasalResultAMA(injector)
|
||||
doClone(newResult)
|
||||
newResult.eventualBG = eventualBG
|
||||
newResult.snoozeBG = snoozeBG
|
||||
return newResult
|
||||
}
|
||||
|
||||
override fun json(): JSONObject? {
|
||||
try {
|
||||
return JSONObject(json.toString())
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
init {
|
||||
hasPredictions = true
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import dagger.android.support.DaggerFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||
|
@ -15,34 +16,42 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.JSONFormatter
|
||||
import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.openapsama_fragment.*
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import javax.inject.Inject
|
||||
|
||||
class OpenAPSAMAFragment : DaggerFragment() {
|
||||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var openAPSAMAPlugin: OpenAPSAMAPlugin
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
private var _binding: OpenapsamaFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.openapsama_fragment, container, false)
|
||||
savedInstanceState: Bundle?): View {
|
||||
_binding = OpenapsamaFragmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
openapsma_run.setOnClickListener {
|
||||
binding.run.setOnClickListener {
|
||||
openAPSAMAPlugin.invoke("OpenAPSAMA button", false)
|
||||
}
|
||||
}
|
||||
|
@ -53,16 +62,16 @@ class OpenAPSAMAFragment : DaggerFragment() {
|
|||
|
||||
disposable += rxBus
|
||||
.toObservable(EventOpenAPSUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
updateGUI()
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventOpenAPSUpdateResultGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
updateResultGUI(it.text)
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
}, fabricPrivacy::logException)
|
||||
|
||||
updateGUI()
|
||||
}
|
||||
|
@ -73,47 +82,53 @@ class OpenAPSAMAFragment : DaggerFragment() {
|
|||
disposable.clear()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun updateGUI() {
|
||||
if (openapsma_result == null) return
|
||||
if (_binding == null) return
|
||||
openAPSAMAPlugin.lastAPSResult?.let { lastAPSResult ->
|
||||
openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
|
||||
openapsma_request.text = lastAPSResult.toSpanned()
|
||||
binding.result.text = JSONFormatter.format(lastAPSResult.json)
|
||||
binding.request.text = lastAPSResult.toSpanned()
|
||||
}
|
||||
openAPSAMAPlugin.lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS ->
|
||||
openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
|
||||
openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
|
||||
binding.glucosestatus.text = JSONFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
|
||||
binding.currenttemp.text = JSONFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
|
||||
try {
|
||||
val iobArray = JSONArray(determineBasalAdapterAMAJS.iobDataParam)
|
||||
openapsma_iobdata.text = TextUtils.concat(resourceHelper.gs(R.string.array_of_elements, iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0)))
|
||||
binding.iobdata.text = TextUtils.concat(resourceHelper.gs(R.string.array_of_elements, iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0)))
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e)
|
||||
@Suppress("SetTextI18n")
|
||||
openapsma_iobdata.text = "JSONException see log for details"
|
||||
binding.iobdata.text = "JSONException see log for details"
|
||||
}
|
||||
|
||||
openapsma_profile.text = JSONFormatter.format(determineBasalAdapterAMAJS.profileParam)
|
||||
openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterAMAJS.mealDataParam)
|
||||
openapsma_scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug
|
||||
binding.profile.text = JSONFormatter.format(determineBasalAdapterAMAJS.profileParam)
|
||||
binding.mealdata.text = JSONFormatter.format(determineBasalAdapterAMAJS.mealDataParam)
|
||||
binding.scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug
|
||||
}
|
||||
if (openAPSAMAPlugin.lastAPSRun != 0L) {
|
||||
openapsma_lastrun.text = dateUtil.dateAndTimeString(openAPSAMAPlugin.lastAPSRun)
|
||||
binding.lastrun.text = dateUtil.dateAndTimeString(openAPSAMAPlugin.lastAPSRun)
|
||||
}
|
||||
openAPSAMAPlugin.lastAutosensResult?.let {
|
||||
openapsma_autosensdata.text = JSONFormatter.format(it.json())
|
||||
openAPSAMAPlugin.lastAutosensResult.let {
|
||||
binding.autosensdata.text = JSONFormatter.format(it.json())
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateResultGUI(text: String) {
|
||||
openapsma_result.text = text
|
||||
openapsma_glucosestatus.text = ""
|
||||
openapsma_currenttemp.text = ""
|
||||
openapsma_iobdata.text = ""
|
||||
openapsma_profile.text = ""
|
||||
openapsma_mealdata.text = ""
|
||||
openapsma_autosensdata.text = ""
|
||||
openapsma_scriptdebugdata.text = ""
|
||||
openapsma_request.text = ""
|
||||
openapsma_lastrun.text = ""
|
||||
binding.result.text = text
|
||||
binding.glucosestatus.text = ""
|
||||
binding.currenttemp.text = ""
|
||||
binding.iobdata.text = ""
|
||||
binding.profile.text = ""
|
||||
binding.mealdata.text = ""
|
||||
binding.autosensdata.text = ""
|
||||
binding.scriptdebugdata.text = ""
|
||||
binding.request.text = ""
|
||||
binding.lastrun.text = ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,263 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSAMA;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader;
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.HardLimits;
|
||||
import info.nightscout.androidaps.utils.Profiler;
|
||||
import info.nightscout.androidaps.utils.Round;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
|
||||
@Singleton
|
||||
public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
|
||||
private final AAPSLogger aapsLogger;
|
||||
private final RxBusWrapper rxBus;
|
||||
private final ConstraintChecker constraintChecker;
|
||||
private final ResourceHelper resourceHelper;
|
||||
private final ProfileFunction profileFunction;
|
||||
private final Context context;
|
||||
private final ActivePluginProvider activePlugin;
|
||||
private final TreatmentsPlugin treatmentsPlugin;
|
||||
private final IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
private final HardLimits hardLimits;
|
||||
private final Profiler profiler;
|
||||
private final FabricPrivacy fabricPrivacy;
|
||||
|
||||
// last values
|
||||
DetermineBasalAdapterAMAJS lastDetermineBasalAdapterAMAJS = null;
|
||||
long lastAPSRun = 0;
|
||||
DetermineBasalResultAMA lastAPSResult = null;
|
||||
AutosensResult lastAutosensResult = null;
|
||||
|
||||
@Inject
|
||||
public OpenAPSAMAPlugin(
|
||||
HasAndroidInjector injector,
|
||||
AAPSLogger aapsLogger,
|
||||
RxBusWrapper rxBus,
|
||||
ConstraintChecker constraintChecker,
|
||||
ResourceHelper resourceHelper,
|
||||
ProfileFunction profileFunction,
|
||||
Context context,
|
||||
ActivePluginProvider activePlugin,
|
||||
TreatmentsPlugin treatmentsPlugin,
|
||||
IobCobCalculatorPlugin iobCobCalculatorPlugin,
|
||||
HardLimits hardLimits,
|
||||
Profiler profiler,
|
||||
FabricPrivacy fabricPrivacy
|
||||
) {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.APS)
|
||||
.fragmentClass(OpenAPSAMAFragment.class.getName())
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.openapsama)
|
||||
.shortName(R.string.oaps_shortname)
|
||||
.preferencesId(R.xml.pref_openapsama)
|
||||
.description(R.string.description_ama),
|
||||
aapsLogger, resourceHelper, injector
|
||||
);
|
||||
this.aapsLogger = aapsLogger;
|
||||
this.rxBus = rxBus;
|
||||
this.constraintChecker = constraintChecker;
|
||||
this.resourceHelper = resourceHelper;
|
||||
this.profileFunction = profileFunction;
|
||||
this.context = context;
|
||||
this.activePlugin = activePlugin;
|
||||
this.treatmentsPlugin = treatmentsPlugin;
|
||||
this.iobCobCalculatorPlugin = iobCobCalculatorPlugin;
|
||||
this.hardLimits = hardLimits;
|
||||
this.profiler = profiler;
|
||||
this.fabricPrivacy = fabricPrivacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialEnableCondition() {
|
||||
try {
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
return pump.getPumpDescription().isTempBasalCapable;
|
||||
} catch (Exception ignored) {
|
||||
// may fail during initialization
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialShowInListCondition() {
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
return pump.getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public APSResult getLastAPSResult() {
|
||||
return lastAPSResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastAPSRun() {
|
||||
return lastAPSRun;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String initiator, boolean tempBasalFallback) {
|
||||
aapsLogger.debug(LTag.APS, "invoke from " + initiator + " tempBasalFallback: " + tempBasalFallback);
|
||||
lastAPSResult = null;
|
||||
DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS;
|
||||
determineBasalAdapterAMAJS = new DetermineBasalAdapterAMAJS(new ScriptReader(context), getInjector());
|
||||
|
||||
GlucoseStatus glucoseStatus = new GlucoseStatus(getInjector()).getGlucoseStatusData();
|
||||
Profile profile = profileFunction.getProfile();
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
|
||||
if (profile == null) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.noprofileselected)));
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.noprofileselected));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isEnabled(PluginType.APS)) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_disabled)));
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.openapsma_disabled));
|
||||
return;
|
||||
}
|
||||
|
||||
if (glucoseStatus == null) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_noglucosedata)));
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.openapsma_noglucosedata));
|
||||
return;
|
||||
}
|
||||
|
||||
double maxBasal = constraintChecker.getMaxBasalAllowed(profile).value();
|
||||
double minBg = profile.getTargetLowMgdl();
|
||||
double maxBg = profile.getTargetHighMgdl();
|
||||
double targetBg = profile.getTargetMgdl();
|
||||
|
||||
minBg = Round.roundTo(minBg, 0.1d);
|
||||
maxBg = Round.roundTo(maxBg, 0.1d);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
long startPart = System.currentTimeMillis();
|
||||
IobTotal[] iobArray = iobCobCalculatorPlugin.calculateIobArrayInDia(profile);
|
||||
profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart);
|
||||
|
||||
startPart = System.currentTimeMillis();
|
||||
MealData mealData = iobCobCalculatorPlugin.getMealData();
|
||||
profiler.log(LTag.APS, "getMealData()", startPart);
|
||||
|
||||
double maxIob = constraintChecker.getMaxIOBAllowed().value();
|
||||
|
||||
minBg = hardLimits.verifyHardLimits(minBg, "minBg", hardLimits.getVERY_HARD_LIMIT_MIN_BG()[0], hardLimits.getVERY_HARD_LIMIT_MIN_BG()[1]);
|
||||
maxBg = hardLimits.verifyHardLimits(maxBg, "maxBg", hardLimits.getVERY_HARD_LIMIT_MAX_BG()[0], hardLimits.getVERY_HARD_LIMIT_MAX_BG()[1]);
|
||||
targetBg = hardLimits.verifyHardLimits(targetBg, "targetBg", hardLimits.getVERY_HARD_LIMIT_TARGET_BG()[0], hardLimits.getVERY_HARD_LIMIT_TARGET_BG()[1]);
|
||||
|
||||
boolean isTempTarget = false;
|
||||
TempTarget tempTarget = treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis());
|
||||
if (tempTarget != null) {
|
||||
isTempTarget = true;
|
||||
minBg = hardLimits.verifyHardLimits(tempTarget.low, "minBg", hardLimits.getVERY_HARD_LIMIT_TEMP_MIN_BG()[0], hardLimits.getVERY_HARD_LIMIT_TEMP_MIN_BG()[1]);
|
||||
maxBg = hardLimits.verifyHardLimits(tempTarget.high, "maxBg", hardLimits.getVERY_HARD_LIMIT_TEMP_MAX_BG()[0], hardLimits.getVERY_HARD_LIMIT_TEMP_MAX_BG()[1]);
|
||||
targetBg = hardLimits.verifyHardLimits(tempTarget.target(), "targetBg", hardLimits.getVERY_HARD_LIMIT_TEMP_TARGET_BG()[0], hardLimits.getVERY_HARD_LIMIT_TEMP_TARGET_BG()[1]);
|
||||
}
|
||||
|
||||
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getDia(), "dia", hardLimits.minDia(), hardLimits.maxDia()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), "sens", hardLimits.getMINISF(), hardLimits.getMAXISF()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.02, hardLimits.maxBasal()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, hardLimits.maxBasal()))
|
||||
return;
|
||||
|
||||
startPart = System.currentTimeMillis();
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
AutosensData autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin");
|
||||
if (autosensData == null) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata)));
|
||||
return;
|
||||
}
|
||||
lastAutosensResult = autosensData.autosensResult;
|
||||
} else {
|
||||
lastAutosensResult = new AutosensResult();
|
||||
lastAutosensResult.sensResult = "autosens disabled";
|
||||
}
|
||||
profiler.log(LTag.APS, "detectSensitivityandCarbAbsorption()", startPart);
|
||||
profiler.log(LTag.APS, "AMA data gathering", start);
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, activePlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
|
||||
lastAutosensResult.ratio, //autosensDataRatio
|
||||
isTempTarget
|
||||
);
|
||||
} catch (JSONException e) {
|
||||
fabricPrivacy.logException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke();
|
||||
profiler.log(LTag.APS, "AMA calculation", start);
|
||||
// Fix bug determine basal
|
||||
if (determineBasalResultAMA == null) {
|
||||
aapsLogger.error(LTag.APS, "SMB calculation returned null");
|
||||
lastDetermineBasalAdapterAMAJS = null;
|
||||
lastAPSResult = null;
|
||||
lastAPSRun = 0;
|
||||
} else {
|
||||
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !treatmentsPlugin.isTempBasalInProgress())
|
||||
determineBasalResultAMA.tempBasalRequested = false;
|
||||
|
||||
determineBasalResultAMA.iob = iobArray[0];
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now));
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e);
|
||||
}
|
||||
|
||||
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS;
|
||||
lastAPSResult = determineBasalResultAMA;
|
||||
lastAPSRun = now;
|
||||
}
|
||||
rxBus.send(new EventOpenAPSUpdateGui());
|
||||
|
||||
//deviceStatus.suggested = determineBasalResultAMA.json;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSAMA
|
||||
|
||||
import android.content.Context
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
import info.nightscout.androidaps.utils.Profiler
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import org.json.JSONException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
open class OpenAPSAMAPlugin @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
private val rxBus: RxBusWrapper,
|
||||
private val constraintChecker: ConstraintChecker,
|
||||
resourceHelper: ResourceHelper,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val context: Context,
|
||||
private val activePlugin: ActivePluginProvider,
|
||||
private val treatmentsPlugin: TreatmentsPlugin,
|
||||
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
|
||||
private val hardLimits: HardLimits,
|
||||
private val profiler: Profiler,
|
||||
private val fabricPrivacy: FabricPrivacy
|
||||
) : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.APS)
|
||||
.fragmentClass(OpenAPSAMAFragment::class.java.name)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.openapsama)
|
||||
.shortName(R.string.oaps_shortname)
|
||||
.preferencesId(R.xml.pref_openapsama)
|
||||
.description(R.string.description_ama),
|
||||
aapsLogger, resourceHelper, injector
|
||||
), APSInterface {
|
||||
|
||||
// last values
|
||||
override var lastAPSRun: Long = 0
|
||||
override var lastAPSResult: DetermineBasalResultAMA? = null
|
||||
var lastDetermineBasalAdapterAMAJS: DetermineBasalAdapterAMAJS? = null
|
||||
var lastAutosensResult: AutosensResult = AutosensResult()
|
||||
|
||||
override fun specialEnableCondition(): Boolean {
|
||||
return try {
|
||||
val pump = activePlugin.activePump
|
||||
pump.pumpDescription.isTempBasalCapable
|
||||
} catch (ignored: Exception) {
|
||||
// may fail during initialization
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun specialShowInListCondition(): Boolean {
|
||||
val pump = activePlugin.activePump
|
||||
return pump.pumpDescription.isTempBasalCapable
|
||||
}
|
||||
|
||||
override fun invoke(initiator: String, tempBasalFallback: Boolean) {
|
||||
aapsLogger.debug(LTag.APS, "invoke from $initiator tempBasalFallback: $tempBasalFallback")
|
||||
lastAPSResult = null
|
||||
val determineBasalAdapterAMAJS = DetermineBasalAdapterAMAJS(ScriptReader(context), injector)
|
||||
val glucoseStatus = GlucoseStatus(injector).glucoseStatusData
|
||||
val profile = profileFunction.getProfile()
|
||||
val pump = activePlugin.activePump
|
||||
if (profile == null) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.noprofileselected)))
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.noprofileselected))
|
||||
return
|
||||
}
|
||||
if (!isEnabled(PluginType.APS)) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_disabled)))
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.openapsma_disabled))
|
||||
return
|
||||
}
|
||||
if (glucoseStatus == null) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_noglucosedata)))
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.openapsma_noglucosedata))
|
||||
return
|
||||
}
|
||||
val inputConstraints = Constraint(0.0) // fake. only for collecting all results
|
||||
val maxBasal = constraintChecker.getMaxBasalAllowed(profile).also {
|
||||
inputConstraints.copyReasons(it)
|
||||
}.value()
|
||||
var start = System.currentTimeMillis()
|
||||
var startPart = System.currentTimeMillis()
|
||||
val iobArray = iobCobCalculatorPlugin.calculateIobArrayInDia(profile)
|
||||
profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart)
|
||||
startPart = System.currentTimeMillis()
|
||||
val mealData = iobCobCalculatorPlugin.mealData
|
||||
profiler.log(LTag.APS, "getMealData()", startPart)
|
||||
val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint ->
|
||||
inputConstraints.copyReasons(maxIOBAllowedConstraint)
|
||||
}.value()
|
||||
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetLowMgdl, 0.1), "minBg", hardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble())
|
||||
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), "maxBg", hardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
|
||||
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, "targetBg", hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
|
||||
var isTempTarget = false
|
||||
treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis())?.let { tempTarget ->
|
||||
isTempTarget = true
|
||||
minBg = hardLimits.verifyHardLimits(tempTarget.low, "minBg", hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
|
||||
maxBg = hardLimits.verifyHardLimits(tempTarget.high, "maxBg", hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble())
|
||||
targetBg = hardLimits.verifyHardLimits(tempTarget.target(), "targetBg", hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble())
|
||||
}
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.dia, "dia", hardLimits.minDia(), hardLimits.maxDia())) return
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC())) return
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, "sens", hardLimits.MINISF, hardLimits.MAXISF)) return
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, "max_daily_basal", 0.02, hardLimits.maxBasal())) return
|
||||
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, "current_basal", 0.01, hardLimits.maxBasal())) return
|
||||
startPart = System.currentTimeMillis()
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin")
|
||||
if (autosensData == null) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata)))
|
||||
return
|
||||
}
|
||||
lastAutosensResult = autosensData.autosensResult
|
||||
} else {
|
||||
lastAutosensResult.sensResult = "autosens disabled"
|
||||
}
|
||||
profiler.log(LTag.APS, "detectSensitivityAndCarbAbsorption()", startPart)
|
||||
profiler.log(LTag.APS, "AMA data gathering", start)
|
||||
start = System.currentTimeMillis()
|
||||
try {
|
||||
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, activePlugin.activePump.baseBasalRate, iobArray, glucoseStatus, mealData,
|
||||
lastAutosensResult.ratio,
|
||||
isTempTarget
|
||||
)
|
||||
} catch (e: JSONException) {
|
||||
fabricPrivacy.logException(e)
|
||||
return
|
||||
}
|
||||
val determineBasalResultAMA = determineBasalAdapterAMAJS.invoke()
|
||||
profiler.log(LTag.APS, "AMA calculation", start)
|
||||
// Fix bug determine basal
|
||||
if (determineBasalResultAMA == null) {
|
||||
aapsLogger.error(LTag.APS, "SMB calculation returned null")
|
||||
lastDetermineBasalAdapterAMAJS = null
|
||||
lastAPSResult = null
|
||||
lastAPSRun = 0
|
||||
} else {
|
||||
if (determineBasalResultAMA.rate == 0.0 && determineBasalResultAMA.duration == 0 && !treatmentsPlugin.isTempBasalInProgress) determineBasalResultAMA.tempBasalRequested = false
|
||||
determineBasalResultAMA.iob = iobArray[0]
|
||||
val now = System.currentTimeMillis()
|
||||
determineBasalResultAMA.json?.put("timestamp", DateUtil.toISOString(now))
|
||||
determineBasalResultAMA.inputConstraints = inputConstraints
|
||||
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS
|
||||
lastAPSResult = determineBasalResultAMA
|
||||
lastAPSRun = now
|
||||
}
|
||||
rxBus.send(EventOpenAPSUpdateGui())
|
||||
|
||||
//deviceStatus.suggested = determineBasalResultAMA.json;
|
||||
}
|
||||
}
|
|
@ -1,386 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSSMB;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Function;
|
||||
import org.mozilla.javascript.NativeJSON;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
import org.mozilla.javascript.RhinoException;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
import org.mozilla.javascript.Undefined;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader;
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.SafeParse;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
|
||||
public class DetermineBasalAdapterSMBJS {
|
||||
private final HasAndroidInjector injector;
|
||||
@Inject AAPSLogger aapsLogger;
|
||||
@Inject ConstraintChecker constraintChecker;
|
||||
@Inject SP sp;
|
||||
@Inject ResourceHelper resourceHelper;
|
||||
@Inject ProfileFunction profileFunction;
|
||||
@Inject TreatmentsPlugin treatmentsPlugin;
|
||||
@Inject ActivePluginProvider activePluginProvider;
|
||||
@Inject OpenHumansUploader openHumansUploader;
|
||||
|
||||
|
||||
private final ScriptReader mScriptReader;
|
||||
private JSONObject mProfile;
|
||||
private JSONObject mGlucoseStatus;
|
||||
private JSONArray mIobData;
|
||||
private JSONObject mMealData;
|
||||
private JSONObject mCurrentTemp;
|
||||
private JSONObject mAutosensData = null;
|
||||
private boolean mMicrobolusAllowed;
|
||||
private boolean mSMBAlwaysAllowed;
|
||||
private long mCurrentTime;
|
||||
private boolean mIsSaveCgmSource;
|
||||
|
||||
private String storedCurrentTemp = null;
|
||||
private String storedIobData = null;
|
||||
|
||||
private String storedGlucoseStatus = null;
|
||||
private String storedProfile = null;
|
||||
private String storedMeal_data = null;
|
||||
private String storedAutosens_data = null;
|
||||
private String storedMicroBolusAllowed = null;
|
||||
private String storedSMBAlwaysAllowed = null;
|
||||
private String storedCurrentTime = null;
|
||||
|
||||
private String scriptDebug = "";
|
||||
|
||||
/**
|
||||
* Main code
|
||||
*/
|
||||
|
||||
DetermineBasalAdapterSMBJS(ScriptReader scriptReader, HasAndroidInjector injector) {
|
||||
mScriptReader = scriptReader;
|
||||
this.injector = injector;
|
||||
injector.androidInjector().inject(this);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public DetermineBasalResultSMB invoke() {
|
||||
|
||||
|
||||
aapsLogger.debug(LTag.APS, ">>> Invoking detemine_basal <<<");
|
||||
aapsLogger.debug(LTag.APS, "Glucose status: " + (storedGlucoseStatus = mGlucoseStatus.toString()));
|
||||
aapsLogger.debug(LTag.APS, "IOB data: " + (storedIobData = mIobData.toString()));
|
||||
aapsLogger.debug(LTag.APS, "Current temp: " + (storedCurrentTemp = mCurrentTemp.toString()));
|
||||
aapsLogger.debug(LTag.APS, "Profile: " + (storedProfile = mProfile.toString()));
|
||||
aapsLogger.debug(LTag.APS, "Meal data: " + (storedMeal_data = mMealData.toString()));
|
||||
if (mAutosensData != null)
|
||||
aapsLogger.debug(LTag.APS, "Autosens data: " + (storedAutosens_data = mAutosensData.toString()));
|
||||
else
|
||||
aapsLogger.debug(LTag.APS, "Autosens data: " + (storedAutosens_data = "undefined"));
|
||||
aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined");
|
||||
aapsLogger.debug(LTag.APS, "MicroBolusAllowed: " + (storedMicroBolusAllowed = "" + mMicrobolusAllowed));
|
||||
aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: " + (storedSMBAlwaysAllowed = "" + mSMBAlwaysAllowed));
|
||||
aapsLogger.debug(LTag.APS, "CurrentTime: " + (storedCurrentTime = "" + mCurrentTime));
|
||||
aapsLogger.debug(LTag.APS, "isSaveCgmSource: " + mIsSaveCgmSource);
|
||||
|
||||
|
||||
DetermineBasalResultSMB determineBasalResultSMB = null;
|
||||
|
||||
Context rhino = Context.enter();
|
||||
Scriptable scope = rhino.initStandardObjects();
|
||||
// Turn off optimization to make Rhino Android compatible
|
||||
rhino.setOptimizationLevel(-1);
|
||||
|
||||
try {
|
||||
|
||||
//register logger callback for console.log and console.error
|
||||
ScriptableObject.defineClass(scope, LoggerCallback.class);
|
||||
Scriptable myLogger = rhino.newObject(scope, "LoggerCallback", null);
|
||||
scope.put("console2", scope, myLogger);
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null);
|
||||
|
||||
//set module parent
|
||||
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null);
|
||||
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null);
|
||||
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null);
|
||||
|
||||
//generate functions "determine_basal" and "setTempBasal"
|
||||
rhino.evaluateString(scope, readFile("OpenAPSSMB/determine-basal.js"), "JavaScript", 0, null);
|
||||
rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null);
|
||||
Object determineBasalObj = scope.get("determine_basal", scope);
|
||||
Object setTempBasalFunctionsObj = scope.get("tempBasalFunctions", scope);
|
||||
|
||||
//call determine-basal
|
||||
if (determineBasalObj instanceof Function && setTempBasalFunctionsObj instanceof NativeObject) {
|
||||
Function determineBasalJS = (Function) determineBasalObj;
|
||||
|
||||
//prepare parameters
|
||||
Object[] params = new Object[]{
|
||||
makeParam(mGlucoseStatus, rhino, scope),
|
||||
makeParam(mCurrentTemp, rhino, scope),
|
||||
makeParamArray(mIobData, rhino, scope),
|
||||
makeParam(mProfile, rhino, scope),
|
||||
makeParam(mAutosensData, rhino, scope),
|
||||
makeParam(mMealData, rhino, scope),
|
||||
setTempBasalFunctionsObj,
|
||||
new Boolean(mMicrobolusAllowed),
|
||||
makeParam(null, rhino, scope), // reservoir data as undefined
|
||||
new Long(mCurrentTime)
|
||||
};
|
||||
|
||||
|
||||
NativeObject jsResult = (NativeObject) determineBasalJS.call(rhino, scope, scope, params);
|
||||
scriptDebug = LoggerCallback.getScriptDebug();
|
||||
|
||||
// Parse the jsResult object to a JSON-String
|
||||
String result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString();
|
||||
aapsLogger.debug(LTag.APS, "Result: " + result);
|
||||
try {
|
||||
JSONObject resultJson = new JSONObject(result);
|
||||
openHumansUploader.enqueueSMBData(mProfile, mGlucoseStatus, mIobData, mMealData, mCurrentTemp, mAutosensData, mMicrobolusAllowed, mSMBAlwaysAllowed, resultJson);
|
||||
determineBasalResultSMB = new DetermineBasalResultSMB(injector, resultJson);
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e);
|
||||
}
|
||||
} else {
|
||||
aapsLogger.error(LTag.APS, "Problem loading JS Functions");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
aapsLogger.error(LTag.APS, "IOException");
|
||||
} catch (RhinoException e) {
|
||||
aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString());
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||
aapsLogger.error(LTag.APS, e.toString());
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
|
||||
storedGlucoseStatus = mGlucoseStatus.toString();
|
||||
storedIobData = mIobData.toString();
|
||||
storedCurrentTemp = mCurrentTemp.toString();
|
||||
storedProfile = mProfile.toString();
|
||||
storedMeal_data = mMealData.toString();
|
||||
|
||||
return determineBasalResultSMB;
|
||||
|
||||
}
|
||||
|
||||
String getGlucoseStatusParam() {
|
||||
return storedGlucoseStatus;
|
||||
}
|
||||
|
||||
String getCurrentTempParam() {
|
||||
return storedCurrentTemp;
|
||||
}
|
||||
|
||||
String getIobDataParam() {
|
||||
return storedIobData;
|
||||
}
|
||||
|
||||
String getProfileParam() {
|
||||
return storedProfile;
|
||||
}
|
||||
|
||||
String getMealDataParam() {
|
||||
return storedMeal_data;
|
||||
}
|
||||
|
||||
String getAutosensDataParam() {
|
||||
return storedAutosens_data;
|
||||
}
|
||||
|
||||
String getMicroBolusAllowedParam() {
|
||||
return storedMicroBolusAllowed;
|
||||
}
|
||||
|
||||
String getScriptDebug() {
|
||||
return scriptDebug;
|
||||
}
|
||||
|
||||
public void setData(Profile profile,
|
||||
double maxIob,
|
||||
double maxBasal,
|
||||
double minBg,
|
||||
double maxBg,
|
||||
double targetBg,
|
||||
double basalrate,
|
||||
IobTotal[] iobArray,
|
||||
GlucoseStatus glucoseStatus,
|
||||
MealData mealData,
|
||||
double autosensDataRatio,
|
||||
boolean tempTargetSet,
|
||||
boolean microBolusAllowed,
|
||||
boolean uamAllowed,
|
||||
boolean advancedFiltering,
|
||||
boolean isSaveCgmSource
|
||||
) throws JSONException {
|
||||
|
||||
String units = profile.getUnits();
|
||||
PumpInterface pump = activePluginProvider.getActivePump();
|
||||
Double pumpbolusstep = pump.getPumpDescription().bolusStep;
|
||||
mProfile = new JSONObject();
|
||||
|
||||
mProfile.put("max_iob", maxIob);
|
||||
//mProfile.put("dia", profile.getDia());
|
||||
mProfile.put("type", "current");
|
||||
mProfile.put("max_daily_basal", profile.getMaxDailyBasal());
|
||||
mProfile.put("max_basal", maxBasal);
|
||||
mProfile.put("min_bg", minBg);
|
||||
mProfile.put("max_bg", maxBg);
|
||||
mProfile.put("target_bg", targetBg);
|
||||
mProfile.put("carb_ratio", profile.getIc());
|
||||
mProfile.put("sens", profile.getIsfMgdl());
|
||||
mProfile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
|
||||
mProfile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
|
||||
|
||||
//mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
|
||||
mProfile.put("high_temptarget_raises_sensitivity", false);
|
||||
//mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
|
||||
mProfile.put("low_temptarget_lowers_sensitivity", false);
|
||||
|
||||
|
||||
mProfile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target,SMBDefaults.sensitivity_raises_target));
|
||||
mProfile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target,SMBDefaults.resistance_lowers_target));
|
||||
mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments);
|
||||
mProfile.put("exercise_mode", SMBDefaults.exercise_mode);
|
||||
mProfile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target);
|
||||
mProfile.put("maxCOB", SMBDefaults.maxCOB);
|
||||
mProfile.put("skip_neutral_temps", pump.setNeutralTempAtFullHour());
|
||||
// min_5m_carbimpact is not used within SMB determinebasal
|
||||
//if (mealData.usedMinCarbsImpact > 0) {
|
||||
// mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact);
|
||||
//} else {
|
||||
// mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
|
||||
//}
|
||||
mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap);
|
||||
mProfile.put("enableUAM", uamAllowed);
|
||||
mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable);
|
||||
|
||||
boolean smbEnabled = sp.getBoolean(R.string.key_use_smb, false);
|
||||
mProfile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval));
|
||||
mProfile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false));
|
||||
mProfile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false));
|
||||
mProfile.put("allowSMB_with_high_temptarget", smbEnabled && sp.getBoolean(R.string.key_allowSMB_with_high_temptarget, false));
|
||||
mProfile.put("enableSMB_always", smbEnabled && sp.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering);
|
||||
mProfile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering);
|
||||
mProfile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes));
|
||||
mProfile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes));
|
||||
//set the min SMB amount to be the amount set by the pump.
|
||||
mProfile.put("bolus_increment", pumpbolusstep);
|
||||
mProfile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold));
|
||||
|
||||
mProfile.put("current_basal", basalrate);
|
||||
mProfile.put("temptargetSet", tempTargetSet);
|
||||
mProfile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")));
|
||||
|
||||
if (profileFunction.getUnits().equals(Constants.MMOL)) {
|
||||
mProfile.put("out_units", "mmol/L");
|
||||
}
|
||||
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now);
|
||||
|
||||
mCurrentTemp = new JSONObject();
|
||||
mCurrentTemp.put("temp", "absolute");
|
||||
mCurrentTemp.put("duration", tb != null ? tb.getPlannedRemainingMinutes() : 0);
|
||||
mCurrentTemp.put("rate", tb != null ? tb.tempBasalConvertedToAbsolute(now, profile) : 0d);
|
||||
|
||||
// as we have non default temps longer than 30 mintues
|
||||
TemporaryBasal tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis());
|
||||
if (tempBasal != null) {
|
||||
mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration());
|
||||
}
|
||||
|
||||
mIobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray);
|
||||
|
||||
mGlucoseStatus = new JSONObject();
|
||||
mGlucoseStatus.put("glucose", glucoseStatus.glucose);
|
||||
mGlucoseStatus.put("noise", glucoseStatus.noise);
|
||||
|
||||
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
|
||||
mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
|
||||
} else {
|
||||
mGlucoseStatus.put("delta", glucoseStatus.delta);
|
||||
}
|
||||
mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta);
|
||||
mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta);
|
||||
mGlucoseStatus.put("date", glucoseStatus.date);
|
||||
|
||||
mMealData = new JSONObject();
|
||||
mMealData.put("carbs", mealData.carbs);
|
||||
mMealData.put("boluses", mealData.boluses);
|
||||
mMealData.put("mealCOB", mealData.mealCOB);
|
||||
mMealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation);
|
||||
mMealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation);
|
||||
mMealData.put("lastBolusTime", mealData.lastBolusTime);
|
||||
mMealData.put("lastCarbTime", mealData.lastCarbTime);
|
||||
|
||||
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
mAutosensData = new JSONObject();
|
||||
mAutosensData.put("ratio", autosensDataRatio);
|
||||
} else {
|
||||
mAutosensData = new JSONObject();
|
||||
mAutosensData.put("ratio", 1.0);
|
||||
}
|
||||
mMicrobolusAllowed = microBolusAllowed;
|
||||
mSMBAlwaysAllowed = advancedFiltering;
|
||||
|
||||
mCurrentTime = now;
|
||||
|
||||
mIsSaveCgmSource = isSaveCgmSource;
|
||||
}
|
||||
|
||||
private Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
|
||||
|
||||
if (jsonObject == null) return Undefined.instance;
|
||||
|
||||
Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), (context, scriptable, scriptable1, objects) -> objects[1]);
|
||||
return param;
|
||||
}
|
||||
|
||||
private Object makeParamArray(JSONArray jsonArray, Context rhino, Scriptable scope) {
|
||||
//Object param = NativeJSON.parse(rhino, scope, "{myarray: " + jsonArray.toString() + " }", new Callable() {
|
||||
Object param = NativeJSON.parse(rhino, scope, jsonArray.toString(), (context, scriptable, scriptable1, objects) -> objects[1]);
|
||||
return param;
|
||||
}
|
||||
|
||||
private String readFile(String filename) throws IOException {
|
||||
byte[] bytes = mScriptReader.readFile(filename);
|
||||
String string = new String(bytes, StandardCharsets.UTF_8);
|
||||
if (string.startsWith("#!/usr/bin/env node")) {
|
||||
string = string.substring(20);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSSMB
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.IobTotal
|
||||
import info.nightscout.androidaps.data.MealData
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.mozilla.javascript.*
|
||||
import org.mozilla.javascript.Function
|
||||
import java.io.IOException
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.nio.charset.StandardCharsets
|
||||
import javax.inject.Inject
|
||||
|
||||
class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var activePluginProvider: ActivePluginProvider
|
||||
@Inject lateinit var openHumansUploader: OpenHumansUploader
|
||||
|
||||
private var profile = JSONObject()
|
||||
private var mGlucoseStatus = JSONObject()
|
||||
private var iobData: JSONArray? = null
|
||||
private var mealData = JSONObject()
|
||||
private var currentTemp = JSONObject()
|
||||
private var autosensData = JSONObject()
|
||||
private var microBolusAllowed = false
|
||||
private var smbAlwaysAllowed = false
|
||||
private var currentTime: Long = 0
|
||||
private var saveCgmSource = false
|
||||
var currentTempParam: String? = null
|
||||
private set
|
||||
var iobDataParam: String? = null
|
||||
private set
|
||||
var glucoseStatusParam: String? = null
|
||||
private set
|
||||
var profileParam: String? = null
|
||||
private set
|
||||
var mealDataParam: String? = null
|
||||
private set
|
||||
var scriptDebug = ""
|
||||
private set
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
operator fun invoke(): DetermineBasalResultSMB? {
|
||||
aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<")
|
||||
aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it })
|
||||
aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Current temp: " + currentTemp.toString().also { currentTempParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Profile: " + profile.toString().also { profileParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Meal data: " + mealData.toString().also { mealDataParam = it })
|
||||
aapsLogger.debug(LTag.APS, "Autosens data: $autosensData")
|
||||
aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined")
|
||||
aapsLogger.debug(LTag.APS, "MicroBolusAllowed: $microBolusAllowed")
|
||||
aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: $smbAlwaysAllowed")
|
||||
aapsLogger.debug(LTag.APS, "CurrentTime: $currentTime")
|
||||
aapsLogger.debug(LTag.APS, "isSaveCgmSource: $saveCgmSource")
|
||||
var determineBasalResultSMB: DetermineBasalResultSMB? = null
|
||||
val rhino = Context.enter()
|
||||
val scope: Scriptable = rhino.initStandardObjects()
|
||||
// Turn off optimization to make Rhino Android compatible
|
||||
rhino.optimizationLevel = -1
|
||||
try {
|
||||
|
||||
//register logger callback for console.log and console.error
|
||||
ScriptableObject.defineClass(scope, LoggerCallback::class.java)
|
||||
val myLogger = rhino.newObject(scope, "LoggerCallback", null)
|
||||
scope.put("console2", scope, myLogger)
|
||||
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null)
|
||||
|
||||
//set module parent
|
||||
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null)
|
||||
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null)
|
||||
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null)
|
||||
|
||||
//generate functions "determine_basal" and "setTempBasal"
|
||||
rhino.evaluateString(scope, readFile("OpenAPSSMB/determine-basal.js"), "JavaScript", 0, null)
|
||||
rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null)
|
||||
val determineBasalObj = scope["determine_basal", scope]
|
||||
val setTempBasalFunctionsObj = scope["tempBasalFunctions", scope]
|
||||
|
||||
//call determine-basal
|
||||
if (determineBasalObj is Function && setTempBasalFunctionsObj is NativeObject) {
|
||||
|
||||
//prepare parameters
|
||||
val params = arrayOf(
|
||||
makeParam(mGlucoseStatus, rhino, scope),
|
||||
makeParam(currentTemp, rhino, scope),
|
||||
makeParamArray(iobData, rhino, scope),
|
||||
makeParam(profile, rhino, scope),
|
||||
makeParam(autosensData, rhino, scope),
|
||||
makeParam(mealData, rhino, scope),
|
||||
setTempBasalFunctionsObj,
|
||||
java.lang.Boolean.valueOf(microBolusAllowed),
|
||||
makeParam(null, rhino, scope), // reservoir data as undefined
|
||||
java.lang.Long.valueOf(currentTime),
|
||||
java.lang.Boolean.valueOf(saveCgmSource)
|
||||
)
|
||||
val jsResult = determineBasalObj.call(rhino, scope, scope, params) as NativeObject
|
||||
scriptDebug = LoggerCallback.scriptDebug
|
||||
|
||||
// Parse the jsResult object to a JSON-String
|
||||
val result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString()
|
||||
aapsLogger.debug(LTag.APS, "Result: $result")
|
||||
try {
|
||||
val resultJson = JSONObject(result)
|
||||
openHumansUploader.enqueueSMBData(profile, mGlucoseStatus, iobData, mealData, currentTemp, autosensData, microBolusAllowed, smbAlwaysAllowed, resultJson)
|
||||
determineBasalResultSMB = DetermineBasalResultSMB(injector, resultJson)
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e)
|
||||
}
|
||||
} else {
|
||||
aapsLogger.error(LTag.APS, "Problem loading JS Functions")
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
aapsLogger.error(LTag.APS, "IOException")
|
||||
} catch (e: RhinoException) {
|
||||
aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString())
|
||||
} catch (e: IllegalAccessException) {
|
||||
aapsLogger.error(LTag.APS, e.toString())
|
||||
} catch (e: InstantiationException) {
|
||||
aapsLogger.error(LTag.APS, e.toString())
|
||||
} catch (e: InvocationTargetException) {
|
||||
aapsLogger.error(LTag.APS, e.toString())
|
||||
} finally {
|
||||
Context.exit()
|
||||
}
|
||||
glucoseStatusParam = mGlucoseStatus.toString()
|
||||
iobDataParam = iobData.toString()
|
||||
currentTempParam = currentTemp.toString()
|
||||
profileParam = profile.toString()
|
||||
mealDataParam = mealData.toString()
|
||||
return determineBasalResultSMB
|
||||
}
|
||||
|
||||
@Suppress("SpellCheckingInspection") fun setData(profile: Profile,
|
||||
maxIob: Double,
|
||||
maxBasal: Double,
|
||||
minBg: Double,
|
||||
maxBg: Double,
|
||||
targetBg: Double,
|
||||
basalRate: Double,
|
||||
iobArray: Array<IobTotal>,
|
||||
glucoseStatus: GlucoseStatus,
|
||||
mealData: MealData,
|
||||
autosensDataRatio: Double,
|
||||
tempTargetSet: Boolean,
|
||||
microBolusAllowed: Boolean,
|
||||
uamAllowed: Boolean,
|
||||
advancedFiltering: Boolean,
|
||||
isSaveCgmSource: Boolean
|
||||
) {
|
||||
val pump = activePluginProvider.activePump
|
||||
val pumpBolusStep = pump.pumpDescription.bolusStep
|
||||
this.profile.put("max_iob", maxIob)
|
||||
//mProfile.put("dia", profile.getDia());
|
||||
this.profile.put("type", "current")
|
||||
this.profile.put("max_daily_basal", profile.maxDailyBasal)
|
||||
this.profile.put("max_basal", maxBasal)
|
||||
this.profile.put("min_bg", minBg)
|
||||
this.profile.put("max_bg", maxBg)
|
||||
this.profile.put("target_bg", targetBg)
|
||||
this.profile.put("carb_ratio", profile.ic)
|
||||
this.profile.put("sens", profile.isfMgdl)
|
||||
this.profile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3))
|
||||
this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
|
||||
|
||||
//mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
|
||||
this.profile.put("high_temptarget_raises_sensitivity", false)
|
||||
//mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
|
||||
this.profile.put("low_temptarget_lowers_sensitivity", false)
|
||||
this.profile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target))
|
||||
this.profile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target))
|
||||
this.profile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments)
|
||||
this.profile.put("exercise_mode", SMBDefaults.exercise_mode)
|
||||
this.profile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target)
|
||||
this.profile.put("maxCOB", SMBDefaults.maxCOB)
|
||||
this.profile.put("skip_neutral_temps", pump.setNeutralTempAtFullHour())
|
||||
// min_5m_carbimpact is not used within SMB determinebasal
|
||||
//if (mealData.usedMinCarbsImpact > 0) {
|
||||
// mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact);
|
||||
//} else {
|
||||
// mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
|
||||
//}
|
||||
this.profile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap)
|
||||
this.profile.put("enableUAM", uamAllowed)
|
||||
this.profile.put("A52_risk_enable", SMBDefaults.A52_risk_enable)
|
||||
val smbEnabled = sp.getBoolean(R.string.key_use_smb, false)
|
||||
this.profile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval))
|
||||
this.profile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false))
|
||||
this.profile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false))
|
||||
this.profile.put("allowSMB_with_high_temptarget", smbEnabled && sp.getBoolean(R.string.key_allowSMB_with_high_temptarget, false))
|
||||
this.profile.put("enableSMB_always", smbEnabled && sp.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering)
|
||||
this.profile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering)
|
||||
this.profile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes))
|
||||
this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes))
|
||||
//set the min SMB amount to be the amount set by the pump.
|
||||
this.profile.put("bolus_increment", pumpBolusStep)
|
||||
this.profile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold))
|
||||
this.profile.put("current_basal", basalRate)
|
||||
this.profile.put("temptargetSet", tempTargetSet)
|
||||
this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")))
|
||||
if (profileFunction.getUnits() == Constants.MMOL) {
|
||||
this.profile.put("out_units", "mmol/L")
|
||||
}
|
||||
val now = System.currentTimeMillis()
|
||||
val tb = treatmentsPlugin.getTempBasalFromHistory(now)
|
||||
currentTemp.put("temp", "absolute")
|
||||
currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0)
|
||||
currentTemp.put("rate", tb?.tempBasalConvertedToAbsolute(now, profile) ?: 0.0)
|
||||
|
||||
// as we have non default temps longer than 30 mintues
|
||||
val tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis())
|
||||
if (tempBasal != null) {
|
||||
currentTemp.put("minutesrunning", tempBasal.realDuration)
|
||||
}
|
||||
iobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray)
|
||||
mGlucoseStatus.put("glucose", glucoseStatus.glucose)
|
||||
mGlucoseStatus.put("noise", glucoseStatus.noise)
|
||||
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
|
||||
mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta)
|
||||
} else {
|
||||
mGlucoseStatus.put("delta", glucoseStatus.delta)
|
||||
}
|
||||
mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta)
|
||||
mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta)
|
||||
mGlucoseStatus.put("date", glucoseStatus.date)
|
||||
this.mealData.put("carbs", mealData.carbs)
|
||||
this.mealData.put("boluses", mealData.boluses)
|
||||
this.mealData.put("mealCOB", mealData.mealCOB)
|
||||
this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation)
|
||||
this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation)
|
||||
this.mealData.put("lastBolusTime", mealData.lastBolusTime)
|
||||
this.mealData.put("lastCarbTime", mealData.lastCarbTime)
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
autosensData.put("ratio", autosensDataRatio)
|
||||
} else {
|
||||
autosensData.put("ratio", 1.0)
|
||||
}
|
||||
this.microBolusAllowed = microBolusAllowed
|
||||
smbAlwaysAllowed = advancedFiltering
|
||||
currentTime = now
|
||||
saveCgmSource = isSaveCgmSource
|
||||
}
|
||||
|
||||
private fun makeParam(jsonObject: JSONObject?, rhino: Context, scope: Scriptable): Any {
|
||||
return if (jsonObject == null) Undefined.instance
|
||||
else NativeJSON.parse(rhino, scope, jsonObject.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
|
||||
}
|
||||
|
||||
private fun makeParamArray(jsonArray: JSONArray?, rhino: Context, scope: Scriptable): Any {
|
||||
return NativeJSON.parse(rhino, scope, jsonArray.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array<Any?> -> objects[1] }
|
||||
}
|
||||
|
||||
@Throws(IOException::class) private fun readFile(filename: String): String {
|
||||
val bytes = scriptReader.readFile(filename)
|
||||
var string = String(bytes, StandardCharsets.UTF_8)
|
||||
if (string.startsWith("#!/usr/bin/env node")) {
|
||||
string = string.substring(20)
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
init {
|
||||
injector.androidInjector().inject(this)
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSSMB;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
public class DetermineBasalResultSMB extends APSResult {
|
||||
@Inject SP sp;
|
||||
|
||||
private double eventualBG;
|
||||
private double snoozeBG;
|
||||
|
||||
private DetermineBasalResultSMB(HasAndroidInjector injector) {
|
||||
super(injector);
|
||||
hasPredictions = true;
|
||||
}
|
||||
|
||||
DetermineBasalResultSMB(HasAndroidInjector injector, JSONObject result) {
|
||||
this(injector);
|
||||
date = DateUtil.now();
|
||||
json = result;
|
||||
try {
|
||||
if (result.has("error")) {
|
||||
reason = result.getString("error");
|
||||
return;
|
||||
}
|
||||
|
||||
reason = result.getString("reason");
|
||||
if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG");
|
||||
if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG");
|
||||
//if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
|
||||
|
||||
if (result.has("carbsReq")) carbsReq = result.getInt("carbsReq");
|
||||
if (result.has("carbsReqWithin")) carbsReqWithin = result.getInt("carbsReqWithin");
|
||||
|
||||
|
||||
if (result.has("rate") && result.has("duration")) {
|
||||
tempBasalRequested = true;
|
||||
rate = result.getDouble("rate");
|
||||
if (rate < 0d) rate = 0d;
|
||||
duration = result.getInt("duration");
|
||||
} else {
|
||||
rate = -1;
|
||||
duration = -1;
|
||||
}
|
||||
|
||||
if (result.has("units")) {
|
||||
bolusRequested = true;
|
||||
smb = result.getDouble("units");
|
||||
} else {
|
||||
smb = 0d;
|
||||
}
|
||||
if (result.has("targetBG")) {
|
||||
targetBG = result.getDouble("targetBG");
|
||||
}
|
||||
|
||||
if (result.has("deliverAt")) {
|
||||
String date = result.getString("deliverAt");
|
||||
try {
|
||||
deliverAt = DateUtil.fromISODateString(date).getTime();
|
||||
} catch (Exception e) {
|
||||
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: " + date, e);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetermineBasalResultSMB newAndClone(HasAndroidInjector injector) {
|
||||
DetermineBasalResultSMB newResult = new DetermineBasalResultSMB(injector);
|
||||
doClone(newResult);
|
||||
|
||||
newResult.eventualBG = eventualBG;
|
||||
newResult.snoozeBG = snoozeBG;
|
||||
return newResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject json() {
|
||||
try {
|
||||
return new JSONObject(this.json.toString());
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error(LTag.APS, "Error converting determine-basal result to JSON", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSSMB
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector) : APSResult(injector) {
|
||||
|
||||
private var eventualBG = 0.0
|
||||
private var snoozeBG = 0.0
|
||||
|
||||
internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) {
|
||||
date = DateUtil.now()
|
||||
json = result
|
||||
try {
|
||||
if (result.has("error")) {
|
||||
reason = result.getString("error")
|
||||
return
|
||||
}
|
||||
reason = result.getString("reason")
|
||||
if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG")
|
||||
if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG")
|
||||
//if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
|
||||
if (result.has("carbsReq")) carbsReq = result.getInt("carbsReq")
|
||||
if (result.has("carbsReqWithin")) carbsReqWithin = result.getInt("carbsReqWithin")
|
||||
if (result.has("rate") && result.has("duration")) {
|
||||
tempBasalRequested = true
|
||||
rate = result.getDouble("rate")
|
||||
if (rate < 0.0) rate = 0.0
|
||||
duration = result.getInt("duration")
|
||||
} else {
|
||||
rate = (-1).toDouble()
|
||||
duration = -1
|
||||
}
|
||||
if (result.has("units")) {
|
||||
bolusRequested = true
|
||||
smb = result.getDouble("units")
|
||||
} else {
|
||||
smb = 0.0
|
||||
}
|
||||
if (result.has("targetBG")) {
|
||||
targetBG = result.getDouble("targetBG")
|
||||
}
|
||||
if (result.has("deliverAt")) {
|
||||
val date = result.getString("deliverAt")
|
||||
try {
|
||||
deliverAt = DateUtil.fromISODateString(date).time
|
||||
} catch (e: Exception) {
|
||||
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
|
||||
}
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun newAndClone(injector: HasAndroidInjector): DetermineBasalResultSMB {
|
||||
val newResult = DetermineBasalResultSMB(injector)
|
||||
doClone(newResult)
|
||||
newResult.eventualBG = eventualBG
|
||||
newResult.snoozeBG = snoozeBG
|
||||
return newResult
|
||||
}
|
||||
|
||||
override fun json(): JSONObject? {
|
||||
try {
|
||||
return JSONObject(json.toString())
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.APS, "Error converting determine-basal result to JSON", e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
init {
|
||||
hasPredictions = true
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import dagger.android.support.DaggerFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.OpenapsamaFragmentBinding
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||
|
@ -16,34 +17,42 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.JSONFormatter
|
||||
import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.openapsama_fragment.*
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import javax.inject.Inject
|
||||
|
||||
class OpenAPSSMBFragment : DaggerFragment() {
|
||||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
private var _binding: OpenapsamaFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.openapsama_fragment, container, false)
|
||||
savedInstanceState: Bundle?): View {
|
||||
_binding = OpenapsamaFragmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
openapsma_run.setOnClickListener {
|
||||
binding.run.setOnClickListener {
|
||||
openAPSSMBPlugin.invoke("OpenAPSSMB button", false)
|
||||
}
|
||||
}
|
||||
|
@ -53,16 +62,16 @@ class OpenAPSSMBFragment : DaggerFragment() {
|
|||
super.onResume()
|
||||
disposable += rxBus
|
||||
.toObservable(EventOpenAPSUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
updateGUI()
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventOpenAPSUpdateResultGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
updateResultGUI(it.text)
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
}, fabricPrivacy::logException)
|
||||
|
||||
updateGUI()
|
||||
}
|
||||
|
@ -73,52 +82,58 @@ class OpenAPSSMBFragment : DaggerFragment() {
|
|||
disposable.clear()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun updateGUI() {
|
||||
if (openapsma_result == null) return
|
||||
if (_binding == null) return
|
||||
openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult ->
|
||||
openapsma_result.text = JSONFormatter.format(lastAPSResult.json)
|
||||
openapsma_request.text = lastAPSResult.toSpanned()
|
||||
binding.result.text = JSONFormatter.format(lastAPSResult.json)
|
||||
binding.request.text = lastAPSResult.toSpanned()
|
||||
}
|
||||
openAPSSMBPlugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS ->
|
||||
openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
|
||||
openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
|
||||
binding.glucosestatus.text = JSONFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
|
||||
binding.currenttemp.text = JSONFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
|
||||
try {
|
||||
val iobArray = JSONArray(determineBasalAdapterSMBJS.iobDataParam)
|
||||
openapsma_iobdata.text = TextUtils.concat(resourceHelper.gs(R.string.array_of_elements, iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0)))
|
||||
binding.iobdata.text = TextUtils.concat(resourceHelper.gs(R.string.array_of_elements, iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0)))
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error(LTag.APS, "Unhandled exception", e)
|
||||
@SuppressLint("SetTextI18n")
|
||||
openapsma_iobdata.text = "JSONException see log for details"
|
||||
binding.iobdata.text = "JSONException see log for details"
|
||||
}
|
||||
|
||||
openapsma_profile.text = JSONFormatter.format(determineBasalAdapterSMBJS.profileParam)
|
||||
openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterSMBJS.mealDataParam)
|
||||
openapsma_scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug
|
||||
binding.profile.text = JSONFormatter.format(determineBasalAdapterSMBJS.profileParam)
|
||||
binding.mealdata.text = JSONFormatter.format(determineBasalAdapterSMBJS.mealDataParam)
|
||||
binding.scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug
|
||||
openAPSSMBPlugin.lastAPSResult?.inputConstraints?.let {
|
||||
openapsma_constraints.text = it.getReasons(aapsLogger)
|
||||
binding.constraints.text = it.getReasons(aapsLogger)
|
||||
}
|
||||
}
|
||||
if (openAPSSMBPlugin.lastAPSRun != 0L) {
|
||||
openapsma_lastrun.text = dateUtil.dateAndTimeString(openAPSSMBPlugin.lastAPSRun)
|
||||
binding.lastrun.text = dateUtil.dateAndTimeString(openAPSSMBPlugin.lastAPSRun)
|
||||
}
|
||||
openAPSSMBPlugin.lastAutosensResult?.let {
|
||||
openapsma_autosensdata.text = JSONFormatter.format(it.json())
|
||||
openAPSSMBPlugin.lastAutosensResult.let {
|
||||
binding.autosensdata.text = JSONFormatter.format(it.json())
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun updateResultGUI(text: String) {
|
||||
if (openapsma_result == null) return
|
||||
openapsma_result.text = text
|
||||
openapsma_glucosestatus.text = ""
|
||||
openapsma_currenttemp.text = ""
|
||||
openapsma_iobdata.text = ""
|
||||
openapsma_profile.text = ""
|
||||
openapsma_mealdata.text = ""
|
||||
openapsma_autosensdata.text = ""
|
||||
openapsma_scriptdebugdata.text = ""
|
||||
openapsma_request.text = ""
|
||||
openapsma_lastrun.text = ""
|
||||
if (_binding == null) return
|
||||
binding.result.text = text
|
||||
binding.glucosestatus.text = ""
|
||||
binding.currenttemp.text = ""
|
||||
binding.iobdata.text = ""
|
||||
binding.profile.text = ""
|
||||
binding.mealdata.text = ""
|
||||
binding.autosensdata.text = ""
|
||||
binding.scriptdebugdata.text = ""
|
||||
binding.request.text = ""
|
||||
binding.lastrun.text = ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,323 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSSMB;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||
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.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader;
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui;
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.HardLimits;
|
||||
import info.nightscout.androidaps.utils.Profiler;
|
||||
import info.nightscout.androidaps.utils.Round;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
@Singleton
|
||||
public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, ConstraintsInterface {
|
||||
private final ConstraintChecker constraintChecker;
|
||||
private final ResourceHelper resourceHelper;
|
||||
private final ProfileFunction profileFunction;
|
||||
private final Context context;
|
||||
private final RxBusWrapper rxBus;
|
||||
private final ActivePluginProvider activePlugin;
|
||||
private final TreatmentsPlugin treatmentsPlugin;
|
||||
private final IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
private final HardLimits hardLimits;
|
||||
private final Profiler profiler;
|
||||
private final FabricPrivacy fabricPrivacy;
|
||||
private final SP sp;
|
||||
|
||||
// last values
|
||||
DetermineBasalAdapterSMBJS lastDetermineBasalAdapterSMBJS = null;
|
||||
long lastAPSRun = 0;
|
||||
DetermineBasalResultSMB lastAPSResult = null;
|
||||
AutosensResult lastAutosensResult = null;
|
||||
|
||||
@Inject
|
||||
public OpenAPSSMBPlugin(
|
||||
HasAndroidInjector injector,
|
||||
AAPSLogger aapsLogger,
|
||||
RxBusWrapper rxBus,
|
||||
ConstraintChecker constraintChecker,
|
||||
ResourceHelper resourceHelper,
|
||||
ProfileFunction profileFunction,
|
||||
Context context,
|
||||
ActivePluginProvider activePlugin,
|
||||
TreatmentsPlugin treatmentsPlugin,
|
||||
IobCobCalculatorPlugin iobCobCalculatorPlugin,
|
||||
HardLimits hardLimits,
|
||||
Profiler profiler,
|
||||
FabricPrivacy fabricPrivacy,
|
||||
SP sp
|
||||
) {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.APS)
|
||||
.fragmentClass(OpenAPSSMBFragment.class.getName())
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.openapssmb)
|
||||
.shortName(R.string.smb_shortname)
|
||||
.preferencesId(R.xml.pref_openapssmb)
|
||||
.description(R.string.description_smb)
|
||||
.setDefault(),
|
||||
aapsLogger, resourceHelper, injector
|
||||
);
|
||||
this.constraintChecker = constraintChecker;
|
||||
this.resourceHelper = resourceHelper;
|
||||
this.profileFunction = profileFunction;
|
||||
this.rxBus = rxBus;
|
||||
this.context = context;
|
||||
this.activePlugin = activePlugin;
|
||||
this.treatmentsPlugin = treatmentsPlugin;
|
||||
this.iobCobCalculatorPlugin = iobCobCalculatorPlugin;
|
||||
this.hardLimits = hardLimits;
|
||||
this.profiler = profiler;
|
||||
this.fabricPrivacy = fabricPrivacy;
|
||||
this.sp = sp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialEnableCondition() {
|
||||
try {
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
return pump.getPumpDescription().isTempBasalCapable;
|
||||
} catch (Exception ignored) {
|
||||
// may fail during initialization
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialShowInListCondition() {
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
return pump.getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessPreferences(@NotNull PreferenceFragmentCompat preferenceFragment) {
|
||||
super.preprocessPreferences(preferenceFragment);
|
||||
boolean smbAlwaysEnabled = sp.getBoolean(R.string.key_enableSMB_always, false);
|
||||
|
||||
SwitchPreference withCOB = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_enableSMB_with_COB));
|
||||
if (withCOB != null) {
|
||||
withCOB.setVisible(!smbAlwaysEnabled);
|
||||
}
|
||||
SwitchPreference withTempTarget = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_enableSMB_with_temptarget));
|
||||
if (withTempTarget != null) {
|
||||
withTempTarget.setVisible(!smbAlwaysEnabled);
|
||||
}
|
||||
SwitchPreference afterCarbs = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_enableSMB_after_carbs));
|
||||
if (afterCarbs != null) {
|
||||
afterCarbs.setVisible(!smbAlwaysEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public APSResult getLastAPSResult() {
|
||||
return lastAPSResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastAPSRun() {
|
||||
return lastAPSRun;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String initiator, boolean tempBasalFallback) {
|
||||
getAapsLogger().debug(LTag.APS, "invoke from " + initiator + " tempBasalFallback: " + tempBasalFallback);
|
||||
lastAPSResult = null;
|
||||
DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS;
|
||||
determineBasalAdapterSMBJS = new DetermineBasalAdapterSMBJS(new ScriptReader(context), getInjector());
|
||||
|
||||
GlucoseStatus glucoseStatus = new GlucoseStatus(getInjector()).getGlucoseStatusData();
|
||||
Profile profile = profileFunction.getProfile();
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
|
||||
if (profile == null) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.noprofileselected)));
|
||||
getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.noprofileselected));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isEnabled(PluginType.APS)) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_disabled)));
|
||||
getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.openapsma_disabled));
|
||||
return;
|
||||
}
|
||||
|
||||
if (glucoseStatus == null) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_noglucosedata)));
|
||||
getAapsLogger().debug(LTag.APS, resourceHelper.gs(R.string.openapsma_noglucosedata));
|
||||
return;
|
||||
}
|
||||
|
||||
Constraint<Double> inputConstraints = new Constraint<>(0d); // fake. only for collecting all results
|
||||
|
||||
Constraint<Double> maxBasalConstraint = constraintChecker.getMaxBasalAllowed(profile);
|
||||
inputConstraints.copyReasons(maxBasalConstraint);
|
||||
double maxBasal = maxBasalConstraint.value();
|
||||
double minBg = profile.getTargetLowMgdl();
|
||||
double maxBg = profile.getTargetHighMgdl();
|
||||
double targetBg = profile.getTargetMgdl();
|
||||
|
||||
minBg = Round.roundTo(minBg, 0.1d);
|
||||
maxBg = Round.roundTo(maxBg, 0.1d);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
long startPart = System.currentTimeMillis();
|
||||
|
||||
MealData mealData = iobCobCalculatorPlugin.getMealData();
|
||||
profiler.log(LTag.APS, "getMealData()", startPart);
|
||||
|
||||
Constraint<Double> maxIOBAllowedConstraint = constraintChecker.getMaxIOBAllowed();
|
||||
inputConstraints.copyReasons(maxIOBAllowedConstraint);
|
||||
double maxIob = maxIOBAllowedConstraint.value();
|
||||
|
||||
minBg = hardLimits.verifyHardLimits(minBg, "minBg", hardLimits.getVERY_HARD_LIMIT_MIN_BG()[0], hardLimits.getVERY_HARD_LIMIT_MIN_BG()[1]);
|
||||
maxBg = hardLimits.verifyHardLimits(maxBg, "maxBg", hardLimits.getVERY_HARD_LIMIT_MAX_BG()[0], hardLimits.getVERY_HARD_LIMIT_MAX_BG()[1]);
|
||||
targetBg = hardLimits.verifyHardLimits(targetBg, "targetBg", hardLimits.getVERY_HARD_LIMIT_TARGET_BG()[0], hardLimits.getVERY_HARD_LIMIT_TARGET_BG()[1]);
|
||||
|
||||
boolean isTempTarget = false;
|
||||
TempTarget tempTarget = treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis());
|
||||
if (tempTarget != null) {
|
||||
isTempTarget = true;
|
||||
minBg = hardLimits.verifyHardLimits(tempTarget.low, "minBg", hardLimits.getVERY_HARD_LIMIT_TEMP_MIN_BG()[0], hardLimits.getVERY_HARD_LIMIT_TEMP_MIN_BG()[1]);
|
||||
maxBg = hardLimits.verifyHardLimits(tempTarget.high, "maxBg", hardLimits.getVERY_HARD_LIMIT_TEMP_MAX_BG()[0], hardLimits.getVERY_HARD_LIMIT_TEMP_MAX_BG()[1]);
|
||||
targetBg = hardLimits.verifyHardLimits(tempTarget.target(), "targetBg", hardLimits.getVERY_HARD_LIMIT_TEMP_TARGET_BG()[0], hardLimits.getVERY_HARD_LIMIT_TEMP_TARGET_BG()[1]);
|
||||
}
|
||||
|
||||
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getDia(), "dia", hardLimits.minDia(), hardLimits.maxDia()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), "sens", hardLimits.getMINISF(), hardLimits.getMAXISF()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.02, hardLimits.maxBasal()))
|
||||
return;
|
||||
if (!hardLimits.checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, hardLimits.maxBasal()))
|
||||
return;
|
||||
|
||||
startPart = System.currentTimeMillis();
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
AutosensData autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin");
|
||||
if (autosensData == null) {
|
||||
rxBus.send(new EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata)));
|
||||
return;
|
||||
}
|
||||
lastAutosensResult = autosensData.autosensResult;
|
||||
} else {
|
||||
lastAutosensResult = new AutosensResult();
|
||||
lastAutosensResult.sensResult = "autosens disabled";
|
||||
}
|
||||
|
||||
IobTotal[] iobArray = iobCobCalculatorPlugin.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget);
|
||||
profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart);
|
||||
|
||||
startPart = System.currentTimeMillis();
|
||||
Constraint<Boolean> smbAllowed = new Constraint<>(!tempBasalFallback);
|
||||
constraintChecker.isSMBModeEnabled(smbAllowed);
|
||||
inputConstraints.copyReasons(smbAllowed);
|
||||
|
||||
Constraint<Boolean> advancedFiltering = new Constraint<>(!tempBasalFallback);
|
||||
constraintChecker.isAdvancedFilteringEnabled(advancedFiltering);
|
||||
inputConstraints.copyReasons(advancedFiltering);
|
||||
|
||||
Constraint<Boolean> uam = new Constraint<>(true);
|
||||
constraintChecker.isUAMEnabled(uam);
|
||||
inputConstraints.copyReasons(uam);
|
||||
|
||||
profiler.log(LTag.APS, "detectSensitivityandCarbAbsorption()", startPart);
|
||||
profiler.log(LTag.APS, "SMB data gathering", start);
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
try {
|
||||
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, activePlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
|
||||
lastAutosensResult.ratio, //autosensDataRatio
|
||||
isTempTarget,
|
||||
smbAllowed.value(),
|
||||
uam.value(),
|
||||
advancedFiltering.value(),
|
||||
activePlugin.getActiveBgSource().getClass().getSimpleName().equals("DexcomPlugin")
|
||||
);
|
||||
} catch (JSONException e) {
|
||||
fabricPrivacy.logException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
DetermineBasalResultSMB determineBasalResultSMB = determineBasalAdapterSMBJS.invoke();
|
||||
profiler.log(LTag.APS, "SMB calculation", start);
|
||||
if (determineBasalResultSMB == null) {
|
||||
getAapsLogger().error(LTag.APS, "SMB calculation returned null");
|
||||
lastDetermineBasalAdapterSMBJS = null;
|
||||
lastAPSResult = null;
|
||||
lastAPSRun = 0;
|
||||
} else {
|
||||
// TODO still needed with oref1?
|
||||
// Fix bug determine basal
|
||||
if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !treatmentsPlugin.isTempBasalInProgress())
|
||||
determineBasalResultSMB.tempBasalRequested = false;
|
||||
|
||||
determineBasalResultSMB.iob = iobArray[0];
|
||||
|
||||
try {
|
||||
determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now));
|
||||
} catch (JSONException e) {
|
||||
getAapsLogger().error(LTag.APS, "Unhandled exception", e);
|
||||
}
|
||||
|
||||
determineBasalResultSMB.inputConstraints = inputConstraints;
|
||||
|
||||
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS;
|
||||
lastAPSResult = determineBasalResultSMB;
|
||||
lastAPSRun = now;
|
||||
}
|
||||
rxBus.send(new EventOpenAPSUpdateGui());
|
||||
|
||||
//deviceStatus.suggested = determineBasalResultAMA.json;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Constraint<Boolean> isSuperBolusEnabled(Constraint<Boolean> value) {
|
||||
value.set(getAapsLogger(), false);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
package info.nightscout.androidaps.plugins.aps.openAPSSMB
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui
|
||||
import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
import info.nightscout.androidaps.utils.Profiler
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
open class OpenAPSSMBPlugin @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
private val rxBus: RxBusWrapper,
|
||||
private val constraintChecker: ConstraintChecker,
|
||||
resourceHelper: ResourceHelper,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val context: Context,
|
||||
private val activePlugin: ActivePluginProvider,
|
||||
private val treatmentsPlugin: TreatmentsPlugin,
|
||||
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
|
||||
private val hardLimits: HardLimits,
|
||||
private val profiler: Profiler,
|
||||
private val sp: SP
|
||||
) : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.APS)
|
||||
.fragmentClass(OpenAPSSMBFragment::class.java.name)
|
||||
.pluginIcon(R.drawable.ic_generic_icon)
|
||||
.pluginName(R.string.openapssmb)
|
||||
.shortName(R.string.smb_shortname)
|
||||
.preferencesId(R.xml.pref_openapssmb)
|
||||
.description(R.string.description_smb)
|
||||
.setDefault(),
|
||||
aapsLogger, resourceHelper, injector
|
||||
), APSInterface, ConstraintsInterface {
|
||||
|
||||
// last values
|
||||
override var lastAPSRun: Long = 0
|
||||
override var lastAPSResult: DetermineBasalResultSMB? = null
|
||||
var lastDetermineBasalAdapterSMBJS: DetermineBasalAdapterSMBJS? = null
|
||||
var lastAutosensResult = AutosensResult()
|
||||
|
||||
override fun specialEnableCondition(): Boolean {
|
||||
return try {
|
||||
activePlugin.activePump.pumpDescription.isTempBasalCapable
|
||||
} catch (ignored: Exception) {
|
||||
// may fail during initialization
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun specialShowInListCondition(): Boolean {
|
||||
val pump = activePlugin.activePump
|
||||
return pump.pumpDescription.isTempBasalCapable
|
||||
}
|
||||
|
||||
override fun preprocessPreferences(preferenceFragment: PreferenceFragmentCompat) {
|
||||
super.preprocessPreferences(preferenceFragment)
|
||||
val smbAlwaysEnabled = sp.getBoolean(R.string.key_enableSMB_always, false)
|
||||
preferenceFragment.findPreference<SwitchPreference>(resourceHelper.gs(R.string.key_enableSMB_with_COB))?.isVisible = !smbAlwaysEnabled
|
||||
preferenceFragment.findPreference<SwitchPreference>(resourceHelper.gs(R.string.key_enableSMB_with_temptarget))?.isVisible = !smbAlwaysEnabled
|
||||
preferenceFragment.findPreference<SwitchPreference>(resourceHelper.gs(R.string.key_enableSMB_after_carbs))?.isVisible = !smbAlwaysEnabled
|
||||
}
|
||||
|
||||
override fun invoke(initiator: String, tempBasalFallback: Boolean) {
|
||||
aapsLogger.debug(LTag.APS, "invoke from $initiator tempBasalFallback: $tempBasalFallback")
|
||||
lastAPSResult = null
|
||||
val glucoseStatus = GlucoseStatus(injector).glucoseStatusData
|
||||
val profile = profileFunction.getProfile()
|
||||
val pump = activePlugin.activePump
|
||||
if (profile == null) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.noprofileselected)))
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.noprofileselected))
|
||||
return
|
||||
}
|
||||
if (!isEnabled(PluginType.APS)) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_disabled)))
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.openapsma_disabled))
|
||||
return
|
||||
}
|
||||
if (glucoseStatus == null) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openapsma_noglucosedata)))
|
||||
aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.openapsma_noglucosedata))
|
||||
return
|
||||
}
|
||||
|
||||
val inputConstraints = Constraint(0.0) // fake. only for collecting all results
|
||||
val maxBasal = constraintChecker.getMaxBasalAllowed(profile).also {
|
||||
inputConstraints.copyReasons(it)
|
||||
}.value()
|
||||
var start = System.currentTimeMillis()
|
||||
var startPart = System.currentTimeMillis()
|
||||
profiler.log(LTag.APS, "getMealData()", startPart)
|
||||
val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint ->
|
||||
inputConstraints.copyReasons(maxIOBAllowedConstraint)
|
||||
}.value()
|
||||
|
||||
var minBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetLowMgdl, 0.1), "minBg", hardLimits.VERY_HARD_LIMIT_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MIN_BG[1].toDouble())
|
||||
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), "maxBg", hardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
|
||||
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, "targetBg", hardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
|
||||
var isTempTarget = false
|
||||
treatmentsPlugin.getTempTargetFromHistory(System.currentTimeMillis())?.let { tempTarget ->
|
||||
isTempTarget = true
|
||||
minBg = hardLimits.verifyHardLimits(tempTarget.low, "minBg", hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
|
||||
maxBg = hardLimits.verifyHardLimits(tempTarget.high, "maxBg", hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1].toDouble())
|
||||
targetBg = hardLimits.verifyHardLimits(tempTarget.target(), "targetBg", hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0].toDouble(), hardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1].toDouble())
|
||||
}
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.dia, "dia", hardLimits.minDia(), hardLimits.maxDia())) return
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC())) return
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.isfMgdl, "sens", hardLimits.MINISF, hardLimits.MAXISF)) return
|
||||
if (!hardLimits.checkOnlyHardLimits(profile.maxDailyBasal, "max_daily_basal", 0.02, hardLimits.maxBasal())) return
|
||||
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, "current_basal", 0.01, hardLimits.maxBasal())) return
|
||||
startPart = System.currentTimeMillis()
|
||||
if (constraintChecker.isAutosensModeEnabled().value()) {
|
||||
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin")
|
||||
if (autosensData == null) {
|
||||
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata)))
|
||||
return
|
||||
}
|
||||
lastAutosensResult = autosensData.autosensResult
|
||||
} else {
|
||||
lastAutosensResult.sensResult = "autosens disabled"
|
||||
}
|
||||
val iobArray = iobCobCalculatorPlugin.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
|
||||
profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart)
|
||||
startPart = System.currentTimeMillis()
|
||||
val smbAllowed = Constraint(!tempBasalFallback).also {
|
||||
constraintChecker.isSMBModeEnabled(it)
|
||||
inputConstraints.copyReasons(it)
|
||||
}
|
||||
val advancedFiltering = Constraint(!tempBasalFallback).also {
|
||||
constraintChecker.isAdvancedFilteringEnabled(it)
|
||||
inputConstraints.copyReasons(it)
|
||||
}
|
||||
val uam = Constraint(true).also {
|
||||
constraintChecker.isUAMEnabled(it)
|
||||
inputConstraints.copyReasons(it)
|
||||
}
|
||||
profiler.log(LTag.APS, "detectSensitivityAndCarbAbsorption()", startPart)
|
||||
profiler.log(LTag.APS, "SMB data gathering", start)
|
||||
start = System.currentTimeMillis()
|
||||
|
||||
DetermineBasalAdapterSMBJS(ScriptReader(context), injector).also { determineBasalAdapterSMBJS ->
|
||||
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg,
|
||||
activePlugin.activePump.baseBasalRate,
|
||||
iobArray,
|
||||
glucoseStatus,
|
||||
iobCobCalculatorPlugin.mealData,
|
||||
lastAutosensResult.ratio,
|
||||
isTempTarget,
|
||||
smbAllowed.value(),
|
||||
uam.value(),
|
||||
advancedFiltering.value(),
|
||||
activePlugin.activeBgSource.javaClass.simpleName == "DexcomPlugin")
|
||||
val now = System.currentTimeMillis()
|
||||
val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke()
|
||||
profiler.log(LTag.APS, "SMB calculation", start)
|
||||
if (determineBasalResultSMB == null) {
|
||||
aapsLogger.error(LTag.APS, "SMB calculation returned null")
|
||||
lastDetermineBasalAdapterSMBJS = null
|
||||
lastAPSResult = null
|
||||
lastAPSRun = 0
|
||||
} else {
|
||||
// TODO still needed with oref1?
|
||||
// Fix bug determine basal
|
||||
if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && !treatmentsPlugin.isTempBasalInProgress) determineBasalResultSMB.tempBasalRequested = false
|
||||
determineBasalResultSMB.iob = iobArray[0]
|
||||
determineBasalResultSMB.json?.put("timestamp", DateUtil.toISOString(now))
|
||||
determineBasalResultSMB.inputConstraints = inputConstraints
|
||||
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS
|
||||
lastAPSResult = determineBasalResultSMB
|
||||
lastAPSRun = now
|
||||
}
|
||||
}
|
||||
rxBus.send(EventOpenAPSUpdateGui())
|
||||
}
|
||||
|
||||
override fun isSuperBolusEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
|
||||
value[aapsLogger] = false
|
||||
return value
|
||||
}
|
||||
}
|
|
@ -12,22 +12,24 @@ import dagger.android.support.DaggerFragment
|
|||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||
import info.nightscout.androidaps.databinding.ConfigbuilderFragmentBinding
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.configbuilder_fragment.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ConfigBuilderFragment : DaggerFragment() {
|
||||
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
|
||||
|
@ -39,25 +41,32 @@ class ConfigBuilderFragment : DaggerFragment() {
|
|||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
private val pluginViewHolders = ArrayList<PluginViewHolder>()
|
||||
|
||||
private var _binding: ConfigbuilderFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.configbuilder_fragment, container, false)
|
||||
savedInstanceState: Bundle?): View {
|
||||
_binding = ConfigbuilderFragmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (protectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES))
|
||||
configbuilder_main_layout.visibility = View.GONE
|
||||
binding.mainLayout.visibility = View.GONE
|
||||
else
|
||||
unlock.visibility = View.GONE
|
||||
binding.unlock.visibility = View.GONE
|
||||
|
||||
unlock.setOnClickListener {
|
||||
binding.unlock.setOnClickListener {
|
||||
activity?.let { activity ->
|
||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, {
|
||||
activity.runOnUiThread {
|
||||
configbuilder_main_layout.visibility = View.VISIBLE
|
||||
unlock.visibility = View.GONE
|
||||
binding.mainLayout.visibility = View.VISIBLE
|
||||
binding.unlock.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -69,10 +78,10 @@ class ConfigBuilderFragment : DaggerFragment() {
|
|||
super.onResume()
|
||||
disposable += rxBus
|
||||
.toObservable(EventConfigBuilderUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
for (pluginViewHolder in pluginViewHolders) pluginViewHolder.update()
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
}, fabricPrivacy::logException)
|
||||
updateGUI()
|
||||
}
|
||||
|
||||
|
@ -82,9 +91,15 @@ class ConfigBuilderFragment : DaggerFragment() {
|
|||
disposable.clear()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun updateGUI() {
|
||||
configbuilder_categories.removeAllViews()
|
||||
binding.categories.removeAllViews()
|
||||
if (!config.NSCLIENT) {
|
||||
createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, activePlugin.getSpecificPluginsVisibleInListByInterface(ProfileInterface::class.java, PluginType.PROFILE))
|
||||
}
|
||||
|
@ -115,7 +130,7 @@ class ConfigBuilderFragment : DaggerFragment() {
|
|||
pluginContainer.addView(pluginViewHolder.baseView)
|
||||
pluginViewHolders.add(pluginViewHolder)
|
||||
}
|
||||
configbuilder_categories.addView(parent)
|
||||
binding.categories.addView(parent)
|
||||
}
|
||||
|
||||
inner class PluginViewHolder internal constructor(private val fragment: ConfigBuilderFragment,
|
||||
|
@ -157,7 +172,7 @@ class ConfigBuilderFragment : DaggerFragment() {
|
|||
|
||||
pluginPreferences.setOnClickListener {
|
||||
fragment.activity?.let { activity ->
|
||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, {
|
||||
val i = Intent(fragment.context, PreferencesActivity::class.java)
|
||||
i.putExtra("id", plugin.preferencesId)
|
||||
fragment.startActivity(i)
|
||||
|
@ -174,7 +189,7 @@ class ConfigBuilderFragment : DaggerFragment() {
|
|||
enabledInclusive.isChecked = plugin.isEnabled(pluginType)
|
||||
enabledInclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled
|
||||
enabledExclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled
|
||||
if(plugin.menuIcon != -1) {
|
||||
if (plugin.menuIcon != -1) {
|
||||
pluginIcon.visibility = View.VISIBLE
|
||||
pluginIcon.setImageDrawable(context?.let { ContextCompat.getDrawable(it, plugin.menuIcon) })
|
||||
} else {
|
||||
|
@ -196,7 +211,5 @@ class ConfigBuilderFragment : DaggerFragment() {
|
|||
private fun areMultipleSelectionsAllowed(type: PluginType): Boolean {
|
||||
return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS || type == PluginType.LOOP
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@ import info.nightscout.androidaps.events.EventRebuildTabs
|
|||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.showConfirmation
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import java.util.*
|
||||
|
@ -25,7 +26,8 @@ class ConfigBuilderPlugin @Inject constructor(
|
|||
resourceHelper: ResourceHelper,
|
||||
private val sp: SP,
|
||||
private val rxBus: RxBusWrapper,
|
||||
private val activePlugin: ActivePluginProvider
|
||||
private val activePlugin: ActivePluginProvider,
|
||||
private val uel: UserEntryLogger
|
||||
) : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(ConfigBuilderFragment::class.java.name)
|
||||
|
@ -137,9 +139,10 @@ class ConfigBuilderPlugin @Inject constructor(
|
|||
if (allowHardwarePump || activity == null) {
|
||||
performPluginSwitch(changedPlugin, newState, type)
|
||||
} else {
|
||||
showConfirmation(activity, resourceHelper.gs(R.string.allow_hardware_pump_text), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.allow_hardware_pump_text), Runnable {
|
||||
performPluginSwitch(changedPlugin, newState, type)
|
||||
sp.putBoolean("allow_hardware_pump", true)
|
||||
uel.log("HW PUMP ALLOWED")
|
||||
aapsLogger.debug(LTag.PUMP, "First time HW pump allowed!")
|
||||
}, Runnable {
|
||||
rxBus.send(EventConfigBuilderUpdateGui())
|
||||
|
|
|
@ -9,8 +9,6 @@ import android.view.Gravity
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
@ -19,11 +17,14 @@ import androidx.recyclerview.widget.LinearSmoothScroller
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import dagger.android.support.DaggerFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
|
||||
import info.nightscout.androidaps.databinding.ObjectivesFragmentBinding
|
||||
import info.nightscout.androidaps.databinding.ObjectivesItemBinding
|
||||
import info.nightscout.androidaps.dialogs.NtpProgressDialog
|
||||
import info.nightscout.androidaps.events.EventNtpStatus
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask
|
||||
import info.nightscout.androidaps.receivers.ReceiverStatusStore
|
||||
|
@ -31,19 +32,20 @@ import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
|
|||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.SntpClient
|
||||
import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.objectives_fragment.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ObjectivesFragment : DaggerFragment() {
|
||||
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
|
@ -51,6 +53,7 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
@Inject lateinit var receiverStatusStore: ReceiverStatusStore
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var sntpClient: SntpClient
|
||||
@Inject lateinit var uel: UserEntryLogger
|
||||
|
||||
private val objectivesAdapter = ObjectivesAdapter()
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
@ -64,19 +67,23 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.objectives_fragment, container, false)
|
||||
}
|
||||
private var _binding: ObjectivesFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
ObjectivesFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
objectives_recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||
objectives_recyclerview.adapter = objectivesAdapter
|
||||
objectives_fake.setOnClickListener { updateGUI() }
|
||||
objectives_reset.setOnClickListener {
|
||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||
binding.recyclerview.adapter = objectivesAdapter
|
||||
binding.fake.setOnClickListener { updateGUI() }
|
||||
binding.reset.setOnClickListener {
|
||||
objectivesPlugin.reset()
|
||||
objectives_recyclerview.adapter?.notifyDataSetChanged()
|
||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||
scrollToCurrentObjective()
|
||||
}
|
||||
scrollToCurrentObjective()
|
||||
|
@ -88,11 +95,10 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
super.onResume()
|
||||
disposable += rxBus
|
||||
.toObservable(EventObjectivesUpdateGui::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.observeOn(aapsSchedulers.main)
|
||||
.subscribe({
|
||||
objectives_recyclerview.adapter?.notifyDataSetChanged()
|
||||
}, { fabricPrivacy.logException(it) }
|
||||
)
|
||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
||||
}, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
|
@ -105,6 +111,7 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
handler.removeCallbacks(objectiveUpdater)
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private fun startUpdateTimer() {
|
||||
|
@ -129,7 +136,7 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
override fun calculateTimeForScrolling(dx: Int): Int = super.calculateTimeForScrolling(dx) * 4
|
||||
}
|
||||
smoothScroller.targetPosition = i
|
||||
objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller)
|
||||
binding.recyclerview.layoutManager?.startSmoothScroll(smoothScroller)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@ -145,67 +152,66 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val objective = objectivesPlugin.objectives[position]
|
||||
holder.title.text = resourceHelper.gs(R.string.nth_objective, position + 1)
|
||||
holder.binding.title.text = resourceHelper.gs(R.string.nth_objective, position + 1)
|
||||
if (objective.objective != 0) {
|
||||
holder.objective.visibility = View.VISIBLE
|
||||
holder.objective.text = resourceHelper.gs(objective.objective)
|
||||
holder.binding.objective.visibility = View.VISIBLE
|
||||
holder.binding.objective.text = resourceHelper.gs(objective.objective)
|
||||
} else
|
||||
holder.objective.visibility = View.GONE
|
||||
holder.binding.objective.visibility = View.GONE
|
||||
if (objective.gate != 0) {
|
||||
holder.gate.visibility = View.VISIBLE
|
||||
holder.gate.text = resourceHelper.gs(objective.gate)
|
||||
holder.binding.gate.visibility = View.VISIBLE
|
||||
holder.binding.gate.text = resourceHelper.gs(objective.gate)
|
||||
} else
|
||||
holder.gate.visibility = View.GONE
|
||||
holder.binding.gate.visibility = View.GONE
|
||||
if (!objective.isStarted) {
|
||||
holder.gate.setTextColor(-0x1)
|
||||
holder.verify.visibility = View.GONE
|
||||
holder.progress.visibility = View.GONE
|
||||
holder.accomplished.visibility = View.GONE
|
||||
holder.unFinish.visibility = View.GONE
|
||||
holder.unStart.visibility = View.GONE
|
||||
holder.binding.gate.setTextColor(-0x1)
|
||||
holder.binding.verify.visibility = View.GONE
|
||||
holder.binding.progress.visibility = View.GONE
|
||||
holder.binding.accomplished.visibility = View.GONE
|
||||
holder.binding.unfinish.visibility = View.GONE
|
||||
holder.binding.unstart.visibility = View.GONE
|
||||
if (position == 0 || objectivesPlugin.allPriorAccomplished(position))
|
||||
holder.start.visibility = View.VISIBLE
|
||||
holder.binding.start.visibility = View.VISIBLE
|
||||
else
|
||||
holder.start.visibility = View.GONE
|
||||
holder.binding.start.visibility = View.GONE
|
||||
} else if (objective.isAccomplished) {
|
||||
holder.gate.setTextColor(-0xb350b0)
|
||||
holder.verify.visibility = View.GONE
|
||||
holder.progress.visibility = View.GONE
|
||||
holder.start.visibility = View.GONE
|
||||
holder.accomplished.visibility = View.VISIBLE
|
||||
holder.unFinish.visibility = View.VISIBLE
|
||||
holder.unStart.visibility = View.GONE
|
||||
holder.binding.gate.setTextColor(-0xb350b0)
|
||||
holder.binding.verify.visibility = View.GONE
|
||||
holder.binding.progress.visibility = View.GONE
|
||||
holder.binding.start.visibility = View.GONE
|
||||
holder.binding.accomplished.visibility = View.VISIBLE
|
||||
holder.binding.unfinish.visibility = View.VISIBLE
|
||||
holder.binding.unstart.visibility = View.GONE
|
||||
} else if (objective.isStarted) {
|
||||
holder.gate.setTextColor(-0x1)
|
||||
holder.verify.visibility = View.VISIBLE
|
||||
holder.verify.isEnabled = objective.isCompleted || objectives_fake.isChecked
|
||||
holder.start.visibility = View.GONE
|
||||
holder.accomplished.visibility = View.GONE
|
||||
holder.unFinish.visibility = View.GONE
|
||||
holder.unStart.visibility = View.VISIBLE
|
||||
holder.progress.visibility = View.VISIBLE
|
||||
holder.progress.removeAllViews()
|
||||
holder.binding.gate.setTextColor(-0x1)
|
||||
holder.binding.verify.visibility = View.VISIBLE
|
||||
holder.binding.verify.isEnabled = objective.isCompleted || binding.fake.isChecked
|
||||
holder.binding.start.visibility = View.GONE
|
||||
holder.binding.accomplished.visibility = View.GONE
|
||||
holder.binding.unfinish.visibility = View.GONE
|
||||
holder.binding.unstart.visibility = View.VISIBLE
|
||||
holder.binding.progress.visibility = View.VISIBLE
|
||||
holder.binding.progress.removeAllViews()
|
||||
for (task in objective.tasks) {
|
||||
if (task.shouldBeIgnored()) continue
|
||||
// name
|
||||
val name = TextView(holder.progress.context)
|
||||
@Suppress("SetTextlI8n")
|
||||
name.text = resourceHelper.gs(task.task) + ":"
|
||||
val name = TextView(holder.binding.progress.context)
|
||||
name.text = "${resourceHelper.gs(task.task)}:"
|
||||
name.setTextColor(-0x1)
|
||||
holder.progress.addView(name, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
holder.binding.progress.addView(name, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
// hint
|
||||
task.hints.forEach { h ->
|
||||
if (!task.isCompleted)
|
||||
holder.progress.addView(h.generate(context))
|
||||
if (!task.isCompleted())
|
||||
context?.let { holder.binding.progress.addView(h.generate(it)) }
|
||||
}
|
||||
// state
|
||||
val state = TextView(holder.progress.context)
|
||||
val state = TextView(holder.binding.progress.context)
|
||||
state.setTextColor(-0x1)
|
||||
val basicHTML = "<font color=\"%1\$s\"><b>%2\$s</b></font>"
|
||||
val formattedHTML = String.format(basicHTML, if (task.isCompleted) "#4CAF50" else "#FF9800", task.progress)
|
||||
val formattedHTML = String.format(basicHTML, if (task.isCompleted()) "#4CAF50" else "#FF9800", task.progress)
|
||||
state.text = HtmlHelper.fromHtml(formattedHTML)
|
||||
state.gravity = Gravity.END
|
||||
holder.progress.addView(state, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
holder.binding.progress.addView(state, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
if (task is ExamTask) {
|
||||
state.setOnClickListener {
|
||||
val dialog = ObjectivesExamDialog()
|
||||
|
@ -218,16 +224,16 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
}
|
||||
}
|
||||
// horizontal line
|
||||
val separator = View(holder.progress.context)
|
||||
val separator = View(holder.binding.progress.context)
|
||||
separator.setBackgroundColor(Color.DKGRAY)
|
||||
holder.progress.addView(separator, LinearLayout.LayoutParams.MATCH_PARENT, 2)
|
||||
holder.binding.progress.addView(separator, LinearLayout.LayoutParams.MATCH_PARENT, 2)
|
||||
}
|
||||
}
|
||||
holder.accomplished.text = resourceHelper.gs(R.string.accomplished, dateUtil.dateAndTimeString(objective.accomplishedOn))
|
||||
holder.accomplished.setTextColor(-0x3e3e3f)
|
||||
holder.verify.setOnClickListener {
|
||||
holder.binding.accomplished.text = resourceHelper.gs(R.string.accomplished, dateUtil.dateAndTimeString(objective.accomplishedOn))
|
||||
holder.binding.accomplished.setTextColor(-0x3e3e3f)
|
||||
holder.binding.verify.setOnClickListener {
|
||||
receiverStatusStore.updateNetworkStatus()
|
||||
if (objectives_fake.isChecked) {
|
||||
if (binding.fake.isChecked) {
|
||||
objective.accomplishedOn = DateUtil.now()
|
||||
scrollToCurrentObjective()
|
||||
startUpdateTimer()
|
||||
|
@ -264,9 +270,9 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
}.start()
|
||||
}
|
||||
}
|
||||
holder.start.setOnClickListener {
|
||||
holder.binding.start.setOnClickListener {
|
||||
receiverStatusStore.updateNetworkStatus()
|
||||
if (objectives_fake.isChecked) {
|
||||
if (binding.fake.isChecked) {
|
||||
objective.startedOn = DateUtil.now()
|
||||
scrollToCurrentObjective()
|
||||
startUpdateTimer()
|
||||
|
@ -298,9 +304,10 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
}, receiverStatusStore.isConnected)
|
||||
}.start()
|
||||
}
|
||||
holder.unStart.setOnClickListener {
|
||||
holder.binding.unstart.setOnClickListener {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.doyouwantresetstart), Runnable {
|
||||
uel.log("OBJECTIVE UNSTARTED", i1 = position + 1)
|
||||
objective.startedOn = 0
|
||||
scrollToCurrentObjective()
|
||||
rxBus.send(EventObjectivesUpdateGui())
|
||||
|
@ -308,7 +315,7 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
})
|
||||
}
|
||||
}
|
||||
holder.unFinish.setOnClickListener {
|
||||
holder.binding.unfinish.setOnClickListener {
|
||||
objective.accomplishedOn = 0
|
||||
scrollToCurrentObjective()
|
||||
rxBus.send(EventObjectivesUpdateGui())
|
||||
|
@ -318,21 +325,21 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
// generate random request code if none exists
|
||||
val request = sp.getString(R.string.key_objectives_request_code, String.format("%1$05d", (Math.random() * 99999).toInt()))
|
||||
sp.putString(R.string.key_objectives_request_code, request)
|
||||
holder.requestCode.text = resourceHelper.gs(R.string.requestcode, request)
|
||||
holder.requestCode.visibility = View.VISIBLE
|
||||
holder.enterButton.visibility = View.VISIBLE
|
||||
holder.input.visibility = View.VISIBLE
|
||||
holder.inputHint.visibility = View.VISIBLE
|
||||
holder.enterButton.setOnClickListener {
|
||||
val input = holder.input.text.toString()
|
||||
objective.specialAction(activity, input)
|
||||
holder.binding.requestcode.text = resourceHelper.gs(R.string.requestcode, request)
|
||||
holder.binding.requestcode.visibility = View.VISIBLE
|
||||
holder.binding.enterbutton.visibility = View.VISIBLE
|
||||
holder.binding.input.visibility = View.VISIBLE
|
||||
holder.binding.inputhint.visibility = View.VISIBLE
|
||||
holder.binding.enterbutton.setOnClickListener {
|
||||
val input = holder.binding.input.text.toString()
|
||||
activity?.let { activity -> objective.specialAction(activity, input) }
|
||||
rxBus.send(EventObjectivesUpdateGui())
|
||||
}
|
||||
} else {
|
||||
holder.enterButton.visibility = View.GONE
|
||||
holder.input.visibility = View.GONE
|
||||
holder.inputHint.visibility = View.GONE
|
||||
holder.requestCode.visibility = View.GONE
|
||||
holder.binding.enterbutton.visibility = View.GONE
|
||||
holder.binding.input.visibility = View.GONE
|
||||
holder.binding.inputhint.visibility = View.GONE
|
||||
holder.binding.requestcode.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,20 +347,9 @@ class ObjectivesFragment : DaggerFragment() {
|
|||
return objectivesPlugin.objectives.size
|
||||
}
|
||||
|
||||
inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val title: TextView = itemView.findViewById(R.id.objective_title)
|
||||
val objective: TextView = itemView.findViewById(R.id.objective_objective)
|
||||
val gate: TextView = itemView.findViewById(R.id.objective_gate)
|
||||
val accomplished: TextView = itemView.findViewById(R.id.objective_accomplished)
|
||||
val progress: LinearLayout = itemView.findViewById(R.id.objective_progress)
|
||||
val verify: Button = itemView.findViewById(R.id.objective_verify)
|
||||
val start: Button = itemView.findViewById(R.id.objective_start)
|
||||
val unFinish: Button = itemView.findViewById(R.id.objective_unfinish)
|
||||
val unStart: Button = itemView.findViewById(R.id.objective_unstart)
|
||||
val inputHint: TextView = itemView.findViewById(R.id.objective_inputhint)
|
||||
val input: EditText = itemView.findViewById(R.id.objective_input)
|
||||
val enterButton: Button = itemView.findViewById(R.id.objective_enterbutton)
|
||||
val requestCode: TextView = itemView.findViewById(R.id.objective_requestcode)
|
||||
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
val binding = ObjectivesItemBinding.bind(itemView)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import info.nightscout.androidaps.Config
|
|||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
|
@ -25,8 +26,8 @@ class ObjectivesPlugin @Inject constructor(
|
|||
resourceHelper: ResourceHelper,
|
||||
private val activePlugin: ActivePluginProvider,
|
||||
private val sp: SP,
|
||||
private val config: Config
|
||||
|
||||
config: Config,
|
||||
private val uel: UserEntryLogger
|
||||
) : PluginBase(PluginDescription()
|
||||
.mainType(PluginType.CONSTRAINTS)
|
||||
.fragmentClass(ObjectivesFragment::class.qualifiedName)
|
||||
|
@ -141,6 +142,7 @@ class ObjectivesPlugin @Inject constructor(
|
|||
sp.putLong("Objectives_" + "auto" + "_accomplished", DateUtil.now())
|
||||
setupObjectives()
|
||||
OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeaccepted))
|
||||
uel.log("OBJECTIVES SKIPPED")
|
||||
} else {
|
||||
OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeinvalid))
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import dagger.android.support.DaggerDialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.ObjectivesExamFragmentBinding
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective
|
||||
|
@ -15,28 +16,36 @@ import info.nightscout.androidaps.utils.DateUtil
|
|||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.objectives_exam_fragment.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ObjectivesExamDialog : DaggerDialogFragment() {
|
||||
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
companion object {
|
||||
|
||||
var objective: Objective? = null
|
||||
}
|
||||
|
||||
private var currentTask = 0
|
||||
|
||||
private var _binding: ObjectivesExamFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
savedInstanceState: Bundle?): View {
|
||||
// load data from bundle
|
||||
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||
currentTask = bundle.getInt("currentTask", 0)
|
||||
}
|
||||
|
||||
return inflater.inflate(R.layout.objectives_exam_fragment, container, false)
|
||||
_binding = ObjectivesExamFragmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -55,36 +64,46 @@ class ObjectivesExamDialog : DaggerDialogFragment() {
|
|||
bundle.putInt("currentTask", currentTask)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun updateGui() {
|
||||
if (_binding == null) return
|
||||
objective?.let { objective ->
|
||||
val task: ExamTask = objective.tasks[currentTask] as ExamTask
|
||||
objectives_exam_name.setText(task.task)
|
||||
objectives_exam_question.setText(task.question)
|
||||
binding.examName.setText(task.task)
|
||||
binding.examQuestion.setText(task.question)
|
||||
// Options
|
||||
objectives_exam_options.removeAllViews()
|
||||
binding.examOptions.removeAllViews()
|
||||
task.options.forEach {
|
||||
val cb = it.generate(context)
|
||||
if (task.answered) {
|
||||
cb.isEnabled = false
|
||||
if (it.isCorrect)
|
||||
cb.isChecked = true
|
||||
context?.let { context ->
|
||||
val cb = it.generate(context)
|
||||
if (task.answered) {
|
||||
cb.isEnabled = false
|
||||
if (it.isCorrect)
|
||||
cb.isChecked = true
|
||||
}
|
||||
binding.examOptions.addView(cb)
|
||||
}
|
||||
objectives_exam_options.addView(cb)
|
||||
}
|
||||
// Hints
|
||||
objectives_exam_hints.removeAllViews()
|
||||
binding.examHints.removeAllViews()
|
||||
for (h in task.hints) {
|
||||
objectives_exam_hints.addView(h.generate(context))
|
||||
context?.let { binding.examHints.addView(h.generate(it)) }
|
||||
}
|
||||
// Disabled to
|
||||
objectives_exam_disabledto.text = resourceHelper.gs(R.string.answerdisabledto, dateUtil.timeString(task.disabledTo))
|
||||
objectives_exam_disabledto.visibility = if (task.isEnabledAnswer) View.GONE else View.VISIBLE
|
||||
binding.examDisabledto.text = resourceHelper.gs(R.string.answerdisabledto, dateUtil.timeString(task.disabledTo))
|
||||
binding.examDisabledto.visibility = if (task.isEnabledAnswer()) View.GONE else View.VISIBLE
|
||||
// Buttons
|
||||
objectives_exam_verify.isEnabled = !task.answered && task.isEnabledAnswer
|
||||
objectives_exam_verify.setOnClickListener {
|
||||
binding.examVerify.isEnabled = !task.answered && task.isEnabledAnswer()
|
||||
binding.examVerify.setOnClickListener {
|
||||
var result = true
|
||||
for (o in task.options) {
|
||||
val option: Option = o as Option
|
||||
val option: Option = o
|
||||
result = result && option.evaluate()
|
||||
}
|
||||
task.answered = result
|
||||
|
@ -95,35 +114,35 @@ class ObjectivesExamDialog : DaggerDialogFragment() {
|
|||
updateGui()
|
||||
rxBus.send(EventObjectivesUpdateGui())
|
||||
}
|
||||
close.setOnClickListener { dismiss() }
|
||||
objectives_exam_reset.setOnClickListener {
|
||||
binding.close.setOnClickListener { dismiss() }
|
||||
binding.examReset.setOnClickListener {
|
||||
task.answered = false
|
||||
//task.disabledTo = 0
|
||||
updateGui()
|
||||
rxBus.send(EventObjectivesUpdateGui())
|
||||
}
|
||||
objectives_back_button.isEnabled = currentTask != 0
|
||||
objectives_back_button.setOnClickListener {
|
||||
binding.backButton.isEnabled = currentTask != 0
|
||||
binding.backButton.setOnClickListener {
|
||||
currentTask--
|
||||
updateGui()
|
||||
}
|
||||
objectives_next_button.isEnabled = currentTask != objective.tasks.size - 1
|
||||
objectives_next_button.setOnClickListener {
|
||||
binding.nextButton.isEnabled = currentTask != objective.tasks.size - 1
|
||||
binding.nextButton.setOnClickListener {
|
||||
currentTask++
|
||||
updateGui()
|
||||
}
|
||||
|
||||
objectives_next_unanswered_button.isEnabled = !objective.isCompleted
|
||||
objectives_next_unanswered_button.setOnClickListener {
|
||||
binding.nextUnansweredButton.isEnabled = !objective.isCompleted
|
||||
binding.nextUnansweredButton.setOnClickListener {
|
||||
for (i in (currentTask + 1) until objective.tasks.size) {
|
||||
if (!objective.tasks[i].isCompleted) {
|
||||
if (!objective.tasks[i].isCompleted()) {
|
||||
currentTask = i
|
||||
updateGui()
|
||||
return@setOnClickListener
|
||||
}
|
||||
}
|
||||
for (i in 0..currentTask) {
|
||||
if (!objective.tasks[i].isCompleted) {
|
||||
if (!objective.tasks[i].isCompleted()) {
|
||||
currentTask = i
|
||||
updateGui()
|
||||
return@setOnClickListener
|
||||
|
|
|
@ -1,296 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.text.util.Linkify;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
public abstract class Objective {
|
||||
@Inject public SP sp;
|
||||
@Inject public ResourceHelper resourceHelper;
|
||||
|
||||
private final String spName;
|
||||
@StringRes private final int objective;
|
||||
@StringRes private final int gate;
|
||||
private long startedOn;
|
||||
private long accomplishedOn;
|
||||
List<Task> tasks = new ArrayList<>();
|
||||
public boolean hasSpecialInput = false;
|
||||
|
||||
public Objective(HasAndroidInjector injector, String spName, @StringRes int objective, @StringRes int gate) {
|
||||
injector.androidInjector().inject(this);
|
||||
this.spName = spName;
|
||||
this.objective = objective;
|
||||
this.gate = gate;
|
||||
startedOn = sp.getLong("Objectives_" + spName + "_started", 0L);
|
||||
accomplishedOn = sp.getLong("Objectives_" + spName + "_accomplished", 0L);
|
||||
if ((accomplishedOn - DateUtil.now()) > T.hours(3).msecs() || (startedOn - DateUtil.now()) > T.hours(3).msecs()) { // more than 3 hours in the future
|
||||
startedOn = 0;
|
||||
accomplishedOn = 0;
|
||||
}
|
||||
setupTasks(tasks);
|
||||
for (Task task : tasks) task.objective = this;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
for (Task task : tasks) {
|
||||
if (!task.shouldBeIgnored() && !task.isCompleted())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isCompleted(long trueTime) {
|
||||
for (Task task : tasks) {
|
||||
if (!task.shouldBeIgnored() && !task.isCompleted(trueTime))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isAccomplished() {
|
||||
return accomplishedOn != 0 && accomplishedOn < DateUtil.now();
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return startedOn != 0;
|
||||
}
|
||||
|
||||
public long getStartedOn() {
|
||||
return startedOn;
|
||||
}
|
||||
|
||||
public int getObjective() {
|
||||
return objective;
|
||||
}
|
||||
|
||||
public int getGate() {
|
||||
return gate;
|
||||
}
|
||||
|
||||
public void setStartedOn(long startedOn) {
|
||||
this.startedOn = startedOn;
|
||||
sp.putLong("Objectives_" + spName + "_started", startedOn);
|
||||
}
|
||||
|
||||
public void setAccomplishedOn(long accomplishedOn) {
|
||||
this.accomplishedOn = accomplishedOn;
|
||||
sp.putLong("Objectives_" + spName + "_accomplished", accomplishedOn);
|
||||
}
|
||||
|
||||
public long getAccomplishedOn() {
|
||||
return accomplishedOn;
|
||||
}
|
||||
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
|
||||
}
|
||||
|
||||
public List<Task> getTasks() {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public boolean specialActionEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void specialAction(FragmentActivity activity, String input) {
|
||||
}
|
||||
|
||||
public abstract class Task {
|
||||
@StringRes
|
||||
private final int task;
|
||||
private Objective objective;
|
||||
ArrayList<Hint> hints = new ArrayList<>();
|
||||
|
||||
public Task(@StringRes int task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public @StringRes int getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
protected Objective getObjective() {
|
||||
return objective;
|
||||
}
|
||||
|
||||
public abstract boolean isCompleted();
|
||||
|
||||
public boolean isCompleted(long trueTime) {
|
||||
return isCompleted();
|
||||
}
|
||||
|
||||
public String getProgress() {
|
||||
return resourceHelper.gs(isCompleted() ? R.string.completed_well_done : R.string.not_completed_yet);
|
||||
}
|
||||
|
||||
Task hint(Hint hint) {
|
||||
hints.add(hint);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ArrayList<Hint> getHints() {
|
||||
return hints;
|
||||
}
|
||||
|
||||
public boolean shouldBeIgnored() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class MinimumDurationTask extends Task {
|
||||
|
||||
private final long minimumDuration;
|
||||
|
||||
MinimumDurationTask(long minimumDuration) {
|
||||
super(R.string.time_elapsed);
|
||||
this.minimumDuration = minimumDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn() >= minimumDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompleted(long trueTime) {
|
||||
return getObjective().isStarted() && trueTime - getObjective().getStartedOn() >= minimumDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProgress() {
|
||||
return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn())
|
||||
+ " / " + getDurationText(minimumDuration);
|
||||
}
|
||||
|
||||
private String getDurationText(long duration) {
|
||||
int days = (int) Math.floor((double) duration / T.days(1).msecs());
|
||||
int hours = (int) Math.floor((double) duration / T.hours(1).msecs());
|
||||
int minutes = (int) Math.floor((double) duration / T.mins(1).msecs());
|
||||
if (days > 0) return resourceHelper.gq(R.plurals.objective_days, days, days);
|
||||
else if (hours > 0) return resourceHelper.gq(R.plurals.objective_hours, hours, hours);
|
||||
else return resourceHelper.gq(R.plurals.objective_minutes, minutes, minutes);
|
||||
}
|
||||
}
|
||||
|
||||
public class ExamTask extends Task {
|
||||
@StringRes
|
||||
int question;
|
||||
ArrayList<Option> options = new ArrayList<>();
|
||||
private final String spIdentifier;
|
||||
private boolean answered;
|
||||
private long disabledTo;
|
||||
|
||||
ExamTask(@StringRes int task, @StringRes int question, String spIdentifier) {
|
||||
super(task);
|
||||
this.question = question;
|
||||
this.spIdentifier = spIdentifier;
|
||||
answered = sp.getBoolean("ExamTask_" + spIdentifier, false);
|
||||
disabledTo = sp.getLong("DisabledTo_" + spIdentifier, 0L);
|
||||
}
|
||||
|
||||
public void setDisabledTo(long newState) {
|
||||
disabledTo = newState;
|
||||
sp.putLong("DisabledTo_" + spIdentifier, disabledTo);
|
||||
}
|
||||
|
||||
public long getDisabledTo() {
|
||||
return disabledTo;
|
||||
}
|
||||
|
||||
public boolean isEnabledAnswer() {
|
||||
return disabledTo < DateUtil.now();
|
||||
}
|
||||
|
||||
public void setAnswered(boolean newState) {
|
||||
answered = newState;
|
||||
sp.putBoolean("ExamTask_" + spIdentifier, answered);
|
||||
}
|
||||
|
||||
public boolean getAnswered() {
|
||||
return answered;
|
||||
}
|
||||
|
||||
ExamTask option(Option option) {
|
||||
options.add(option);
|
||||
return this;
|
||||
}
|
||||
|
||||
public @StringRes int getQuestion() {
|
||||
return question;
|
||||
}
|
||||
|
||||
public List<Objective.Option> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return answered;
|
||||
}
|
||||
}
|
||||
|
||||
public class Option {
|
||||
@StringRes int option;
|
||||
boolean isCorrect;
|
||||
|
||||
CheckBox cb; // TODO: change it, this will block releasing memeory
|
||||
|
||||
Option(@StringRes int option, boolean isCorrect) {
|
||||
this.option = option;
|
||||
this.isCorrect = isCorrect;
|
||||
}
|
||||
|
||||
public boolean isCorrect() {
|
||||
return isCorrect;
|
||||
}
|
||||
|
||||
public CheckBox generate(Context context) {
|
||||
cb = new CheckBox(context);
|
||||
cb.setText(option);
|
||||
return cb;
|
||||
}
|
||||
|
||||
public boolean evaluate() {
|
||||
boolean selection = cb.isChecked();
|
||||
if (selection && isCorrect) return true;
|
||||
return !selection && !isCorrect;
|
||||
}
|
||||
}
|
||||
|
||||
public class Hint {
|
||||
@StringRes int hint;
|
||||
|
||||
Hint(@StringRes int hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
public TextView generate(Context context) {
|
||||
TextView textView = new TextView(context);
|
||||
textView.setText(hint);
|
||||
textView.setAutoLinkMask(Linkify.WEB_URLS);
|
||||
textView.setLinksClickable(true);
|
||||
textView.setLinkTextColor(Color.YELLOW);
|
||||
Linkify.addLinks(textView, Linkify.WEB_URLS);
|
||||
return textView;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.text.util.Linkify
|
||||
import android.widget.CheckBox
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.floor
|
||||
|
||||
abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRes objective: Int, @StringRes gate: Int) {
|
||||
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
|
||||
private val spName: String
|
||||
@StringRes val objective: Int
|
||||
@StringRes val gate: Int
|
||||
var startedOn: Long = 0
|
||||
set(value) {
|
||||
field = value
|
||||
sp.putLong("Objectives_" + spName + "_started", startedOn)
|
||||
}
|
||||
var accomplishedOn: Long = 0
|
||||
set(value) {
|
||||
field = value
|
||||
sp.putLong("Objectives_" + spName + "_accomplished", value)
|
||||
}
|
||||
|
||||
var tasks: MutableList<Task> = ArrayList()
|
||||
|
||||
var hasSpecialInput = false
|
||||
|
||||
val isCompleted: Boolean
|
||||
get() {
|
||||
for (task in tasks) {
|
||||
if (!task.shouldBeIgnored() && !task.isCompleted()) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
init {
|
||||
injector.androidInjector().inject(this)
|
||||
this.spName = spName
|
||||
this.objective = objective
|
||||
this.gate = gate
|
||||
startedOn = sp.getLong("Objectives_" + spName + "_started", 0L)
|
||||
accomplishedOn = sp.getLong("Objectives_" + spName + "_accomplished", 0L)
|
||||
if (accomplishedOn - DateUtil.now() > T.hours(3).msecs() || startedOn - DateUtil.now() > T.hours(3).msecs()) { // more than 3 hours in the future
|
||||
startedOn = 0
|
||||
accomplishedOn = 0
|
||||
}
|
||||
}
|
||||
|
||||
fun isCompleted(trueTime: Long): Boolean {
|
||||
for (task in tasks) {
|
||||
if (!task.shouldBeIgnored() && !task.isCompleted(trueTime)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
val isAccomplished: Boolean
|
||||
get() = accomplishedOn != 0L && accomplishedOn < DateUtil.now()
|
||||
val isStarted: Boolean
|
||||
get() = startedOn != 0L
|
||||
|
||||
open fun specialActionEnabled(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
open fun specialAction(activity: FragmentActivity, input: String) {}
|
||||
|
||||
abstract inner class Task(var objective: Objective, @StringRes val task: Int) {
|
||||
|
||||
var hints = ArrayList<Hint>()
|
||||
|
||||
abstract fun isCompleted(): Boolean
|
||||
|
||||
open fun isCompleted(trueTime: Long): Boolean = isCompleted
|
||||
|
||||
open val progress: String
|
||||
get() = resourceHelper.gs(if (isCompleted) R.string.completed_well_done else R.string.not_completed_yet)
|
||||
|
||||
fun hint(hint: Hint): Task {
|
||||
hints.add(hint)
|
||||
return this
|
||||
}
|
||||
|
||||
open fun shouldBeIgnored(): Boolean = false
|
||||
}
|
||||
|
||||
inner class MinimumDurationTask internal constructor(objective: Objective, private val minimumDuration: Long) : Task(objective, R.string.time_elapsed) {
|
||||
|
||||
override fun isCompleted(): Boolean =
|
||||
objective.isStarted && System.currentTimeMillis() - objective.startedOn >= minimumDuration
|
||||
|
||||
override fun isCompleted(trueTime: Long): Boolean {
|
||||
return objective.isStarted && trueTime - objective.startedOn >= minimumDuration
|
||||
}
|
||||
|
||||
override val progress: String
|
||||
get() = (getDurationText(System.currentTimeMillis() - objective.startedOn)
|
||||
+ " / " + getDurationText(minimumDuration))
|
||||
|
||||
private fun getDurationText(duration: Long): String {
|
||||
val days = floor(duration.toDouble() / T.days(1).msecs()).toInt()
|
||||
val hours = floor(duration.toDouble() / T.hours(1).msecs()).toInt()
|
||||
val minutes = floor(duration.toDouble() / T.mins(1).msecs()).toInt()
|
||||
return when {
|
||||
days > 0 -> resourceHelper.gq(R.plurals.days, days, days)
|
||||
hours > 0 -> resourceHelper.gq(R.plurals.hours, hours, hours)
|
||||
else -> resourceHelper.gq(R.plurals.minutes, minutes, minutes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class ExamTask internal constructor(objective: Objective, @StringRes task: Int, @StringRes val question: Int, private val spIdentifier: String) : Task(objective, task) {
|
||||
|
||||
var options = ArrayList<Option>()
|
||||
var answered: Boolean = false
|
||||
set(value) {
|
||||
field = value
|
||||
sp.putBoolean("ExamTask_$spIdentifier", value)
|
||||
}
|
||||
var disabledTo: Long = 0
|
||||
set(value) {
|
||||
field = value
|
||||
sp.putLong("DisabledTo_$spIdentifier", value)
|
||||
}
|
||||
|
||||
init {
|
||||
answered = sp.getBoolean("ExamTask_$spIdentifier", false)
|
||||
disabledTo = sp.getLong("DisabledTo_$spIdentifier", 0L)
|
||||
}
|
||||
|
||||
override fun isCompleted(): Boolean = answered
|
||||
|
||||
fun isEnabledAnswer(): Boolean = disabledTo < DateUtil.now()
|
||||
|
||||
fun option(option: Option): ExamTask {
|
||||
options.add(option)
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
inner class Option internal constructor(@StringRes var option: Int, var isCorrect: Boolean) {
|
||||
|
||||
var cb: CheckBox? = null // TODO: change it, this will block releasing memory
|
||||
|
||||
fun generate(context: Context): CheckBox {
|
||||
cb = CheckBox(context)
|
||||
cb?.setText(option)
|
||||
return cb!!
|
||||
}
|
||||
|
||||
fun evaluate(): Boolean {
|
||||
val selection = cb!!.isChecked
|
||||
return if (selection && isCorrect) true else !selection && !isCorrect
|
||||
}
|
||||
}
|
||||
|
||||
inner class Hint internal constructor(@StringRes var hint: Int) {
|
||||
|
||||
fun generate(context: Context): TextView {
|
||||
val textView = TextView(context)
|
||||
textView.setText(hint)
|
||||
textView.autoLinkMask = Linkify.WEB_URLS
|
||||
textView.linksClickable = true
|
||||
textView.setLinkTextColor(Color.YELLOW)
|
||||
Linkify.addLinks(textView, Linkify.WEB_URLS)
|
||||
return textView
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
public class Objective0 extends Objective {
|
||||
@Inject SP sp;
|
||||
@Inject ActivePluginProvider activePlugin;
|
||||
@Inject VirtualPumpPlugin virtualPumpPlugin;
|
||||
@Inject TreatmentsPlugin treatmentsPlugin;
|
||||
@Inject LoopPlugin loopPlugin;
|
||||
@Inject NSClientPlugin nsClientPlugin;
|
||||
@Inject IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
|
||||
public Objective0(HasAndroidInjector injector) {
|
||||
super(injector, "config", R.string.objectives_0_objective, R.string.objectives_0_gate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new Task(R.string.objectives_bgavailableinns) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false);
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.nsclienthaswritepermission) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return nsClientPlugin.hasWritePermission();
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.virtualpump_uploadstatus_title) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_virtualpump_uploadstatus, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBeIgnored() {
|
||||
return !virtualPumpPlugin.isEnabled(PluginType.PUMP);
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false);
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.hasbgdata) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return iobCobCalculatorPlugin.lastBg() != null;
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.loopenabled) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return loopPlugin.isEnabled(PluginType.LOOP);
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.apsselected) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
APSInterface usedAPS = activePlugin.getActiveAPS();
|
||||
return ((PluginBase) usedAPS).isEnabled(PluginType.APS);
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.activate_profile) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now()) != null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import javax.inject.Inject
|
||||
|
||||
class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R.string.objectives_0_objective, R.string.objectives_0_gate) {
|
||||
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var loopPlugin: LoopPlugin
|
||||
@Inject lateinit var nsClientPlugin: NSClientPlugin
|
||||
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||
|
||||
init {
|
||||
tasks.add(object : Task(this, R.string.objectives_bgavailableinns) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false)
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.nsclienthaswritepermission) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return nsClientPlugin.hasWritePermission()
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.virtualpump_uploadstatus_title) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_virtualpump_uploadstatus, false)
|
||||
}
|
||||
|
||||
override fun shouldBeIgnored(): Boolean {
|
||||
return !virtualPumpPlugin.isEnabled(PluginType.PUMP)
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.objectives_pumpstatusavailableinns) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false)
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.hasbgdata) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return iobCobCalculatorPlugin.lastBg() != null
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.loopenabled) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return loopPlugin.isEnabled(PluginType.LOOP)
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.apsselected) {
|
||||
override fun isCompleted(): Boolean {
|
||||
val usedAPS = activePlugin.activeAPS
|
||||
return (usedAPS as PluginBase).isEnabled(PluginType.APS)
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.activate_profile) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now()) != null
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
public class Objective1 extends Objective {
|
||||
@Inject SP sp;
|
||||
@Inject ActionsPlugin actionsPlugin;
|
||||
|
||||
@Inject
|
||||
public Objective1(HasAndroidInjector injector) {
|
||||
super(injector, "usage", R.string.objectives_usage_objective, R.string.objectives_usage_gate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new Task(R.string.objectives_useprofileswitch) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_objectiveuseprofileswitch, false);
|
||||
}
|
||||
});
|
||||
tasks.add(new Task(R.string.objectives_usedisconnectpump) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_objectiveusedisconnect, false);
|
||||
}
|
||||
}.hint(new Hint(R.string.disconnectpump_hint)));
|
||||
tasks.add(new Task(R.string.objectives_usereconnectpump) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_objectiveusereconnect, false);
|
||||
}
|
||||
}.hint(new Hint(R.string.disconnectpump_hint)));
|
||||
tasks.add(new Task(R.string.objectives_usetemptarget) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_objectiveusetemptarget, false);
|
||||
}
|
||||
}.hint(new Hint(R.string.usetemptarget_hint)));
|
||||
tasks.add(new Task(R.string.objectives_useactions) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_objectiveuseactions, false) && actionsPlugin.isEnabled(PluginType.GENERAL) && actionsPlugin.isFragmentVisible();
|
||||
}
|
||||
}.hint(new Hint(R.string.useaction_hint)));
|
||||
tasks.add(new Task(R.string.objectives_useloop) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_objectiveuseloop, false);
|
||||
}
|
||||
}.hint(new Hint(R.string.useaction_hint)));
|
||||
tasks.add(new Task(R.string.objectives_usescale) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getBoolean(R.string.key_objectiveusescale, false);
|
||||
}
|
||||
}.hint(new Hint(R.string.usescale_hint)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
|
||||
import javax.inject.Inject
|
||||
|
||||
class Objective1 @Inject constructor(injector: HasAndroidInjector) : Objective(injector, "usage", R.string.objectives_usage_objective, R.string.objectives_usage_gate) {
|
||||
|
||||
@Inject lateinit var actionsPlugin: ActionsPlugin
|
||||
|
||||
init {
|
||||
tasks.add(object : Task(this, R.string.objectives_useprofileswitch) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_objectiveuseprofileswitch, false)
|
||||
}
|
||||
})
|
||||
tasks.add(object : Task(this, R.string.objectives_usedisconnectpump) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_objectiveusedisconnect, false)
|
||||
}
|
||||
}.hint(Hint(R.string.disconnectpump_hint)))
|
||||
tasks.add(object : Task(this, R.string.objectives_usereconnectpump) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_objectiveusereconnect, false)
|
||||
}
|
||||
}.hint(Hint(R.string.disconnectpump_hint)))
|
||||
tasks.add(object : Task(this, R.string.objectives_usetemptarget) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_objectiveusetemptarget, false)
|
||||
}
|
||||
}.hint(Hint(R.string.usetemptarget_hint)))
|
||||
tasks.add(object : Task(this, R.string.objectives_useactions) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_objectiveuseactions, false) && actionsPlugin.isEnabled(PluginType.GENERAL) && actionsPlugin.isFragmentVisible()
|
||||
}
|
||||
}.hint(Hint(R.string.useaction_hint)))
|
||||
tasks.add(object : Task(this, R.string.objectives_useloop) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_objectiveuseloop, false)
|
||||
}
|
||||
}.hint(Hint(R.string.useaction_hint)))
|
||||
tasks.add(object : Task(this, R.string.objectives_usescale) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getBoolean(R.string.key_objectiveusescale, false)
|
||||
}
|
||||
}.hint(Hint(R.string.usescale_hint)))
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
public class Objective10 extends Objective {
|
||||
|
||||
public Objective10(HasAndroidInjector injector) {
|
||||
super(injector, "auto", R.string.objectives_auto_objective, R.string.objectives_auto_gate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new MinimumDurationTask(T.days(28).msecs()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.T
|
||||
|
||||
class Objective10(injector: HasAndroidInjector) : Objective(injector, "auto", R.string.objectives_auto_objective, R.string.objectives_auto_gate) {
|
||||
|
||||
init {
|
||||
tasks.add(MinimumDurationTask(this, T.days(28).msecs()))
|
||||
}
|
||||
}
|
|
@ -1,211 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
||||
public class Objective2 extends Objective {
|
||||
|
||||
|
||||
public Objective2(HasAndroidInjector injector) {
|
||||
super(injector, "exam", R.string.objectives_exam_objective, R.string.objectives_exam_gate);
|
||||
for (Task task : tasks) {
|
||||
if (!task.isCompleted()) setAccomplishedOn(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new ExamTask(R.string.dia_label_exam, R.string.dia_whatmeansdia,"dia")
|
||||
.option(new Option(R.string.dia_minimumis3h, false))
|
||||
.option(new Option(R.string.dia_minimumis5h, true))
|
||||
.option(new Option(R.string.dia_meaningisequaltodiapump, false))
|
||||
.option(new Option(R.string.dia_valuemustbedetermined, true))
|
||||
.hint(new Hint(R.string.dia_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.hypott_label, R.string.hypott_whenhypott,"hypott")
|
||||
.option(new Option(R.string.hypott_goinglow, false))
|
||||
.option(new Option(R.string.hypott_preventoversmb, true))
|
||||
.hint(new Hint(R.string.hypott_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.offlineprofile_label, R.string.offlineprofile_whatprofile,"offlineprofile")
|
||||
.option(new Option(R.string.localprofile, true))
|
||||
.option(new Option(R.string.nsprofile, false))
|
||||
.option(new Option(R.string.offlineprofile_nsprofile, true))
|
||||
.hint(new Hint(R.string.offlineprofile_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.pumpdisconnect_label, R.string.pumpdisconnect_label,"pumpdisconnect")
|
||||
.option(new Option(R.string.pumpdisconnect_letknow, true))
|
||||
.option(new Option(R.string.pumpdisconnect_suspend, false))
|
||||
.option(new Option(R.string.pumpdisconnect_dontchnage, false))
|
||||
.hint(new Hint(R.string.pumpdisconnect_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.objectives_label, R.string.objectives_howtosave,"objectives")
|
||||
.option(new Option(R.string.objectives_exportsettings, true))
|
||||
.option(new Option(R.string.objectives_storeelsewhere, true))
|
||||
.option(new Option(R.string.objectives_doexportonstart, false))
|
||||
.option(new Option(R.string.objectives_doexportafterchange, true))
|
||||
.option(new Option(R.string.objectives_doexportafterobjective, true))
|
||||
.option(new Option(R.string.objectives_doexportafterfirtssettings, true))
|
||||
.hint(new Hint(R.string.objectives_hint1))
|
||||
.hint(new Hint(R.string.objectives_hint2))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.noisycgm_label, R.string.noisycgm_whattodo,"noisycgm")
|
||||
.option(new Option(R.string.nothing, false))
|
||||
.option(new Option(R.string.disconnectpumpfor1h, false))
|
||||
.option(new Option(R.string.noisycgm_pause, true))
|
||||
.option(new Option(R.string.noisycgm_replacesensor, true))
|
||||
.option(new Option(R.string.noisycgm_turnoffphone, false))
|
||||
.option(new Option(R.string.noisycgm_checksmoothing, true))
|
||||
.hint(new Hint(R.string.noisycgm_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.exercise_label, R.string.exercise_whattodo,"exercise")
|
||||
.option(new Option(R.string.nothing, false))
|
||||
.option(new Option(R.string.exercise_setactivitytt, true))
|
||||
.option(new Option(R.string.exercise_switchprofilebelow100, true))
|
||||
.option(new Option(R.string.exercise_switchprofileabove100, false))
|
||||
.option(new Option(R.string.exercise_stoploop, false))
|
||||
.option(new Option(R.string.exercise_doitbeforestart, true))
|
||||
.option(new Option(R.string.exercise_afterstart, true))
|
||||
.hint(new Hint(R.string.exercise_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.suspendloop_label, R.string.suspendloop_doigetinsulin,"suspendloop")
|
||||
.option(new Option(R.string.suspendloop_yes, true))
|
||||
.option(new Option(R.string.suspendloop_no, false))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.basaltest_label, R.string.basaltest_when,"basaltest")
|
||||
.option(new Option(R.string.basaltest_beforeloop, true))
|
||||
.option(new Option(R.string.basaltest_havingregularhypo, true))
|
||||
.option(new Option(R.string.basaltest_havingregularhyper, true))
|
||||
.hint(new Hint(R.string.basaltest_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.basalhelp_label, R.string.basalhelp_where,"basalhelp")
|
||||
.option(new Option(R.string.basalhelp_diabetesteam, true))
|
||||
.option(new Option(R.string.basalhelp_google, false))
|
||||
.option(new Option(R.string.basalhelp_facebook, false))
|
||||
.hint(new Hint(R.string.basalhelp_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.prerequisites_label, R.string.prerequisites_what, "prerequisites")
|
||||
.option(new Option(R.string.prerequisites_determinedcorrectprofile, true))
|
||||
.option(new Option(R.string.prerequisites_computer, true))
|
||||
.option(new Option(R.string.prerequisites_phone, true))
|
||||
.option(new Option(R.string.prerequisites_car, false))
|
||||
.option(new Option(R.string.prerequisites_nightscout, true))
|
||||
.option(new Option(R.string.prerequisites_tidepoolaccount, false))
|
||||
.option(new Option(R.string.prerequisites_googleaccount, false))
|
||||
.option(new Option(R.string.prerequisites_githubaccount, false))
|
||||
.option(new Option(R.string.prerequisites_beanandroiddeveloper, false))
|
||||
.option(new Option(R.string.prerequisites_own670g, false))
|
||||
.option(new Option(R.string.prerequisites_smartwatch, false))
|
||||
.option(new Option(R.string.prerequisites_supportedcgm, true))
|
||||
.hint(new Hint(R.string.prerequisites_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.update_label, R.string.whatistrue,"update")
|
||||
.option(new Option(R.string.update_git, true))
|
||||
.option(new Option(R.string.update_asap, true))
|
||||
.option(new Option(R.string.update_keys, true))
|
||||
.option(new Option(R.string.update_neverupdate, false))
|
||||
.option(new Option(R.string.update_askfriend, false))
|
||||
.hint(new Hint(R.string.update_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.troubleshooting_label, R.string.troubleshooting_wheretoask,"troubleshooting")
|
||||
.option(new Option(R.string.troubleshooting_fb, true))
|
||||
.option(new Option(R.string.troubleshooting_wiki, true))
|
||||
.option(new Option(R.string.troubleshooting_gitter, true))
|
||||
.option(new Option(R.string.troubleshooting_googlesupport, false))
|
||||
.option(new Option(R.string.troubleshooting_yourendo, false))
|
||||
.hint(new Hint(R.string.troubleshooting_hint1))
|
||||
.hint(new Hint(R.string.troubleshooting_hint2))
|
||||
.hint(new Hint(R.string.troubleshooting_hint3))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.insulin_label, R.string.insulin_ultrarapid,"insulin")
|
||||
.option(new Option(R.string.insulin_fiasp, true))
|
||||
.option(new Option(R.string.insulin_novorapid, false))
|
||||
.option(new Option(R.string.insulin_humalog, false))
|
||||
.option(new Option(R.string.insulin_actrapid, false))
|
||||
.hint(new Hint(R.string.insulin_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.sensitivity_label, R.string.sensitivity_which,"sensitivity")
|
||||
.option(new Option(R.string.sensitivityweightedaverage, true))
|
||||
.option(new Option(R.string.sensitivityoref1, false))
|
||||
.option(new Option(R.string.sensitivityaaps, true))
|
||||
.hint(new Hint(R.string.sensitivity_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.sensitivity_label, R.string.sensitivityuam_which,"sensitivityuam")
|
||||
.option(new Option(R.string.sensitivityweightedaverage, false))
|
||||
.option(new Option(R.string.sensitivityoref1, true))
|
||||
.option(new Option(R.string.sensitivityaaps, false))
|
||||
.hint(new Hint(R.string.sensitivity_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.wrongcarbs_label, R.string.wrongcarbs_whattodo,"wrongcarbs")
|
||||
.option(new Option(R.string.wrongcarbs_addfakeinsulin, false))
|
||||
.option(new Option(R.string.wrongcarbs_treatmentstab, true))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.extendedcarbs_label, R.string.extendedcarbs_handling,"extendedcarbs")
|
||||
.option(new Option(R.string.extendedcarbs_useextendedcarbs, true))
|
||||
.option(new Option(R.string.extendedcarbs_add, false))
|
||||
.option(new Option(R.string.extendedcarbs_useextendedbolus, false))
|
||||
.hint(new Hint(R.string.extendedcarbs_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.nsclient_label, R.string.nsclient_howcanyou,"nsclient")
|
||||
.option(new Option(R.string.nsclient_nightscout, true))
|
||||
.option(new Option(R.string.nsclientinternal, true))
|
||||
.option(new Option(R.string.nsclient_dexcomfollow, true))
|
||||
.option(new Option(R.string.nsclient_dexcomfollowxdrip, false))
|
||||
.option(new Option(R.string.nsclient_xdripfollower, true))
|
||||
.option(new Option(R.string.nsclient_looponiphone, false))
|
||||
.option(new Option(R.string.nsclient_spikeiphone, true))
|
||||
.hint(new Hint(R.string.nsclient_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.isf_label_exam, R.string.whatistrue,"isf")
|
||||
.option(new Option(R.string.isf_increasingvalue, true))
|
||||
.option(new Option(R.string.isf_decreasingvalue, false))
|
||||
.option(new Option(R.string.isf_noeffect, false))
|
||||
.option(new Option(R.string.isf_preferences, false))
|
||||
.option(new Option(R.string.isf_profile, false))
|
||||
.hint(new Hint(R.string.isf_hint1))
|
||||
.hint(new Hint(R.string.isf_hint2))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.ic_label_exam, R.string.whatistrue,"ic")
|
||||
.option(new Option(R.string.ic_increasingvalue, true))
|
||||
.option(new Option(R.string.ic_decreasingvalue, false))
|
||||
.option(new Option(R.string.ic_noeffect, false))
|
||||
.option(new Option(R.string.ic_different, false))
|
||||
.option(new Option(R.string.ic_meaning, false))
|
||||
.hint(new Hint(R.string.ic_hint1))
|
||||
);
|
||||
tasks.add(new ExamTask(R.string.profileswitch_label, R.string.profileswitch_pctwillchange,"profileswitch")
|
||||
.option(new Option(R.string.profileswitch_basalhigher, false))
|
||||
.option(new Option(R.string.profileswitch_basallower, true))
|
||||
.option(new Option(R.string.profileswitch_ichigher, true))
|
||||
.option(new Option(R.string.profileswitch_iclower, false))
|
||||
.option(new Option(R.string.profileswitch_isfhigher, true))
|
||||
.option(new Option(R.string.profileswitch_isflower, false))
|
||||
.option(new Option(R.string.profileswitch_overall, true))
|
||||
.option(new Option(R.string.profileswitch_targethigher, false))
|
||||
.option(new Option(R.string.profileswitch_targetlower, false))
|
||||
.option(new Option(R.string.profileswitch_targetbottom, false))
|
||||
.hint(new Hint(R.string.profileswitch_hint1))
|
||||
);
|
||||
|
||||
tasks.add(new ExamTask(R.string.profileswitch_label, R.string.profileswitchtime_iwant,"profileswitchtime")
|
||||
.option(new Option(R.string.profileswitchtime_1, false))
|
||||
.option(new Option(R.string.profileswitchtime__1, true))
|
||||
.option(new Option(R.string.profileswitchtime_60, false))
|
||||
.option(new Option(R.string.profileswitchtime__60, false))
|
||||
.hint(new Hint(R.string.profileswitchtime_hint1))
|
||||
);
|
||||
|
||||
tasks.add(new ExamTask(R.string.other_medication_label, R.string.other_medication_text,"otherMedicationWarning")
|
||||
.option(new Option(R.string.yes, true))
|
||||
.option(new Option(R.string.no, false))
|
||||
);
|
||||
|
||||
for (Task task : tasks)
|
||||
Collections.shuffle(((ExamTask)task).options);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
class Objective2(injector: HasAndroidInjector) : Objective(injector, "exam", R.string.objectives_exam_objective, R.string.objectives_exam_gate) {
|
||||
|
||||
init {
|
||||
tasks.add(ExamTask(this, R.string.prerequisites_label, R.string.prerequisites_what, "prerequisites")
|
||||
.option(Option(R.string.prerequisites_nightscout, true))
|
||||
.option(Option(R.string.prerequisites_computer, true))
|
||||
.option(Option(R.string.prerequisites_pump, true))
|
||||
.option(Option(R.string.prerequisites_beanandroiddeveloper, false))
|
||||
.hint(Hint(R.string.prerequisites_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.prerequisites2_label, R.string.prerequisites2_what, "prerequisites2")
|
||||
.option(Option(R.string.prerequisites2_profile, true))
|
||||
.option(Option(R.string.prerequisites2_device, true))
|
||||
.option(Option(R.string.prerequisites2_internet, false))
|
||||
.option(Option(R.string.prerequisites2_supportedcgm, true))
|
||||
.hint(Hint(R.string.prerequisites2_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.basaltest_label, R.string.basaltest_when, "basaltest")
|
||||
.option(Option(R.string.basaltest_fixed, false))
|
||||
.option(Option(R.string.basaltest_havingregularhighlow, true))
|
||||
.option(Option(R.string.basaltest_weekly, false))
|
||||
.option(Option(R.string.basaltest_beforeloop, true))
|
||||
.hint(Hint(R.string.basaltest_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.dia_label_exam, R.string.dia_whatmeansdia, "dia")
|
||||
.option(Option(R.string.dia_profile, true))
|
||||
.option(Option(R.string.dia_minimumis5h, true))
|
||||
.option(Option(R.string.dia_meaningisequaltodiapump, false))
|
||||
.option(Option(R.string.dia_valuemustbedetermined, true))
|
||||
.hint(Hint(R.string.dia_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.isf_label_exam, R.string.blank, "isf")
|
||||
.option(Option(R.string.isf_decreasingvalue, true))
|
||||
.option(Option(R.string.isf_preferences, false))
|
||||
.option(Option(R.string.isf_increasingvalue, false))
|
||||
.option(Option(R.string.isf_noeffect, false))
|
||||
.hint(Hint(R.string.isf_hint1))
|
||||
.hint(Hint(R.string.isf_hint2))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.ic_label_exam, R.string.blank, "ic")
|
||||
.option(Option(R.string.ic_increasingvalue, true))
|
||||
.option(Option(R.string.ic_decreasingvalue, false))
|
||||
.option(Option(R.string.ic_multiple, true))
|
||||
.option(Option(R.string.ic_isf, false))
|
||||
.hint(Hint(R.string.ic_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.hypott_label, R.string.hypott_whenhypott, "hypott")
|
||||
.option(Option(R.string.hypott_preventoversmb, true))
|
||||
.option(Option(R.string.hypott_exercise, false))
|
||||
.option(Option(R.string.hypott_wrongbasal, false))
|
||||
.option(Option(R.string.hypott_0basal, false))
|
||||
.hint(Hint(R.string.hypott_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.profileswitch_label, R.string.profileswitch_pctwillchange, "profileswitch")
|
||||
.option(Option(R.string.profileswitch_basallower, true))
|
||||
.option(Option(R.string.profileswitch_isfhigher, true))
|
||||
.option(Option(R.string.profileswitch_iclower, false))
|
||||
.option(Option(R.string.profileswitch_unchanged, false))
|
||||
.hint(Hint(R.string.profileswitch_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.profileswitch2_label, R.string.profileswitch2_pctwillchange, "profileswitch2")
|
||||
.option(Option(R.string.profileswitch2_bghigher, false))
|
||||
.option(Option(R.string.profileswitch2_basalhigher, true))
|
||||
.option(Option(R.string.profileswitch2_bgunchanged, true))
|
||||
.option(Option(R.string.profileswitch2_isfhigher, false))
|
||||
.hint(Hint(R.string.profileswitch_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.profileswitchtime_label, R.string.profileswitchtime_iwant, "profileswitchtime")
|
||||
.option(Option(R.string.profileswitchtime_2, false))
|
||||
.option(Option(R.string.profileswitchtime__2, true))
|
||||
.option(Option(R.string.profileswitchtime_tt, false))
|
||||
.option(Option(R.string.profileswitchtime_100, false))
|
||||
.hint(Hint(R.string.profileswitchtime_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.profileswitch4_label, R.string.blank, "profileswitch4")
|
||||
.option(Option(R.string.profileswitch4_rates, true))
|
||||
.option(Option(R.string.profileswitch4_internet, true))
|
||||
.option(Option(R.string.profileswitch4_sufficient, false))
|
||||
.option(Option(R.string.profileswitch4_multi, true))
|
||||
.hint(Hint(R.string.profileswitch_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.exerciseprofile_label, R.string.exerciseprofile_whattodo, "exercise")
|
||||
.option(Option(R.string.exerciseprofile_switchprofileabove100, false))
|
||||
.option(Option(R.string.exerciseprofile_switchprofilebelow100, true))
|
||||
.option(Option(R.string.exerciseprofile_suspendloop, false))
|
||||
.option(Option(R.string.exerciseprofile_leaveat100, false))
|
||||
.hint(Hint(R.string.exerciseprofile_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.exercise_label, R.string.exercise_whattodo, "exercise2")
|
||||
.option(Option(R.string.exercise_settt, true))
|
||||
.option(Option(R.string.exercise_setfinished, false))
|
||||
.option(Option(R.string.exercise_setunchanged, false))
|
||||
.option(Option(R.string.exercise_15g, false))
|
||||
.hint(Hint(R.string.exercise_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.noisycgm_label, R.string.noisycgm_whattodo, "noisycgm")
|
||||
.option(Option(R.string.noisycgm_nothing, false))
|
||||
.option(Option(R.string.noisycgm_pause, true))
|
||||
.option(Option(R.string.noisycgm_replacesensor, true))
|
||||
.option(Option(R.string.noisycgm_checksmoothing, true))
|
||||
.hint(Hint(R.string.noisycgm_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.pumpdisconnect_label, R.string.blank, "pumpdisconnect")
|
||||
.option(Option(R.string.pumpdisconnect_unnecessary, false))
|
||||
.option(Option(R.string.pumpdisconnect_missinginsulin, true))
|
||||
.option(Option(R.string.pumpdisconnect_notstop, false))
|
||||
.option(Option(R.string.pumpdisconnect_openloop, false))
|
||||
.hint(Hint(R.string.pumpdisconnect_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.insulin_label, R.string.insulin_ultrarapid, "insulin")
|
||||
.option(Option(R.string.insulin_novorapid, false))
|
||||
.option(Option(R.string.insulin_humalog, false))
|
||||
.option(Option(R.string.insulin_actrapid, false))
|
||||
.option(Option(R.string.insulin_fiasp, true))
|
||||
.hint(Hint(R.string.insulin_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.sensitivity_label, R.string.blank, "sensitivity")
|
||||
.option(Option(R.string.sensitivity_adjust, true))
|
||||
.option(Option(R.string.sensitivity_edit, false))
|
||||
.option(Option(R.string.sensitivity_cannula, true))
|
||||
.option(Option(R.string.sensitivity_time, true))
|
||||
.hint(Hint(R.string.sensitivity_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.objectives_label, R.string.objectives_howtosave, "objectives")
|
||||
.option(Option(R.string.objectives_notesettings, false))
|
||||
.option(Option(R.string.objectives_afterobjective, true))
|
||||
.option(Option(R.string.objectives_afterchange, true))
|
||||
.option(Option(R.string.objectives_afterinitialsetup, true))
|
||||
.hint(Hint(R.string.objectives_hint1))
|
||||
.hint(Hint(R.string.objectives_hint2))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.objectives2_label, R.string.objectives_howtosave, "objectives2")
|
||||
.option(Option(R.string.objectives2_maintenance, true))
|
||||
.option(Option(R.string.objectives2_internalstorage, true))
|
||||
.option(Option(R.string.objectives2_cloud, true))
|
||||
.option(Option(R.string.objectives2_easyrestore, false))
|
||||
.hint(Hint(R.string.objectives_hint1))
|
||||
.hint(Hint(R.string.objectives_hint2))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.update_label, R.string.blank, "update")
|
||||
.option(Option(R.string.update_git, true))
|
||||
.option(Option(R.string.update_askfriend, false))
|
||||
.option(Option(R.string.update_keys, true))
|
||||
.option(Option(R.string.update_asap, true))
|
||||
.hint(Hint(R.string.update_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.troubleshooting_label, R.string.troubleshooting_wheretoask, "troubleshooting")
|
||||
.option(Option(R.string.troubleshooting_fb, true))
|
||||
.option(Option(R.string.troubleshooting_wiki, true))
|
||||
.option(Option(R.string.troubleshooting_gitter, true))
|
||||
.option(Option(R.string.troubleshooting_yourendo, false))
|
||||
.hint(Hint(R.string.troubleshooting_hint1))
|
||||
.hint(Hint(R.string.troubleshooting_hint2))
|
||||
.hint(Hint(R.string.troubleshooting_hint3))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.wrongcarbs_label, R.string.wrongcarbs_whattodo, "wrongcarbs")
|
||||
.option(Option(R.string.wrongcarbs_addinsulin, false))
|
||||
.option(Option(R.string.wrongcarbs_treatmentstab, true))
|
||||
.option(Option(R.string.wrongcarbs_donothing, false))
|
||||
.option(Option(R.string.wrongcarbs_bolus, false))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.wronginsulin_label, R.string.wronginsulin_whattodo, "wronginsulin")
|
||||
.option(Option(R.string.wronginsulin_careportal, false))
|
||||
.option(Option(R.string.wronginsulin_compare, true))
|
||||
.option(Option(R.string.wronginsulin_prime, true))
|
||||
.option(Option(R.string.wrongcarbs_donothing, false))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.iob_label, R.string.blank, "iob")
|
||||
.option(Option(R.string.iob_value, true))
|
||||
.option(Option(R.string.iob_hightemp, false))
|
||||
.option(Option(R.string.iob_negiob, true))
|
||||
.option(Option(R.string.iob_posiob, true))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.breadgrams_label, R.string.blank, "breadgrams")
|
||||
.option(Option(R.string.breadgrams_grams, true))
|
||||
.option(Option(R.string.breadgrams_exchange, false))
|
||||
.option(Option(R.string.breadgrams_decay, true))
|
||||
.option(Option(R.string.breadgrams_calc, true))
|
||||
.hint(Hint(R.string.breadgrams_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.extendedcarbs_label, R.string.extendedcarbs_handling, "extendedcarbs")
|
||||
.option(Option(R.string.extendedcarbs_future, true))
|
||||
.option(Option(R.string.extendedcarbs_free, false))
|
||||
.option(Option(R.string.extendedcarbs_fat, true))
|
||||
.option(Option(R.string.extendedcarbs_rescue, false))
|
||||
.hint(Hint(R.string.extendedcarbs_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.nsclient_label, R.string.nsclient_howcanyou, "nsclient")
|
||||
.option(Option(R.string.nsclient_nightscout, true))
|
||||
.option(Option(R.string.nsclient_dexcomfollow, true))
|
||||
.option(Option(R.string.nsclient_data, true))
|
||||
.option(Option(R.string.nsclient_fullcontrol, false))
|
||||
.hint(Hint(R.string.nsclient_hint1))
|
||||
)
|
||||
tasks.add(ExamTask(this, R.string.other_medication_label, R.string.other_medication_text, "otherMedicationWarning")
|
||||
.option(Option(R.string.yes, true))
|
||||
.option(Option(R.string.no, false))
|
||||
)
|
||||
for (task in tasks) (task as ExamTask).options.shuffle()
|
||||
|
||||
for (task in tasks) {
|
||||
if (!task.isCompleted()) accomplishedOn = 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
public class Objective3 extends Objective {
|
||||
@Inject SP sp;
|
||||
@Inject ObjectivesPlugin objectivesPlugin;
|
||||
@Inject ResourceHelper resourceHelper;
|
||||
@Inject NSClientPlugin nsClientPlugin;
|
||||
|
||||
private final int MANUAL_ENACTS_NEEDED = 20;
|
||||
|
||||
@Inject
|
||||
public Objective3(HasAndroidInjector injector) {
|
||||
super(injector, "openloop", R.string.objectives_openloop_objective, R.string.objectives_openloop_gate);
|
||||
// disable option for skipping objectives for now
|
||||
// hasSpecialInput = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new MinimumDurationTask(T.days(7).msecs()));
|
||||
tasks.add(new Task(R.string.objectives_manualenacts) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return sp.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProgress() {
|
||||
if (sp.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED)
|
||||
return resourceHelper.gs(R.string.completed_well_done);
|
||||
else
|
||||
return sp.getInt(R.string.key_ObjectivesmanualEnacts, 0) + " / " + MANUAL_ENACTS_NEEDED;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialActionEnabled() {
|
||||
return NSClientService.isConnected && NSClientService.hasWriteAuth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void specialAction(FragmentActivity activity, String input) {
|
||||
objectivesPlugin.completeObjectives(activity, input);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
class Objective3 @Inject constructor(injector: HasAndroidInjector) : Objective(injector, "openloop", R.string.objectives_openloop_objective, R.string.objectives_openloop_gate) {
|
||||
|
||||
@Inject lateinit var objectivesPlugin: ObjectivesPlugin
|
||||
@Inject lateinit var nsClientPlugin: NSClientPlugin
|
||||
|
||||
init {
|
||||
tasks.add(MinimumDurationTask(this, T.days(7).msecs()))
|
||||
tasks.add(object : Task(this, R.string.objectives_manualenacts) {
|
||||
override fun isCompleted(): Boolean {
|
||||
return sp.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED
|
||||
}
|
||||
|
||||
override val progress: String
|
||||
get() = if (sp.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED) resourceHelper.gs(R.string.completed_well_done) else sp.getInt(R.string.key_ObjectivesmanualEnacts, 0).toString() + " / " + MANUAL_ENACTS_NEEDED
|
||||
})
|
||||
}
|
||||
|
||||
override fun specialActionEnabled(): Boolean =
|
||||
NSClientService.isConnected && NSClientService.hasWriteAuth
|
||||
|
||||
override fun specialAction(activity: FragmentActivity, input: String) {
|
||||
objectivesPlugin.completeObjectives(activity, input)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val MANUAL_ENACTS_NEEDED = 20
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
||||
public class Objective4 extends Objective {
|
||||
|
||||
public Objective4(HasAndroidInjector injector) {
|
||||
super(injector, "maxbasal", R.string.objectives_maxbasal_objective, R.string.objectives_maxbasal_gate);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
class Objective4(injector: HasAndroidInjector) : Objective(injector, "maxbasal", R.string.objectives_maxbasal_objective, R.string.objectives_maxbasal_gate)
|
|
@ -1,32 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
public class Objective5 extends Objective {
|
||||
@Inject SafetyPlugin safetyPlugin;
|
||||
|
||||
public Objective5(HasAndroidInjector injector) {
|
||||
super(injector, "maxiobzero", R.string.objectives_maxiobzero_objective, R.string.objectives_maxiobzero_gate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new MinimumDurationTask(T.days(5).msecs()));
|
||||
tasks.add(new Task(R.string.closedmodeenabled) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
Constraint<Boolean> closedLoopEnabled = new Constraint<>(true);
|
||||
safetyPlugin.isClosedLoopAllowed(closedLoopEnabled);
|
||||
return closedLoopEnabled.value();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
class Objective5(injector: HasAndroidInjector) : Objective(injector, "maxiobzero", R.string.objectives_maxiobzero_objective, R.string.objectives_maxiobzero_gate) {
|
||||
|
||||
@Inject lateinit var safetyPlugin: SafetyPlugin
|
||||
|
||||
init {
|
||||
tasks.add(MinimumDurationTask(this, T.days(5).msecs()))
|
||||
tasks.add(object : Task(this, R.string.closedmodeenabled) {
|
||||
override fun isCompleted(): Boolean {
|
||||
val closedLoopEnabled = Constraint(true)
|
||||
safetyPlugin.isClosedLoopAllowed(closedLoopEnabled)
|
||||
return closedLoopEnabled.value()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
public class Objective6 extends Objective {
|
||||
@Inject ConstraintChecker constraintChecker;
|
||||
|
||||
public Objective6(HasAndroidInjector injector) {
|
||||
super(injector, "maxiob", R.string.objectives_maxiob_objective, R.string.objectives_maxiob_gate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new MinimumDurationTask(T.days(1).msecs()));
|
||||
tasks.add(new Task(R.string.maxiobset) {
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
double maxIOB = constraintChecker.getMaxIOBAllowed().value();
|
||||
return maxIOB > 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
class Objective6(injector: HasAndroidInjector) : Objective(injector, "maxiob", R.string.objectives_maxiob_objective, R.string.objectives_maxiob_gate) {
|
||||
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
|
||||
init {
|
||||
tasks.add(MinimumDurationTask(this, T.days(1).msecs()))
|
||||
tasks.add(object : Task(this, R.string.maxiobset) {
|
||||
override fun isCompleted(): Boolean {
|
||||
val maxIOB = constraintChecker.getMaxIOBAllowed().value()
|
||||
return maxIOB > 0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
public class Objective7 extends Objective {
|
||||
|
||||
public Objective7(HasAndroidInjector injector) {
|
||||
super(injector, "autosens", R.string.objectives_autosens_objective, R.string.objectives_autosens_gate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new MinimumDurationTask(T.days(7).msecs()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.T
|
||||
|
||||
class Objective7(injector: HasAndroidInjector) : Objective(injector, "autosens", R.string.objectives_autosens_objective, R.string.objectives_autosens_gate) {
|
||||
|
||||
init {
|
||||
tasks.add(MinimumDurationTask(this, T.days(7).msecs()))
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
public class Objective8 extends Objective {
|
||||
|
||||
public Objective8(HasAndroidInjector injector) {
|
||||
super(injector, "ama", R.string.objectives_ama_objective, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new MinimumDurationTask(T.days(28).msecs()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.T
|
||||
|
||||
class Objective8(injector: HasAndroidInjector) : Objective(injector, "ama", R.string.objectives_ama_objective, 0) {
|
||||
|
||||
init {
|
||||
tasks.add(MinimumDurationTask(this, T.days(28).msecs()))
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
public class Objective9 extends Objective {
|
||||
|
||||
public Objective9(HasAndroidInjector injector) {
|
||||
super(injector, "smb", R.string.objectives_smb_objective, R.string.objectives_smb_gate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupTasks(List<Task> tasks) {
|
||||
tasks.add(new MinimumDurationTask(T.days(28).msecs()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.T
|
||||
|
||||
class Objective9(injector: HasAndroidInjector) : Objective(injector, "smb", R.string.objectives_smb_objective, R.string.objectives_smb_gate) {
|
||||
|
||||
init {
|
||||
tasks.add(MinimumDurationTask(this, T.days(28).msecs()))
|
||||
}
|
||||
}
|
|
@ -1,289 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.safety;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.android.HasAndroidInjector;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||
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.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
||||
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;
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
@Singleton
|
||||
public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
||||
|
||||
private final SP sp;
|
||||
private final RxBusWrapper rxBus;
|
||||
private final ConstraintChecker constraintChecker;
|
||||
private final OpenAPSAMAPlugin openAPSAMAPlugin;
|
||||
private final OpenAPSSMBPlugin openAPSSMBPlugin;
|
||||
private final SensitivityOref1Plugin sensitivityOref1Plugin;
|
||||
private final ActivePluginProvider activePlugin;
|
||||
private final HardLimits hardLimits;
|
||||
private final BuildHelper buildHelper;
|
||||
private final TreatmentsPlugin treatmentsPlugin;
|
||||
private final Config config;
|
||||
|
||||
@Inject
|
||||
public SafetyPlugin(
|
||||
HasAndroidInjector injector,
|
||||
AAPSLogger aapsLogger,
|
||||
ResourceHelper resourceHelper,
|
||||
SP sp,
|
||||
RxBusWrapper rxBus,
|
||||
ConstraintChecker constraintChecker,
|
||||
OpenAPSAMAPlugin openAPSAMAPlugin,
|
||||
OpenAPSSMBPlugin openAPSSMBPlugin,
|
||||
SensitivityOref1Plugin sensitivityOref1Plugin,
|
||||
ActivePluginProvider activePlugin,
|
||||
HardLimits hardLimits,
|
||||
BuildHelper buildHelper,
|
||||
TreatmentsPlugin treatmentsPlugin,
|
||||
Config config
|
||||
) {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.CONSTRAINTS)
|
||||
.neverVisible(true)
|
||||
.alwaysEnabled(true)
|
||||
.showInList(false)
|
||||
.pluginName(R.string.safety)
|
||||
.preferencesId(R.xml.pref_safety),
|
||||
aapsLogger, resourceHelper, injector
|
||||
);
|
||||
this.sp = sp;
|
||||
this.rxBus = rxBus;
|
||||
this.constraintChecker = constraintChecker;
|
||||
this.openAPSAMAPlugin = openAPSAMAPlugin;
|
||||
this.openAPSSMBPlugin = openAPSSMBPlugin;
|
||||
this.sensitivityOref1Plugin = sensitivityOref1Plugin;
|
||||
this.activePlugin = activePlugin;
|
||||
this.hardLimits = hardLimits;
|
||||
this.buildHelper = buildHelper;
|
||||
this.treatmentsPlugin = treatmentsPlugin;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraints interface
|
||||
**/
|
||||
@NonNull @Override
|
||||
public Constraint<Boolean> isLoopInvocationAllowed(@NonNull Constraint<Boolean> value) {
|
||||
if (!activePlugin.getActivePump().getPumpDescription().isTempBasalCapable)
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.pumpisnottempbasalcapable), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Boolean> isClosedLoopAllowed(@NonNull Constraint<Boolean> value) {
|
||||
String mode = sp.getString(R.string.key_aps_mode, "open");
|
||||
if ((mode.equals("open")))
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.closedmodedisabledinpreferences), this);
|
||||
|
||||
if (!buildHelper.isEngineeringModeOrRelease()) {
|
||||
if (value.value()) {
|
||||
Notification n = new Notification(Notification.TOAST_ALARM, getResourceHelper().gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL);
|
||||
rxBus.send(new EventNewNotification(n));
|
||||
}
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.closed_loop_disabled_on_dev_branch), this);
|
||||
}
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
if (!pump.isFakingTempsByExtendedBoluses() && treatmentsPlugin.isInHistoryExtendedBoluslInProgress()) {
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.closed_loop_disabled_with_eb), this);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Boolean> isAutosensModeEnabled(@NonNull Constraint<Boolean> value) {
|
||||
boolean enabled = sp.getBoolean(R.string.key_openapsama_useautosens, false);
|
||||
if (!enabled)
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.autosensdisabledinpreferences), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Boolean> isSMBModeEnabled(@NonNull Constraint<Boolean> value) {
|
||||
boolean enabled = sp.getBoolean(R.string.key_use_smb, false);
|
||||
if (!enabled)
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.smbdisabledinpreferences), this);
|
||||
Constraint<Boolean> closedLoop = constraintChecker.isClosedLoopAllowed();
|
||||
if (!closedLoop.value())
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.smbnotallowedinopenloopmode), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Boolean> isUAMEnabled(@NonNull Constraint<Boolean> value) {
|
||||
boolean enabled = sp.getBoolean(R.string.key_use_uam, false);
|
||||
if (!enabled)
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.uamdisabledinpreferences), this);
|
||||
boolean oref1Enabled = sensitivityOref1Plugin.isEnabled(PluginType.SENSITIVITY);
|
||||
if (!oref1Enabled)
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.uamdisabledoref1notselected), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Boolean> isAdvancedFilteringEnabled(@NonNull Constraint<Boolean> value) {
|
||||
BgSourceInterface bgSource = activePlugin.getActiveBgSource();
|
||||
|
||||
if (!bgSource.advancedFilteringSupported())
|
||||
value.set(getAapsLogger(), false, getResourceHelper().gs(R.string.smbalwaysdisabled), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, @NonNull Profile profile) {
|
||||
|
||||
absoluteRate.setIfGreater(getAapsLogger(), 0d, String.format(getResourceHelper().gs(R.string.limitingbasalratio), 0d, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
||||
|
||||
if (config.getAPS()) {
|
||||
double maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1d);
|
||||
if (maxBasal < profile.getMaxDailyBasal()) {
|
||||
maxBasal = profile.getMaxDailyBasal();
|
||||
absoluteRate.addReason(getResourceHelper().gs(R.string.increasingmaxbasal), this);
|
||||
}
|
||||
absoluteRate.setIfSmaller(getAapsLogger(), maxBasal, String.format(getResourceHelper().gs(R.string.limitingbasalratio), maxBasal, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||
double maxBasalMult = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d);
|
||||
double maxFromBasalMult = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
|
||||
absoluteRate.setIfSmaller(getAapsLogger(), maxFromBasalMult, String.format(getResourceHelper().gs(R.string.limitingbasalratio), maxFromBasalMult, getResourceHelper().gs(R.string.maxbasalmultiplier)), this);
|
||||
|
||||
double maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d);
|
||||
double maxFromDaily = Math.floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100;
|
||||
absoluteRate.setIfSmaller(getAapsLogger(), maxFromDaily, String.format(getResourceHelper().gs(R.string.limitingbasalratio), maxFromDaily, getResourceHelper().gs(R.string.maxdailybasalmultiplier)), this);
|
||||
}
|
||||
|
||||
absoluteRate.setIfSmaller(getAapsLogger(), hardLimits.maxBasal(), String.format(getResourceHelper().gs(R.string.limitingbasalratio), hardLimits.maxBasal(), getResourceHelper().gs(R.string.hardlimit)), this);
|
||||
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
// check for pump max
|
||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
absoluteRate.setIfSmaller(getAapsLogger(), pumpLimit, String.format(getResourceHelper().gs(R.string.limitingbasalratio), pumpLimit, getResourceHelper().gs(R.string.pumplimit)), this);
|
||||
}
|
||||
|
||||
// do rounding
|
||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||
absoluteRate.set(getAapsLogger(), Round.roundTo(absoluteRate.value(), pump.getPumpDescription().tempAbsoluteStep));
|
||||
}
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
|
||||
|
||||
Double currentBasal = profile.getBasal();
|
||||
double absoluteRate = currentBasal * ((double) percentRate.originalValue() / 100);
|
||||
|
||||
percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this);
|
||||
|
||||
Constraint<Double> absoluteConstraint = new Constraint<>(absoluteRate);
|
||||
applyBasalConstraints(absoluteConstraint, profile);
|
||||
percentRate.copyReasons(absoluteConstraint);
|
||||
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
|
||||
int percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue();
|
||||
if (percentRateAfterConst < 100)
|
||||
percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, (double) pump.getPumpDescription().tempPercentStep).intValue();
|
||||
else
|
||||
percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, (double) pump.getPumpDescription().tempPercentStep).intValue();
|
||||
|
||||
percentRate.set(getAapsLogger(), percentRateAfterConst, String.format(getResourceHelper().gs(R.string.limitingpercentrate), percentRateAfterConst, getResourceHelper().gs(R.string.pumplimit)), this);
|
||||
|
||||
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
percentRate.setIfSmaller(getAapsLogger(), (int) pumpLimit, String.format(getResourceHelper().gs(R.string.limitingbasalratio), pumpLimit, getResourceHelper().gs(R.string.pumplimit)), this);
|
||||
}
|
||||
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
|
||||
insulin.setIfGreater(getAapsLogger(), 0d, String.format(getResourceHelper().gs(R.string.limitingbolus), 0d, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
||||
|
||||
Double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3d);
|
||||
insulin.setIfSmaller(getAapsLogger(), maxBolus, String.format(getResourceHelper().gs(R.string.limitingbolus), maxBolus, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
insulin.setIfSmaller(getAapsLogger(), hardLimits.maxBolus(), String.format(getResourceHelper().gs(R.string.limitingbolus), hardLimits.maxBolus(), getResourceHelper().gs(R.string.hardlimit)), this);
|
||||
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
double rounded = pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value());
|
||||
insulin.setIfDifferent(getAapsLogger(), rounded, getResourceHelper().gs(R.string.pumplimit), this);
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) {
|
||||
insulin.setIfGreater(getAapsLogger(), 0d, String.format(getResourceHelper().gs(R.string.limitingextendedbolus), 0d, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
||||
|
||||
Double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3d);
|
||||
insulin.setIfSmaller(getAapsLogger(), maxBolus, String.format(getResourceHelper().gs(R.string.limitingextendedbolus), maxBolus, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
insulin.setIfSmaller(getAapsLogger(), hardLimits.maxBolus(), String.format(getResourceHelper().gs(R.string.limitingextendedbolus), hardLimits.maxBolus(), getResourceHelper().gs(R.string.hardlimit)), this);
|
||||
|
||||
PumpInterface pump = activePlugin.getActivePump();
|
||||
double rounded = pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value());
|
||||
insulin.setIfDifferent(getAapsLogger(), rounded, getResourceHelper().gs(R.string.pumplimit), this);
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
|
||||
carbs.setIfGreater(getAapsLogger(), 0, String.format(getResourceHelper().gs(R.string.limitingcarbs), 0, getResourceHelper().gs(R.string.itmustbepositivevalue)), this);
|
||||
|
||||
Integer maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
|
||||
carbs.setIfSmaller(getAapsLogger(), maxCarbs, String.format(getResourceHelper().gs(R.string.limitingcarbs), maxCarbs, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
return carbs;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Constraint<Double> applyMaxIOBConstraints(@NonNull Constraint<Double> maxIob) {
|
||||
double maxIobPref;
|
||||
String apsmode = sp.getString(R.string.key_aps_mode, "open");
|
||||
if (openAPSSMBPlugin.isEnabled(PluginType.APS))
|
||||
maxIobPref = sp.getDouble(R.string.key_openapssmb_max_iob, 3d);
|
||||
else
|
||||
maxIobPref = sp.getDouble(R.string.key_openapsma_max_iob, 1.5d);
|
||||
maxIob.setIfSmaller(getAapsLogger(), maxIobPref, String.format(getResourceHelper().gs(R.string.limitingiob), maxIobPref, getResourceHelper().gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
if (openAPSAMAPlugin.isEnabled(PluginType.APS))
|
||||
maxIob.setIfSmaller(getAapsLogger(), hardLimits.maxIobAMA(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.maxIobAMA(), getResourceHelper().gs(R.string.hardlimit)), this);
|
||||
if (openAPSSMBPlugin.isEnabled(PluginType.APS))
|
||||
maxIob.setIfSmaller(getAapsLogger(), hardLimits.maxIobSMB(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.maxIobSMB(), getResourceHelper().gs(R.string.hardlimit)), this);
|
||||
if ((apsmode.equals("lgs")))
|
||||
maxIob.setIfSmaller(getAapsLogger(), hardLimits.getMAXIOB_LGS(), String.format(getResourceHelper().gs(R.string.limitingiob), hardLimits.getMAXIOB_LGS(), getResourceHelper().gs(R.string.lowglucosesuspend)), this);
|
||||
|
||||
return maxIob;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue