Merge branch 'dev2_dana_combo_only' of github.com:nightscout/AndroidAPS into dev2_dana_combo_only

This commit is contained in:
Andy Rozman 2021-04-16 21:49:31 +01:00
commit 99946dd728
753 changed files with 33771 additions and 12351 deletions

View file

@ -2,19 +2,24 @@
<dictionary name="project-dictionary"> <dictionary name="project-dictionary">
<words> <words>
<w>aaps</w> <w>aaps</w>
<w>acked</w>
<w>actionstring</w> <w>actionstring</w>
<w>allowednumbers</w> <w>allowednumbers</w>
<w>androidaps</w> <w>androidaps</w>
<w>autosens</w> <w>autosens</w>
<w>autosensdata</w> <w>autosensdata</w>
<w>autosense</w>
<w>bage</w> <w>bage</w>
<w>basaliob</w>
<w>basals</w> <w>basals</w>
<w>bgcheck</w> <w>bgcheck</w>
<w>bgsource</w>
<w>bolusing</w> <w>bolusing</w>
<w>carb</w> <w>carb</w>
<w>carbs</w> <w>carbs</w>
<w>carbsreq</w> <w>carbsreq</w>
<w>careportal</w> <w>careportal</w>
<w>cellnovo</w>
<w>crashlytics</w> <w>crashlytics</w>
<w>danar</w> <w>danar</w>
<w>danars</w> <w>danars</w>
@ -23,6 +28,7 @@
<w>dexcom</w> <w>dexcom</w>
<w>dexdrip</w> <w>dexdrip</w>
<w>enteredby</w> <w>enteredby</w>
<w>enteredinsulin</w>
<w>eveningoutpost</w> <w>eveningoutpost</w>
<w>eversense</w> <w>eversense</w>
<w>extendedbolus</w> <w>extendedbolus</w>
@ -32,12 +38,15 @@
<w>gson</w> <w>gson</w>
<w>hmac</w> <w>hmac</w>
<w>iage</w> <w>iage</w>
<w>insulet</w>
<w>iobtotal</w> <w>iobtotal</w>
<w>libre</w>
<w>listdelimiter</w> <w>listdelimiter</w>
<w>localprofile</w> <w>localprofile</w>
<w>medtronic</w> <w>medtronic</w>
<w>mgdl</w> <w>mgdl</w>
<w>mmol</w> <w>mmol</w>
<w>multiwave</w>
<w>netinsulin</w> <w>netinsulin</w>
<w>netratio</w> <w>netratio</w>
<w>nightscout</w> <w>nightscout</w>
@ -45,6 +54,7 @@
<w>nsclient</w> <w>nsclient</w>
<w>okcancel</w> <w>okcancel</w>
<w>omnipod</w> <w>omnipod</w>
<w>openaps</w>
<w>oref</w> <w>oref</w>
<w>passcode</w> <w>passcode</w>
<w>poctech</w> <w>poctech</w>
@ -56,7 +66,9 @@
<w>refresheventsfromnightscout</w> <w>refresheventsfromnightscout</w>
<w>rileylink</w> <w>rileylink</w>
<w>roboelectric</w> <w>roboelectric</w>
<w>sitechange</w>
<w>smscommunicator</w> <w>smscommunicator</w>
<w>sooil</w>
<w>soundid</w> <w>soundid</w>
<w>splitted</w> <w>splitted</w>
<w>superbolus</w> <w>superbolus</w>
@ -73,6 +85,9 @@
<w>uart</w> <w>uart</w>
<w>wizzardpage</w> <w>wizzardpage</w>
<w>xdrip</w> <w>xdrip</w>
<w>ypso</w>
<w>ypsomed</w>
<w>ypsopump</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

View file

@ -111,7 +111,7 @@ android {
defaultConfig { defaultConfig {
multiDexEnabled true multiDexEnabled true
versionCode 1500 versionCode 1500
version "2.8.2.1-dev-e" version "2.8.2.1-dev-e3"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -1,35 +1,8 @@
package info.nightscout.androidaps package info.nightscout.androidaps
import android.os.SystemClock
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest import androidx.test.filters.LargeTest
import androidx.test.rule.ActivityTestRule
import androidx.test.rule.GrantPermissionRule
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.source.RandomBgPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.extensions.isRunningTest
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONObject
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import javax.inject.Inject
@LargeTest @LargeTest
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@ -89,7 +62,7 @@ class RealPumpTest {
localProfilePlugin.numOfProfiles = 0 localProfilePlugin.numOfProfiles = 0
val singleProfile = LocalProfilePlugin.SingleProfile().copyFrom(localProfilePlugin.rawProfile, profile, "TestProfile") val singleProfile = LocalProfilePlugin.SingleProfile().copyFrom(localProfilePlugin.rawProfile, profile, "TestProfile")
localProfilePlugin.addProfile(singleProfile) localProfilePlugin.addProfile(singleProfile)
val profileSwitch = profileFunction.prepareProfileSwitch(localProfilePlugin.createProfileStore(), "TestProfile", 0, 100, 0, DateUtil.now()) val profileSwitch = profileFunction.prepareProfileSwitch(localProfilePlugin.createProfileStore(), "TestProfile", 0, 100, 0, dateUtil._now())
treatmentsPlugin.addToHistoryProfileSwitch(profileSwitch) treatmentsPlugin.addToHistoryProfileSwitch(profileSwitch)
// Insulin // Insulin
configBuilderPlugin.performPluginSwitch(insulinOrefUltraRapidActingPlugin, true, PluginType.INSULIN) configBuilderPlugin.performPluginSwitch(insulinOrefUltraRapidActingPlugin, true, PluginType.INSULIN)

View file

@ -0,0 +1,2 @@
package info.nightscout.androidaps

View file

@ -32,15 +32,20 @@ import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.activities.ProfileHelperActivity import info.nightscout.androidaps.activities.ProfileHelperActivity
import info.nightscout.androidaps.activities.SingleFragmentActivity import info.nightscout.androidaps.activities.SingleFragmentActivity
import info.nightscout.androidaps.activities.StatsActivity import info.nightscout.androidaps.activities.StatsActivity
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.ActivityMainBinding import info.nightscout.androidaps.databinding.ActivityMainBinding
import info.nightscout.androidaps.events.EventAppExit import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRebuildTabs import info.nightscout.androidaps.events.EventRebuildTabs
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.IconsProvider
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -56,7 +61,6 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.IconsProvider
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.tabs.TabPageAdapter import info.nightscout.androidaps.utils.tabs.TabPageAdapter
@ -80,13 +84,14 @@ class MainActivity : NoSplashAppCompatActivity() {
@Inject lateinit var loopPlugin: LoopPlugin @Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var nsSettingsStatus: NSSettingsStatus @Inject lateinit var nsSettingsStatus: NSSettingsStatus
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var protectionCheck: ProtectionCheck @Inject lateinit var protectionCheck: ProtectionCheck
@Inject lateinit var iconsProvider: IconsProvider @Inject lateinit var iconsProvider: IconsProvider
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin @Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
private var pluginPreferencesMenuItem: MenuItem? = null private var pluginPreferencesMenuItem: MenuItem? = null
@ -316,6 +321,7 @@ class MainActivity : NoSplashAppCompatActivity() {
R.id.nav_exit -> { R.id.nav_exit -> {
aapsLogger.debug(LTag.CORE, "Exiting") aapsLogger.debug(LTag.CORE, "Exiting")
uel.log(Action.EXIT_AAPS, Sources.Aaps)
rxBus.send(EventAppExit()) rxBus.send(EventAppExit())
finish() finish()
System.runFinalization() System.runFinalization()
@ -375,7 +381,7 @@ class MainActivity : NoSplashAppCompatActivity() {
if (!config.NSCLIENT && !config.PUMPCONTROL) if (!config.NSCLIENT && !config.PUMPCONTROL)
activePlugin.activeAPS.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Aps", it::class.java.simpleName) } activePlugin.activeAPS.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Aps", it::class.java.simpleName) }
activePlugin.activeBgSource.let { fabricPrivacy.firebaseAnalytics.setUserProperty("BgSource", it::class.java.simpleName) } activePlugin.activeBgSource.let { fabricPrivacy.firebaseAnalytics.setUserProperty("BgSource", it::class.java.simpleName) }
fabricPrivacy.firebaseAnalytics.setUserProperty("Profile", activePlugin.activeProfileInterface.javaClass.simpleName) fabricPrivacy.firebaseAnalytics.setUserProperty("Profile", activePlugin.activeProfileSource.javaClass.simpleName)
activePlugin.activeSensitivity.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Sensitivity", it::class.java.simpleName) } activePlugin.activeSensitivity.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Sensitivity", it::class.java.simpleName) }
activePlugin.activeInsulin.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Insulin", it::class.java.simpleName) } activePlugin.activeInsulin.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Insulin", it::class.java.simpleName) }
// Add to crash log too // Add to crash log too

View file

@ -5,31 +5,38 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import android.os.Build
import com.j256.ormlite.android.apptools.OpenHelperManager import com.j256.ormlite.android.apptools.OpenHelperManager
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.DaggerApplication import dagger.android.DaggerApplication
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction
import info.nightscout.androidaps.database.transactions.VersionChangeTransaction import info.nightscout.androidaps.database.transactions.VersionChangeTransaction
import info.nightscout.androidaps.db.CompatDBHelper import info.nightscout.androidaps.db.CompatDBHelper
import info.nightscout.androidaps.db.DatabaseHelper import info.nightscout.androidaps.db.DatabaseHelper
import info.nightscout.androidaps.db.StaticInjector import info.nightscout.androidaps.db.StaticInjector
import info.nightscout.androidaps.dependencyInjection.DaggerAppComponent import info.nightscout.androidaps.dependencyInjection.DaggerAppComponent
import info.nightscout.androidaps.interfaces.ConfigBuilder
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.PluginStore import info.nightscout.androidaps.plugins.configBuilder.PluginStore
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.receivers.BTReceiver import info.nightscout.androidaps.receivers.BTReceiver
import info.nightscout.androidaps.receivers.ChargingStateReceiver import info.nightscout.androidaps.receivers.ChargingStateReceiver
import info.nightscout.androidaps.receivers.KeepAliveReceiver.KeepAliveManager import info.nightscout.androidaps.receivers.KeepAliveReceiver.KeepAliveManager
import info.nightscout.androidaps.receivers.NetworkChangeReceiver import info.nightscout.androidaps.receivers.NetworkChangeReceiver
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
import info.nightscout.androidaps.utils.ActivityMonitor import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.locale.LocaleHelper.update import info.nightscout.androidaps.utils.locale.LocaleHelper.update
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import net.danlew.android.joda.JodaTimeAndroid import net.danlew.android.joda.JodaTimeAndroid
import javax.inject.Inject import javax.inject.Inject
@ -42,14 +49,15 @@ class MainApp : DaggerApplication() {
@Inject lateinit var activityMonitor: ActivityMonitor @Inject lateinit var activityMonitor: ActivityMonitor
@Inject lateinit var versionCheckersUtils: VersionCheckerUtils @Inject lateinit var versionCheckersUtils: VersionCheckerUtils
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin @Inject lateinit var configBuilder: ConfigBuilder
@Inject lateinit var keepAliveManager: KeepAliveManager @Inject lateinit var keepAliveManager: KeepAliveManager
@Inject lateinit var plugins: List<@JvmSuppressWildcards PluginBase> @Inject lateinit var plugins: List<@JvmSuppressWildcards PluginBase>
@Inject lateinit var compatDBHelper: CompatDBHelper @Inject lateinit var compatDBHelper: CompatDBHelper
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var staticInjector: StaticInjector// TODO avoid , here fake only to initialize @Inject lateinit var staticInjector: StaticInjector// TODO avoid , here fake only to initialize
@Inject lateinit var uel: UserEntryLogger
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -63,8 +71,9 @@ class MainApp : DaggerApplication() {
gitRemote = null gitRemote = null
commitHash = null commitHash = null
} }
disposable.add(repository.runTransaction(VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe()) disposable += repository.runTransaction(VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe()
disposable.add(compatDBHelper.dbChangeDisposable()) disposable += repository.runTransaction(InsertIfNewByTimestampTherapyEventTransaction(timestamp = dateUtil.now(), type = TherapyEvent.Type.NOTE, note = getString(info.nightscout.androidaps.core.R.string.androidaps_start).toString() + " - " + Build.MANUFACTURER + " " + Build.MODEL, glucoseUnit = TherapyEvent.GlucoseUnit.MGDL)).subscribe()
disposable += compatDBHelper.dbChangeDisposable()
registerActivityLifecycleCallbacks(activityMonitor) registerActivityLifecycleCallbacks(activityMonitor)
JodaTimeAndroid.init(this) JodaTimeAndroid.init(this)
aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME) aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME)
@ -77,10 +86,10 @@ class MainApp : DaggerApplication() {
// Register all tabs in app here // Register all tabs in app here
pluginStore.plugins = plugins pluginStore.plugins = plugins
configBuilderPlugin.initialize() configBuilder.initialize()
nsUpload.uploadAppStart() keepAliveManager.setAlarm(this)
Thread { keepAliveManager.setAlarm(this) }.start()
doMigrations() doMigrations()
uel.log(UserEntry.Action.START_AAPS, UserEntry.Sources.Aaps)
} }
private fun doMigrations() { private fun doMigrations() {

View file

@ -8,7 +8,7 @@ import android.os.Bundle
import androidx.annotation.XmlRes import androidx.annotation.XmlRes
import androidx.preference.* import androidx.preference.*
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.danaRv2.DanaRv2Plugin

View file

@ -13,7 +13,7 @@ import info.nightscout.androidaps.data.defaultProfile.DefaultProfileDPV
import info.nightscout.androidaps.databinding.ActivityProfilehelperBinding import info.nightscout.androidaps.databinding.ActivityProfilehelperBinding
import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.dialogs.ProfileViewerDialog import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
@ -24,7 +24,7 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.stats.TddCalculator import info.nightscout.androidaps.utils.stats.TddCalculator
import java.text.DecimalFormat import java.text.DecimalFormat
import javax.inject.Inject import javax.inject.Inject
@ -39,7 +39,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
@Inject lateinit var localProfilePlugin: LocalProfilePlugin @Inject lateinit var localProfilePlugin: LocalProfilePlugin
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var databaseHelper: DatabaseHelperInterface
enum class ProfileType { enum class ProfileType {
@ -98,7 +98,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
} }
// Active profile // Active profile
profileList = activePlugin.activeProfileInterface.profile?.getProfileList() ?: ArrayList() profileList = activePlugin.activeProfileSource.profile?.getProfileList() ?: ArrayList()
binding.availableProfileList.setOnClickListener { binding.availableProfileList.setOnClickListener {
PopupMenu(this, binding.availableProfileList).apply { PopupMenu(this, binding.availableProfileList).apply {
@ -114,7 +114,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
} }
// Profile switch // Profile switch
profileSwitch = databaseHelper.getProfileSwitchData(dateUtil._now() - T.months(2).msecs(), true) profileSwitch = databaseHelper.getProfileSwitchData(dateUtil.now() - T.months(2).msecs(), true)
binding.profileswitchList.setOnClickListener { binding.profileswitchList.setOnClickListener {
PopupMenu(this, binding.profileswitchList).apply { PopupMenu(this, binding.profileswitchList).apply {
@ -141,7 +141,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
profile?.let { profile?.let {
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile), Runnable { OKDialog.showConfirmation(this, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile), Runnable {
localProfilePlugin.addProfile(localProfilePlugin.copyFrom(it, "DefaultProfile " + localProfilePlugin.addProfile(localProfilePlugin.copyFrom(it, "DefaultProfile " +
dateUtil.dateAndTimeAndSecondsString(dateUtil._now()) dateUtil.dateAndTimeAndSecondsString(dateUtil.now())
.replace(".", "/") .replace(".", "/")
)) ))
rxBus.send(EventLocalProfileChanged()) rxBus.send(EventLocalProfileChanged())
@ -210,7 +210,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
getProfile(ageUsed[1], tddUsed[1], weightUsed[1], pctUsed[1] / 100.0, 1)?.let { profile1 -> getProfile(ageUsed[1], tddUsed[1], weightUsed[1], pctUsed[1] / 100.0, 1)?.let { profile1 ->
ProfileViewerDialog().also { pvd -> ProfileViewerDialog().also { pvd ->
pvd.arguments = Bundle().also { pvd.arguments = Bundle().also {
it.putLong("time", DateUtil.now()) it.putLong("time", dateUtil.now())
it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal) it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal)
it.putString("customProfile", profile0.data.toString()) it.putString("customProfile", profile0.data.toString())
it.putString("customProfile2", profile1.data.toString()) it.putString("customProfile2", profile1.data.toString())
@ -233,7 +233,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits()) ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits()) ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits())
ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile() ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile()
ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString()) ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileSource.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString())
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile() ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile()
} }
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -2,7 +2,8 @@ package info.nightscout.androidaps.activities
import android.os.Bundle import android.os.Bundle
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.ActivityStatsBinding import info.nightscout.androidaps.databinding.ActivityStatsBinding
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.utils.ActivityMonitor import info.nightscout.androidaps.utils.ActivityMonitor
@ -32,7 +33,7 @@ class StatsActivity : NoSplashAppCompatActivity() {
binding.ok.setOnClickListener { finish() } binding.ok.setOnClickListener { finish() }
binding.reset.setOnClickListener { binding.reset.setOnClickListener {
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.doyouwantresetstats)) { OKDialog.showConfirmation(this, resourceHelper.gs(R.string.doyouwantresetstats)) {
uel.log(Action.STAT_RESET) uel.log(Action.STAT_RESET, Sources.Stats)
activityMonitor.reset() activityMonitor.reset()
recreate() recreate()
} }

View file

@ -8,7 +8,7 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
import info.nightscout.androidaps.databinding.ActivitySurveyBinding import info.nightscout.androidaps.databinding.ActivitySurveyBinding
import info.nightscout.androidaps.dialogs.ProfileViewerDialog import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -24,12 +24,13 @@ import javax.inject.Inject
class SurveyActivity : NoSplashAppCompatActivity() { class SurveyActivity : NoSplashAppCompatActivity() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var tddCalculator: TddCalculator @Inject lateinit var tddCalculator: TddCalculator
@Inject lateinit var tirCalculator: TirCalculator @Inject lateinit var tirCalculator: TirCalculator
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activityMonitor: ActivityMonitor @Inject lateinit var activityMonitor: ActivityMonitor
@Inject lateinit var defaultProfile: DefaultProfile @Inject lateinit var defaultProfile: DefaultProfile
@Inject lateinit var dateUtil: DateUtil
private lateinit var binding: ActivitySurveyBinding private lateinit var binding: ActivitySurveyBinding
@ -40,7 +41,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
binding.id.text = InstanceId.instanceId() binding.id.text = InstanceId.instanceId()
val profileStore = activePlugin.activeProfileInterface.profile val profileStore = activePlugin.activeProfileSource.profile
val profileList = profileStore?.getProfileList() ?: return val profileList = profileStore?.getProfileList() ?: return
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList) binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
@ -68,7 +69,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())?.let { profile -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())?.let { profile ->
ProfileViewerDialog().also { pvd -> ProfileViewerDialog().also { pvd ->
pvd.arguments = Bundle().also { pvd.arguments = Bundle().also {
it.putLong("time", DateUtil.now()) it.putLong("time", dateUtil.now())
it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal) it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal)
it.putString("customProfile", runningProfile.data.toString()) it.putString("customProfile", runningProfile.data.toString())
it.putString("customProfile2", profile.data.toString()) it.putString("customProfile2", profile.data.toString())

View file

@ -1,14 +1,10 @@
package info.nightscout.androidaps.db package info.nightscout.androidaps.db
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Food import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.ExtendedBolus
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryBasal
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.events.EventFoodDatabaseChanged
import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.events.EventTempTargetChange
import info.nightscout.androidaps.events.EventTherapyEventChange
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -30,13 +26,41 @@ class CompatDBHelper @Inject constructor(
rxBus.send(EventNewBG(null)) rxBus.send(EventNewBG(null))
} }
.subscribe { .subscribe {
it.filterIsInstance<GlucoseValue>().firstOrNull()?.let { /**
aapsLogger.debug(LTag.DATABASE, "Firing EventNewHistoryData") * GlucoseValues can come in batch
rxBus.send(EventNewHistoryData(it.timestamp)) * oldest one should be used for invalidation, newest one for for triggering Loop.
} * Thus we need to collect both
it.filterIsInstance<GlucoseValue>().lastOrNull()?.let { *
*/
var newestGlucoseValue : GlucoseValue? = null
it.filterIsInstance<GlucoseValue>().lastOrNull()?.let { gv ->
aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg") aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg")
rxBus.send(EventNewBG(it)) rxBus.send(EventNewBG(gv))
newestGlucoseValue = gv
}
it.filterIsInstance<GlucoseValue>().map { gv -> gv.timestamp }.minOrNull()?.let { timestamp ->
aapsLogger.debug(LTag.DATABASE, "Firing EventNewHistoryData")
rxBus.send(EventNewHistoryData(timestamp, true, newestGlucoseValue))
}
it.filterIsInstance<Carbs>().map { t -> t.timestamp }.minOrNull()?.let { timestamp ->
aapsLogger.debug(LTag.DATABASE, "Firing EventTreatmentChange")
rxBus.send(EventTreatmentChange())
rxBus.send(EventNewHistoryData(timestamp, false))
}
it.filterIsInstance<Bolus>().map { t -> t.timestamp }.minOrNull()?.let { timestamp ->
aapsLogger.debug(LTag.DATABASE, "Firing EventTreatmentChange")
rxBus.send(EventTreatmentChange())
rxBus.send(EventNewHistoryData(timestamp, false))
}
it.filterIsInstance<TemporaryBasal>().map { t -> t.timestamp }.minOrNull()?.let { timestamp ->
aapsLogger.debug(LTag.DATABASE, "Firing EventTempBasalChange")
rxBus.send(EventTempBasalChange())
rxBus.send(EventNewHistoryData(timestamp, false))
}
it.filterIsInstance<ExtendedBolus>().map { t -> t.timestamp }.minOrNull()?.let { timestamp ->
aapsLogger.debug(LTag.DATABASE, "Firing EventExtendedBolusChange")
rxBus.send(EventExtendedBolusChange())
rxBus.send(EventNewHistoryData(timestamp, false))
} }
it.filterIsInstance<TemporaryTarget>().firstOrNull()?.let { it.filterIsInstance<TemporaryTarget>().firstOrNull()?.let {
aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange") aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange")

View file

@ -34,24 +34,20 @@ import javax.inject.Inject;
import info.nightscout.androidaps.dana.comm.RecordTypes; import info.nightscout.androidaps.dana.comm.RecordTypes;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventProfileNeedsUpdate;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.events.EventReloadProfileSwitchData; import info.nightscout.androidaps.events.EventReloadProfileSwitchData;
import info.nightscout.androidaps.events.EventReloadTempBasalData; import info.nightscout.androidaps.interfaces.ActivePlugin;
import info.nightscout.androidaps.events.EventReloadTreatmentData;
import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileSource;
import info.nightscout.androidaps.interfaces.ProfileStore; import info.nightscout.androidaps.interfaces.ProfileStore;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader; import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.PercentageSplitter; import info.nightscout.androidaps.utils.PercentageSplitter;
/** /**
@ -67,25 +63,18 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
@Inject RxBusWrapper rxBus; @Inject RxBusWrapper rxBus;
@Inject VirtualPumpPlugin virtualPumpPlugin; @Inject VirtualPumpPlugin virtualPumpPlugin;
@Inject OpenHumansUploader openHumansUploader; @Inject OpenHumansUploader openHumansUploader;
@Inject ActivePluginProvider activePlugin; @Inject ActivePlugin activePlugin;
@Inject NSUpload nsUpload; @Inject NSUpload nsUpload;
@Inject DateUtil dateUtil;
public static final String DATABASE_NAME = "AndroidAPSDb"; public static final String DATABASE_NAME = "AndroidAPSDb";
public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses";
public static final String DATABASE_DANARHISTORY = "DanaRHistory"; public static final String DATABASE_DANARHISTORY = "DanaRHistory";
public static final String DATABASE_DBREQUESTS = "DBRequests"; public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_TDDS = "TDDs";
private static final int DATABASE_VERSION = 13; private static final int DATABASE_VERSION = 13;
public static Long earliestDataChange = null; public static Long earliestDataChange = null;
private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledTemBasalsPost = null;
private static final ScheduledExecutorService extendedBolusWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledExtendedBolusPost = null;
private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor(); private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null; private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null;
@ -198,8 +187,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
virtualPumpPlugin.setFakingStatus(true); virtualPumpPlugin.setFakingStatus(true);
scheduleTemporaryBasalChange();
scheduleExtendedBolusChange();
scheduleProfileSwitchChange(); scheduleProfileSwitchChange();
new java.util.Timer().schedule( new java.util.Timer().schedule(
new java.util.TimerTask() { new java.util.TimerTask() {
@ -212,29 +199,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
); );
} }
public void resetTemporaryBasals() {
try {
TableUtils.dropTable(connectionSource, TemporaryBasal.class, true);
TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class);
updateEarliestDataChange(0);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
virtualPumpPlugin.setFakingStatus(false);
scheduleTemporaryBasalChange();
}
public void resetExtededBoluses() {
try {
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
updateEarliestDataChange(0);
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
scheduleExtendedBolusChange();
}
public void resetProfileSwitch() { public void resetProfileSwitch() {
try { try {
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
@ -507,7 +471,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
openHumansUploader.enqueueTemporaryBasal(old); openHumansUploader.enqueueTemporaryBasal(old);
updateEarliestDataChange(tempBasal.date); updateEarliestDataChange(tempBasal.date);
scheduleTemporaryBasalChange(); // scheduleTemporaryBasalChange();
return false; return false;
} }
@ -516,7 +480,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
openHumansUploader.enqueueTemporaryBasal(tempBasal); openHumansUploader.enqueueTemporaryBasal(tempBasal);
aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
updateEarliestDataChange(tempBasal.date); updateEarliestDataChange(tempBasal.date);
scheduleTemporaryBasalChange(); // scheduleTemporaryBasalChange();
return true; return true;
} }
if (tempBasal.source == Source.NIGHTSCOUT) { if (tempBasal.source == Source.NIGHTSCOUT) {
@ -535,7 +499,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by date from: " + Source.getString(tempBasal.source) + " " + old.toString()); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by date from: " + Source.getString(tempBasal.source) + " " + old.toString());
updateEarliestDataChange(oldDate); updateEarliestDataChange(oldDate);
updateEarliestDataChange(old.date); updateEarliestDataChange(old.date);
scheduleTemporaryBasalChange(); // scheduleTemporaryBasalChange();
return true; return true;
} }
return false; return false;
@ -558,7 +522,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by _id from: " + Source.getString(tempBasal.source) + " " + old.toString()); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by _id from: " + Source.getString(tempBasal.source) + " " + old.toString());
updateEarliestDataChange(oldDate); updateEarliestDataChange(oldDate);
updateEarliestDataChange(old.date); updateEarliestDataChange(old.date);
scheduleTemporaryBasalChange(); // scheduleTemporaryBasalChange();
return true; return true;
} }
} }
@ -567,7 +531,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
openHumansUploader.enqueueTemporaryBasal(tempBasal); openHumansUploader.enqueueTemporaryBasal(tempBasal);
aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
updateEarliestDataChange(tempBasal.date); updateEarliestDataChange(tempBasal.date);
scheduleTemporaryBasalChange(); // scheduleTemporaryBasalChange();
return true; return true;
} }
if (tempBasal.source == Source.USER) { if (tempBasal.source == Source.USER) {
@ -575,7 +539,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
openHumansUploader.enqueueTemporaryBasal(tempBasal); openHumansUploader.enqueueTemporaryBasal(tempBasal);
aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
updateEarliestDataChange(tempBasal.date); updateEarliestDataChange(tempBasal.date);
scheduleTemporaryBasalChange(); // scheduleTemporaryBasalChange();
return true; return true;
} }
} catch (SQLException e) { } catch (SQLException e) {
@ -592,16 +556,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) { } catch (SQLException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
scheduleTemporaryBasalChange(); // scheduleTemporaryBasalChange();
}
public List<TemporaryBasal> getAllTemporaryBasals() {
try {
return getDaoTemporaryBasal().queryForAll();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return Collections.emptyList();
} }
public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long mills, boolean ascending) { public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long mills, boolean ascending) {
@ -620,44 +575,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<TemporaryBasal>(); return new ArrayList<TemporaryBasal>();
} }
public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long from, long to, boolean ascending) {
try {
List<TemporaryBasal> tempbasals;
QueryBuilder<TemporaryBasal, Long> queryBuilder = getDaoTemporaryBasal().queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
where.between("date", from, to);
PreparedQuery<TemporaryBasal> preparedQuery = queryBuilder.prepare();
tempbasals = getDaoTemporaryBasal().query(preparedQuery);
return tempbasals;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<TemporaryBasal>();
}
private void scheduleTemporaryBasalChange() {
class PostRunnable implements Runnable {
public void run() {
aapsLogger.debug(LTag.DATABASE, "Firing EventTempBasalChange");
rxBus.send(new EventReloadTempBasalData());
rxBus.send(new EventTempBasalChange());
if (earliestDataChange != null)
rxBus.send(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null;
scheduledTemBasalsPost = null;
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (scheduledTemBasalsPost != null)
scheduledTemBasalsPost.cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
scheduledTemBasalsPost = tempBasalsWorker.schedule(task, sec, TimeUnit.SECONDS);
}
/* /*
{ {
"_id": "59232e1ddd032d04218dab00", "_id": "59232e1ddd032d04218dab00",
@ -674,93 +591,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
*/ */
public void createTempBasalFromJsonIfNotExists(JSONObject trJson) {
try {
if (trJson.has("originalExtendedAmount")) { // extended bolus uploaded as temp basal
ExtendedBolus extendedBolus = new ExtendedBolus(StaticInjector.Companion.getInstance())
.source(Source.NIGHTSCOUT)
.date(trJson.getLong("mills"))
.pumpId(trJson.has("pumpId") ? trJson.getLong("pumpId") : 0)
.durationInMinutes(trJson.getInt("duration"))
.insulin(trJson.getDouble("originalExtendedAmount"))
._id(trJson.getString("_id"));
// if faking found in NS, adapt AAPS to use it too
if (!virtualPumpPlugin.getFakingStatus()) {
virtualPumpPlugin.setFakingStatus(true);
updateEarliestDataChange(0);
scheduleTemporaryBasalChange();
}
createOrUpdate(extendedBolus);
} else if (trJson.has("isFakedTempBasal")) { // extended bolus end uploaded as temp basal end
ExtendedBolus extendedBolus = new ExtendedBolus(StaticInjector.Companion.getInstance());
extendedBolus.source = Source.NIGHTSCOUT;
extendedBolus.date = trJson.getLong("mills");
extendedBolus.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0;
extendedBolus.durationInMinutes = 0;
extendedBolus.insulin = 0;
extendedBolus._id = trJson.getString("_id");
// if faking found in NS, adapt AAPS to use it too
if (!virtualPumpPlugin.getFakingStatus()) {
virtualPumpPlugin.setFakingStatus(true);
updateEarliestDataChange(0);
scheduleTemporaryBasalChange();
}
createOrUpdate(extendedBolus);
} else {
TemporaryBasal tempBasal = new TemporaryBasal(StaticInjector.Companion.getInstance())
.date(trJson.getLong("mills"))
.source(Source.NIGHTSCOUT)
.pumpId(trJson.has("pumpId") ? trJson.getLong("pumpId") : 0);
if (trJson.has("duration")) {
tempBasal.durationInMinutes = trJson.getInt("duration");
}
if (trJson.has("percent")) {
tempBasal.percentRate = trJson.getInt("percent") + 100;
tempBasal.isAbsolute = false;
}
if (trJson.has("absolute")) {
tempBasal.absoluteRate = trJson.getDouble("absolute");
tempBasal.isAbsolute = true;
}
tempBasal._id = trJson.getString("_id");
createOrUpdate(tempBasal);
}
} catch (JSONException e) {
aapsLogger.error("Unhandled exception: " + trJson.toString(), e);
}
}
public void deleteTempBasalById(String _id) {
TemporaryBasal stored = findTempBasalById(_id);
if (stored != null) {
aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Removing TempBasal record from database: " + stored.toString());
delete(stored);
updateEarliestDataChange(stored.date);
scheduleTemporaryBasalChange();
}
}
public TemporaryBasal findTempBasalById(String _id) {
try {
QueryBuilder<TemporaryBasal, Long> queryBuilder = null;
queryBuilder = getDaoTemporaryBasal().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", _id);
PreparedQuery<TemporaryBasal> preparedQuery = queryBuilder.prepare();
List<TemporaryBasal> list = getDaoTemporaryBasal().query(preparedQuery);
if (list.size() != 1) {
return null;
} else {
return list.get(0);
}
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return null;
}
public TemporaryBasal findTempBasalByPumpId(Long pumpId) { public TemporaryBasal findTempBasalByPumpId(Long pumpId) {
try { try {
QueryBuilder<TemporaryBasal, Long> queryBuilder = null; QueryBuilder<TemporaryBasal, Long> queryBuilder = null;
@ -785,109 +615,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// ------------ ExtendedBolus handling --------------- // ------------ ExtendedBolus handling ---------------
public boolean createOrUpdate(ExtendedBolus extendedBolus) {
try {
aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: createOrUpdate: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
ExtendedBolus old;
extendedBolus.date = roundDateToSec(extendedBolus.date);
if (extendedBolus.source == Source.PUMP) {
// if pumpId == 0 do not check for existing pumpId
// used with pumps without history
// and insight where record as added first without pumpId
// and then is record updated with pumpId
if (extendedBolus.pumpId == 0) {
getDaoExtendedBolus().createOrUpdate(extendedBolus);
openHumansUploader.enqueueExtendedBolus(extendedBolus);
} else {
QueryBuilder<ExtendedBolus, Long> queryBuilder = getDaoExtendedBolus().queryBuilder();
Where where = queryBuilder.where();
where.eq("pumpId", extendedBolus.pumpId);
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
List<ExtendedBolus> trList = getDaoExtendedBolus().query(preparedQuery);
if (trList.size() > 1) {
aapsLogger.error("EXTENDEDBOLUS: Multiple records found for pumpId: " + extendedBolus.pumpId);
return false;
}
getDaoExtendedBolus().createOrUpdate(extendedBolus);
openHumansUploader.enqueueExtendedBolus(extendedBolus);
}
aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
updateEarliestDataChange(extendedBolus.date);
scheduleExtendedBolusChange();
return true;
}
if (extendedBolus.source == Source.NIGHTSCOUT) {
old = getDaoExtendedBolus().queryForId(extendedBolus.date);
if (old != null) {
if (!old.isEqual(extendedBolus)) {
long oldDate = old.date;
getDaoExtendedBolus().delete(old); // need to delete/create because date may change too
old.copyFrom(extendedBolus);
getDaoExtendedBolus().create(old);
aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: Updating record by date from: " + Source.getString(extendedBolus.source) + " " + old.log());
openHumansUploader.enqueueExtendedBolus(old);
updateEarliestDataChange(oldDate);
updateEarliestDataChange(old.date);
scheduleExtendedBolusChange();
return true;
}
return false;
}
// find by NS _id
if (extendedBolus._id != null) {
QueryBuilder<ExtendedBolus, Long> queryBuilder = getDaoExtendedBolus().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", extendedBolus._id);
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
List<ExtendedBolus> trList = getDaoExtendedBolus().query(preparedQuery);
if (trList.size() > 0) {
old = trList.get(0);
if (!old.isEqual(extendedBolus)) {
long oldDate = old.date;
getDaoExtendedBolus().delete(old); // need to delete/create because date may change too
old.copyFrom(extendedBolus);
getDaoExtendedBolus().create(old);
aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: Updating record by _id from: " + Source.getString(extendedBolus.source) + " " + old.log());
openHumansUploader.enqueueExtendedBolus(old);
updateEarliestDataChange(oldDate);
updateEarliestDataChange(old.date);
scheduleExtendedBolusChange();
return true;
}
}
}
getDaoExtendedBolus().create(extendedBolus);
aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
openHumansUploader.enqueueExtendedBolus(extendedBolus);
updateEarliestDataChange(extendedBolus.date);
scheduleExtendedBolusChange();
return true;
}
if (extendedBolus.source == Source.USER) {
getDaoExtendedBolus().create(extendedBolus);
aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.log());
openHumansUploader.enqueueExtendedBolus(extendedBolus);
updateEarliestDataChange(extendedBolus.date);
scheduleExtendedBolusChange();
return true;
}
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return false;
}
public List<ExtendedBolus> getAllExtendedBoluses() {
try {
return getDaoExtendedBolus().queryForAll();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return Collections.emptyList();
}
public ExtendedBolus getExtendedBolusByPumpId(long pumpId) { public ExtendedBolus getExtendedBolusByPumpId(long pumpId) {
try { try {
return getDaoExtendedBolus().queryBuilder() return getDaoExtendedBolus().queryBuilder()
@ -907,69 +634,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) { } catch (SQLException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
scheduleExtendedBolusChange(); // scheduleExtendedBolusChange();
}
public List<ExtendedBolus> getExtendedBolusDataFromTime(long mills, boolean ascending) {
try {
List<ExtendedBolus> extendedBoluses;
QueryBuilder<ExtendedBolus, Long> queryBuilder = getDaoExtendedBolus().queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
where.ge("date", mills);
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
extendedBoluses = getDaoExtendedBolus().query(preparedQuery);
return extendedBoluses;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<ExtendedBolus>();
}
public List<ExtendedBolus> getExtendedBolusDataFromTime(long from, long to, boolean ascending) {
try {
List<ExtendedBolus> extendedBoluses;
QueryBuilder<ExtendedBolus, Long> queryBuilder = getDaoExtendedBolus().queryBuilder();
queryBuilder.orderBy("date", ascending);
Where where = queryBuilder.where();
where.between("date", from, to);
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
extendedBoluses = getDaoExtendedBolus().query(preparedQuery);
return extendedBoluses;
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return new ArrayList<ExtendedBolus>();
}
public void deleteExtendedBolusById(String _id) {
ExtendedBolus stored = findExtendedBolusById(_id);
if (stored != null) {
aapsLogger.debug(LTag.DATABASE, "EXTENDEDBOLUS: Removing ExtendedBolus record from database: " + stored.toString());
delete(stored);
updateEarliestDataChange(stored.date);
scheduleExtendedBolusChange();
}
}
public ExtendedBolus findExtendedBolusById(String _id) {
try {
QueryBuilder<ExtendedBolus, Long> queryBuilder = null;
queryBuilder = getDaoExtendedBolus().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", _id);
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
List<ExtendedBolus> list = getDaoExtendedBolus().query(preparedQuery);
if (list.size() == 1) {
return list.get(0);
} else {
return null;
}
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return null;
} }
/* /*
@ -989,33 +654,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
*/ */
public void createExtendedBolusFromJsonIfNotExists(JSONObject json) {
ExtendedBolus extendedBolus = ExtendedBolus.createFromJson(StaticInjector.Companion.getInstance(), json);
if (extendedBolus != null)
createOrUpdate(extendedBolus);
}
private void scheduleExtendedBolusChange() {
class PostRunnable implements Runnable {
public void run() {
aapsLogger.debug(LTag.DATABASE, "Firing EventExtendedBolusChange");
rxBus.send(new EventReloadTreatmentData(new EventExtendedBolusChange()));
if (earliestDataChange != null)
rxBus.send(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null;
scheduledExtendedBolusPost = null;
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (scheduledExtendedBolusPost != null)
scheduledExtendedBolusPost.cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
scheduledExtendedBolusPost = extendedBolusWorker.schedule(task, sec, TimeUnit.SECONDS);
}
// ---------------- ProfileSwitch handling --------------- // ---------------- ProfileSwitch handling ---------------
public List<ProfileSwitch> getProfileSwitchData(long from, boolean ascending) { public List<ProfileSwitch> getProfileSwitchData(long from, boolean ascending) {
@ -1157,7 +795,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
} }
// look for already added percentage from NS // look for already added percentage from NS
profileSwitch.profileName = PercentageSplitter.pureName(profileSwitch.profileName); profileSwitch.profileName = PercentageSplitter.INSTANCE.pureName(profileSwitch.profileName);
getDaoProfileSwitch().create(profileSwitch); getDaoProfileSwitch().create(profileSwitch);
aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString()); aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString());
openHumansUploader.enqueueProfileSwitch(profileSwitch); openHumansUploader.enqueueProfileSwitch(profileSwitch);
@ -1235,15 +873,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (trJson.has("profileJson")) if (trJson.has("profileJson"))
profileSwitch.profileJson = trJson.getString("profileJson"); profileSwitch.profileJson = trJson.getString("profileJson");
else { else {
ProfileInterface profileInterface = activePlugin.getActiveProfileInterface(); ProfileSource profileSource = activePlugin.getActiveProfileSource();
ProfileStore store = profileInterface.getProfile(); ProfileStore store = profileSource.getProfile();
if (store != null) { if (store != null) {
Profile profile = store.getSpecificProfile(profileSwitch.profileName); Profile profile = store.getSpecificProfile(profileSwitch.profileName);
if (profile != null) { if (profile != null) {
profileSwitch.profileJson = profile.getData().toString(); profileSwitch.profileJson = profile.getData().toString();
aapsLogger.debug(LTag.DATABASE, "Profile switch prefilled with JSON from local store"); aapsLogger.debug(LTag.DATABASE, "Profile switch prefilled with JSON from local store");
// Update data in NS // Update data in NS
nsUpload.updateProfileSwitch(profileSwitch); nsUpload.updateProfileSwitch(profileSwitch, dateUtil);
} else { } else {
aapsLogger.debug(LTag.DATABASE, "JSON for profile switch doesn't exist. Ignoring: " + trJson.toString()); aapsLogger.debug(LTag.DATABASE, "JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
return; return;

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.db; package info.nightscout.androidaps.db;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.j256.ormlite.dao.CloseableIterator; import com.j256.ormlite.dao.CloseableIterator;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject; import org.json.JSONObject;
import java.sql.SQLException; import java.sql.SQLException;
@ -16,6 +16,7 @@ import javax.inject.Singleton;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
@Deprecated
@Singleton @Singleton
public class DatabaseHelperProvider implements DatabaseHelperInterface { public class DatabaseHelperProvider implements DatabaseHelperInterface {
@ -78,10 +79,11 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().createOrUpdate(tempBasal); return MainApp.Companion.getDbHelper().createOrUpdate(tempBasal);
} }
@NonNull @Override public TemporaryBasal findTempBasalByPumpId(long id) { @Nullable @Override public TemporaryBasal findTempBasalByPumpId(long id) {
return MainApp.Companion.getDbHelper().findTempBasalByPumpId(id); return MainApp.Companion.getDbHelper().findTempBasalByPumpId(id);
} }
@Deprecated
@NonNull @Override public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long mills, boolean ascending) { @NonNull @Override public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long mills, boolean ascending) {
return MainApp.Companion.getDbHelper().getTemporaryBasalsDataFromTime(mills, ascending); return MainApp.Companion.getDbHelper().getTemporaryBasalsDataFromTime(mills, ascending);
} }
@ -134,42 +136,14 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().getPumpStoppedEvent(pumpSerial, before); return MainApp.Companion.getDbHelper().getPumpStoppedEvent(pumpSerial, before);
} }
@Override public boolean createOrUpdate(@NonNull ExtendedBolus extendedBolus) {
return MainApp.Companion.getDbHelper().createOrUpdate(extendedBolus);
}
@Override public void createOrUpdate(@NonNull ProfileSwitch profileSwitch) { @Override public void createOrUpdate(@NonNull ProfileSwitch profileSwitch) {
MainApp.Companion.getDbHelper().createOrUpdate(profileSwitch); MainApp.Companion.getDbHelper().createOrUpdate(profileSwitch);
} }
@Override public void delete(@NonNull TemporaryBasal tempBasal) {
MainApp.Companion.getDbHelper().delete(tempBasal);
}
@NonNull @Override public List<ExtendedBolus> getExtendedBolusDataFromTime(long mills, boolean ascending) {
return MainApp.Companion.getDbHelper().getExtendedBolusDataFromTime(mills, ascending);
}
@Override public void deleteTempBasalById(@NonNull String _id) {
MainApp.Companion.getDbHelper().deleteTempBasalById(_id);
}
@Override public void deleteExtendedBolusById(@NonNull String _id) {
MainApp.Companion.getDbHelper().deleteExtendedBolusById(_id);
}
@Override public void deleteProfileSwitchById(@NonNull String _id) { @Override public void deleteProfileSwitchById(@NonNull String _id) {
MainApp.Companion.getDbHelper().deleteProfileSwitchById(_id); MainApp.Companion.getDbHelper().deleteProfileSwitchById(_id);
} }
@Override public void createTempBasalFromJsonIfNotExists(@NonNull JSONObject json) {
MainApp.Companion.getDbHelper().createTempBasalFromJsonIfNotExists(json);
}
@Override public void createExtendedBolusFromJsonIfNotExists(@NonNull JSONObject json) {
MainApp.Companion.getDbHelper().createExtendedBolusFromJsonIfNotExists(json);
}
@Override public void createProfileSwitchFromJsonIfNotExists(@NonNull JSONObject trJson) { @Override public void createProfileSwitchFromJsonIfNotExists(@NonNull JSONObject trJson) {
MainApp.Companion.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson); MainApp.Companion.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson);
} }
@ -194,10 +168,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().getProfileSwitchEventsFromTime(mills, ascending); return MainApp.Companion.getDbHelper().getProfileSwitchEventsFromTime(mills, ascending);
} }
@NonNull @Override public List<ExtendedBolus> getAllExtendedBoluses() {
return MainApp.Companion.getDbHelper().getAllExtendedBoluses();
}
@NonNull @Override public List<ProfileSwitch> getAllProfileSwitches() { @NonNull @Override public List<ProfileSwitch> getAllProfileSwitches() {
return MainApp.Companion.getDbHelper().getAllProfileSwitches(); return MainApp.Companion.getDbHelper().getAllProfileSwitches();
} }
@ -206,10 +176,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface {
return MainApp.Companion.getDbHelper().getAllTDDs(); return MainApp.Companion.getDbHelper().getAllTDDs();
} }
@NonNull @Override public List<TemporaryBasal> getAllTemporaryBasals() {
return MainApp.Companion.getDbHelper().getAllTemporaryBasals();
}
@NonNull @Override public List<OHQueueItem> getAllOHQueueItems(long maxEntries) { @NonNull @Override public List<OHQueueItem> getAllOHQueueItems(long maxEntries) {
return MainApp.Companion.getDbHelper().getAllOHQueueItems(maxEntries); return MainApp.Companion.getDbHelper().getAllOHQueueItems(maxEntries);
} }

View file

@ -6,7 +6,7 @@ import dagger.Lazy
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.db.DatabaseHelperProvider import info.nightscout.androidaps.db.DatabaseHelperProvider
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
@ -15,36 +15,40 @@ import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.PluginStore import info.nightscout.androidaps.plugins.configBuilder.PluginStore
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefsImpl
import info.nightscout.androidaps.plugins.general.nsclient.DataSyncSelectorImplementation
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.pump.PumpSyncImplementation
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.CommandQueue import info.nightscout.androidaps.queue.CommandQueue
import info.nightscout.androidaps.utils.androidNotification.NotificationHolder import info.nightscout.androidaps.utils.androidNotification.NotificationHolderImpl
import info.nightscout.androidaps.utils.resources.IconsProvider import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.utils.resources.IconsProviderImplementation
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.rx.DefaultAapsSchedulers import info.nightscout.androidaps.utils.rx.DefaultAapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.storage.FileStorage import info.nightscout.androidaps.utils.storage.FileStorage
import info.nightscout.androidaps.utils.storage.Storage import info.nightscout.androidaps.utils.storage.Storage
import javax.inject.Singleton import javax.inject.Singleton
@Suppress("unused")
@Module(includes = [ @Module(includes = [
AppModule.AppBindings::class AppModule.AppBindings::class
]) ])
open class AppModule { open class AppModule {
@Provides @Provides
fun providesPlugins(configInterface: ConfigInterface, fun providesPlugins(config: Config,
@PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>, @PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>,
@PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>, @PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
@PluginsModule.NotNSClient notNsClient: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>, @PluginsModule.NotNSClient notNsClient: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
@PluginsModule.APS aps: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>) @PluginsModule.APS aps: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>)
: List<@JvmSuppressWildcards PluginBase> { : List<@JvmSuppressWildcards PluginBase> {
val plugins = allConfigs.toMutableMap() val plugins = allConfigs.toMutableMap()
if (configInterface.PUMPDRIVERS) plugins += pumpDrivers.get() if (config.PUMPDRIVERS) plugins += pumpDrivers.get()
if (configInterface.APS) plugins += aps.get() if (config.APS) plugins += aps.get()
if (!configInterface.NSCLIENT) plugins += notNsClient.get() if (!config.NSCLIENT) plugins += notNsClient.get()
return plugins.toList().sortedBy { it.first }.map { it.second } return plugins.toList().sortedBy { it.first }.map { it.second }
} }
@ -72,19 +76,22 @@ open class AppModule {
interface AppBindings { interface AppBindings {
@Binds fun bindContext(mainApp: MainApp): Context @Binds fun bindContext(mainApp: MainApp): Context
@Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector @Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector
@Binds fun bindActivePluginProvider(pluginStore: PluginStore): ActivePluginProvider @Binds fun bindActivePluginProvider(pluginStore: PluginStore): ActivePlugin
@Binds fun bindCommandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider @Binds fun bindCommandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider
@Binds fun bindConfigInterface(config: Config): ConfigInterface @Binds fun bindConfigInterface(config: ConfigImpl): Config
@Binds fun bindConfigBuilderInterface(configBuilderPlugin: ConfigBuilderPlugin): ConfigBuilderInterface @Binds fun bindConfigBuilderInterface(configBuilderPlugin: ConfigBuilderPlugin): ConfigBuilder
@Binds fun bindTreatmentInterface(treatmentsPlugin: TreatmentsPlugin): TreatmentsInterface @Binds fun bindTreatmentsInterface(treatmentsPlugin: TreatmentsPlugin): TreatmentsInterface
@Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface @Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface
@Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolder): NotificationHolderInterface @Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolderImpl): NotificationHolder
@Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefs): ImportExportPrefsInterface @Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefsImpl): ImportExportPrefs
@Binds fun bindIconsProviderInterface(iconsProvider: IconsProvider): IconsProviderInterface @Binds fun bindIconsProviderInterface(iconsProvider: IconsProviderImplementation): IconsProvider
@Binds fun bindLoopInterface(loopPlugin: LoopPlugin): LoopInterface @Binds fun bindLoopInterface(loopPlugin: LoopPlugin): LoopInterface
@Binds fun bindIobCobCalculatorInterface(iobCobCalculatorPlugin: IobCobCalculatorPlugin): IobCobCalculatorInterface @Binds fun bindIobCobCalculatorInterface(iobCobCalculatorPlugin: IobCobCalculatorPlugin): IobCobCalculator
@Binds fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicatorInterface @Binds fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicator
@Binds fun bindUploadQueueAdminInterfaceToUploadQueue(uploadQueueAdminInterface: UploadQueueAdminInterface) : UploadQueueInterface @Binds fun bindUploadQueueAdminInterfaceToUploadQueue(uploadQueueAdminInterface: UploadQueueAdminInterface) : UploadQueueInterface
@Binds fun bindDataSyncSelector(dataSyncSelectorImplementation: DataSyncSelectorImplementation): DataSyncSelector
@Binds fun bindPumpSync(pumpSyncImplementation: PumpSyncImplementation): PumpSync
} }
} }

View file

@ -14,7 +14,7 @@ abstract class DataClassesModule {
@ContributesAndroidInjector abstract fun glucoseStatusInjector(): GlucoseStatus @ContributesAndroidInjector abstract fun glucoseStatusInjector(): GlucoseStatus
@ContributesAndroidInjector abstract fun DatabaseHelperInjector(): DatabaseHelper @ContributesAndroidInjector abstract fun databaseHelperInjector(): DatabaseHelper
@ContributesAndroidInjector abstract fun treatmentServiceInjector(): TreatmentService @ContributesAndroidInjector abstract fun treatmentServiceInjector(): TreatmentService
@ContributesAndroidInjector abstract fun bolusWizardInjector(): BolusWizard @ContributesAndroidInjector abstract fun bolusWizardInjector(): BolusWizard

View file

@ -66,7 +66,7 @@ abstract class FragmentsModule {
@ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment @ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment @ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusFragment @ContributesAndroidInjector abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusCarbsFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment @ContributesAndroidInjector abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment @ContributesAndroidInjector abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment
@ContributesAndroidInjector abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment @ContributesAndroidInjector abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment

View file

@ -3,6 +3,8 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.TherapyEventDataPoint
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
@Module @Module

View file

@ -17,6 +17,7 @@ abstract class ReceiversModule {
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver @ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver @ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver @ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver
@ContributesAndroidInjector abstract fun contributesKeepAliveWorker(): KeepAliveReceiver.KeepAliveWorker
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver @ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver @ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver @ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver

View file

@ -3,9 +3,11 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.general.food.FoodPlugin import info.nightscout.androidaps.plugins.general.food.FoodPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddAckWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientUpdateRemoveAckWorker
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
import info.nightscout.androidaps.plugins.source.* import info.nightscout.androidaps.plugins.source.*
@ -25,6 +27,8 @@ abstract class WorkersModule {
@ContributesAndroidInjector abstract fun contributesNSProfileWorker(): NSProfilePlugin.NSProfileWorker @ContributesAndroidInjector abstract fun contributesNSProfileWorker(): NSProfilePlugin.NSProfileWorker
@ContributesAndroidInjector abstract fun contributesSmsCommunicatorWorker(): SmsCommunicatorPlugin.SmsCommunicatorWorker @ContributesAndroidInjector abstract fun contributesSmsCommunicatorWorker(): SmsCommunicatorPlugin.SmsCommunicatorWorker
@ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientAddUpdateWorker @ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientAddUpdateWorker
@ContributesAndroidInjector abstract fun contributesNSClientAddAckWorker(): NSClientAddAckWorker
@ContributesAndroidInjector abstract fun contributesNSClientUpdateRemoveAckWorker(): NSClientUpdateRemoveAckWorker
@ContributesAndroidInjector abstract fun contributesNSClientRemoveWorker(): NSClientRemoveWorker @ContributesAndroidInjector abstract fun contributesNSClientRemoveWorker(): NSClientRemoveWorker
@ContributesAndroidInjector abstract fun contributesNSClientMbgWorker(): NSClientMbgWorker @ContributesAndroidInjector abstract fun contributesNSClientMbgWorker(): NSClientMbgWorker
@ContributesAndroidInjector abstract fun contributesFoodWorker(): FoodPlugin.FoodWorker @ContributesAndroidInjector abstract fun contributesFoodWorker(): FoodPlugin.FoodWorker

View file

@ -9,7 +9,9 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogCalibrationBinding import info.nightscout.androidaps.databinding.DialogCalibrationBinding
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -79,7 +81,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
if (bg > 0) { if (bg > 0) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log(Action.CALIBRATION, ValueWithUnit(bg, units)) uel.log(Action.CALIBRATION, Sources.CalibrationDialog, ValueWithUnit.fromGlucoseUnit(bg, units))
xdripCalibrations.sendIntent(bg) xdripCalibrations.sendIntent(bg)
}) })
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@ -8,27 +9,29 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogCarbsBinding import info.nightscout.androidaps.databinding.DialogCarbsBinding
import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.CommandQueue
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
@ -40,17 +43,16 @@ import kotlin.math.max
class CarbsDialog : DialogFragmentWithDate() { class CarbsDialog : DialogFragmentWithDate() {
@Inject lateinit var mainApp: MainApp @Inject lateinit var ctx: Context
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var carbsGenerator: CarbsGenerator
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var carbTimer: CarbTimer @Inject lateinit var carbTimer: CarbTimer
@Inject lateinit var commandQueue: CommandQueue
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
companion object { companion object {
@ -76,15 +78,15 @@ class CarbsDialog : DialogFragmentWithDate() {
val time = binding.time.value.toInt() val time = binding.time.value.toInt()
if (time > 12 * 60 || time < -12 * 60) { if (time > 12 * 60 || time < -12 * 60) {
binding.time.value = 0.0 binding.time.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.constraintapllied))
} }
if (binding.duration.value > 10) { if (binding.duration.value > 10) {
binding.duration.value = 0.0 binding.duration.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.constraintapllied))
} }
if (binding.carbs.value.toInt() > maxCarbs) { if (binding.carbs.value.toInt() > maxCarbs) {
binding.carbs.value = 0.0 binding.carbs.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.carbsconstraintapplied))
} }
} }
@ -142,7 +144,7 @@ class CarbsDialog : DialogFragmentWithDate() {
validateInputs() validateInputs()
} }
iobCobCalculatorPlugin.actualBg()?.let { bgReading -> iobCobCalculator.ads.actualBg()?.let { bgReading ->
if (bgReading.value < 72) if (bgReading.value < 72)
binding.hypoTt.isChecked = true binding.hypoTt.isChecked = true
} }
@ -222,7 +224,10 @@ class CarbsDialog : DialogFragmentWithDate() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
when { when {
activitySelected -> { activitySelected -> {
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.ACTIVITY.text, Units.TherapyEvent), ValueWithUnit(activityTT, units) , ValueWithUnit(activityTTDuration, Units.M)) uel.log(Action.TT, Sources.CarbDialog,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.ACTIVITY),
ValueWithUnit.fromGlucoseUnit(activityTT, units),
ValueWithUnit.Minute(activityTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(activityTTDuration.toLong()), duration = TimeUnit.MINUTES.toMillis(activityTTDuration.toLong()),
@ -230,15 +235,18 @@ class CarbsDialog : DialogFragmentWithDate() {
lowTarget = Profile.toMgdl(activityTT, profileFunction.getUnits()), lowTarget = Profile.toMgdl(activityTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(activityTT, profileFunction.getUnits()) highTarget = Profile.toMgdl(activityTT, profileFunction.getUnits())
)).subscribe({ result -> )).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { nsUpload.updateTempTarget(it) } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
} }
eatingSoonSelected -> { eatingSoonSelected -> {
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(eatingSoonTT, units) , ValueWithUnit(eatingSoonTTDuration, Units.M)) uel.log(Action.TT, Sources.CarbDialog,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON),
ValueWithUnit.fromGlucoseUnit(eatingSoonTT, units),
ValueWithUnit.Minute(eatingSoonTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()), duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
@ -246,15 +254,18 @@ class CarbsDialog : DialogFragmentWithDate() {
lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()), lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()) highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())
)).subscribe({ result -> )).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { nsUpload.updateTempTarget(it) } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
} }
hypoSelected -> { hypoSelected -> {
uel.log(Action.TT, ValueWithUnit(TemporaryTarget.Reason.HYPOGLYCEMIA.text, Units.TherapyEvent), ValueWithUnit(hypoTT, units) , ValueWithUnit(hypoTTDuration, Units.M)) uel.log(Action.TT, Sources.CarbDialog,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.HYPOGLYCEMIA),
ValueWithUnit.fromGlucoseUnit(hypoTT, units),
ValueWithUnit.Minute(hypoTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(hypoTTDuration.toLong()), duration = TimeUnit.MINUTES.toMillis(hypoTTDuration.toLong()),
@ -262,24 +273,37 @@ class CarbsDialog : DialogFragmentWithDate() {
lowTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits()), lowTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits()) highTarget = Profile.toMgdl(hypoTT, profileFunction.getUnits())
)).subscribe({ result -> )).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { nsUpload.updateTempTarget(it) } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
} }
} }
if (carbsAfterConstraints > 0) { if (carbsAfterConstraints > 0) {
if (duration == 0) { val detailedBolusInfo = DetailedBolusInfo()
carbsGenerator.createCarb(carbsAfterConstraints, time, TherapyEvent.Type.CARBS_CORRECTION.text, notes) detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
} else { detailedBolusInfo.carbs = carbsAfterConstraints.toDouble()
carbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes) detailedBolusInfo.context = context
nsUpload.uploadEvent(TherapyEvent.Type.NOTE.text, DateUtil.now() - 2000, resourceHelper.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset)) detailedBolusInfo.notes = notes
} detailedBolusInfo.carbsDuration = T.hours(duration.toLong()).msecs()
uel.log(Action.CARBS, notes, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(carbsAfterConstraints, Units.G), ValueWithUnit(timeOffset, Units.M, timeOffset != 0), ValueWithUnit(duration, Units.H, duration != 0)) detailedBolusInfo.carbsTimestamp = time
uel.log(if (duration == 0) Action.CARBS else Action.EXTENDED_CARBS, Sources.CarbDialog,
notes,
ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged },
ValueWithUnit.Gram(carbsAfterConstraints),
ValueWithUnit.Minute(timeOffset).takeIf { timeOffset != 0 },
ValueWithUnit.Hour(duration).takeIf { duration != 0 })
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), R.raw.boluserror)
}
}
})
} }
if (useAlarm && carbs > 0 && timeOffset > 0) { if (useAlarm && carbs > 0 && timeOffset > 0) {
carbTimer.scheduleReminder(dateUtil._now() + T.mins(timeOffset.toLong()).msecs()) carbTimer.scheduleReminder(dateUtil.now() + T.mins(timeOffset.toLong()).msecs())
} }
}, null) }, null)
} }

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@ -10,24 +11,24 @@ import androidx.annotation.StringRes
import com.google.common.base.Joiner import com.google.common.base.Joiner
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction
import info.nightscout.androidaps.databinding.DialogCareBinding import info.nightscout.androidaps.databinding.DialogCareBinding
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.Translator
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.fromConstant import info.nightscout.androidaps.extensions.fromConstant
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
@ -38,10 +39,9 @@ import javax.inject.Inject
class CareDialog : DialogFragmentWithDate() { class CareDialog : DialogFragmentWithDate() {
@Inject lateinit var injector: HasAndroidInjector @Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var mainApp: MainApp @Inject lateinit var ctx: Context
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var translator: Translator @Inject lateinit var translator: Translator
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@ -60,7 +60,8 @@ class CareDialog : DialogFragmentWithDate() {
} }
private var options: EventType = EventType.BGCHECK private var options: EventType = EventType.BGCHECK
private var valuesWithUnit = mutableListOf<ValueWithUnit>() //private var valuesWithUnit = mutableListOf<XXXValueWithUnit?>()
private var valuesWithUnit = mutableListOf<ValueWithUnit?>()
@StringRes @StringRes
private var event: Int = R.string.none private var event: Int = R.string.none
@ -198,17 +199,17 @@ class CareDialog : DialogFragmentWithDate() {
binding.sensor.isChecked -> TherapyEvent.MeterType.SENSOR binding.sensor.isChecked -> TherapyEvent.MeterType.SENSOR
else -> TherapyEvent.MeterType.MANUAL else -> TherapyEvent.MeterType.MANUAL
} }
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + translator.translate(meterType.text)) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + translator.translate(meterType))
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, binding.bg.value) + " " + resourceHelper.gs(unitResId)) actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, binding.bg.value) + " " + resourceHelper.gs(unitResId))
therapyEvent.glucoseType = meterType therapyEvent.glucoseType = meterType
therapyEvent.glucose = binding.bg.value therapyEvent.glucose = binding.bg.value
valuesWithUnit.add(ValueWithUnit(binding.bg.value.toDouble(), profileFunction.getUnits())) valuesWithUnit.add(ValueWithUnit.fromGlucoseUnit(binding.bg.value.toDouble(), profileFunction.getUnits()))
valuesWithUnit.add(ValueWithUnit(meterType.text, Units.TherapyEvent)) valuesWithUnit.add(ValueWithUnit.TherapyEventMeterType(meterType))
} }
if (options == EventType.NOTE || options == EventType.EXERCISE) { if (options == EventType.NOTE || options == EventType.EXERCISE) {
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_duration_label) + ": " + resourceHelper.gs(R.string.format_mins, binding.duration.value.toInt())) actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_duration_label) + ": " + resourceHelper.gs(R.string.format_mins, binding.duration.value.toInt()))
therapyEvent.duration = T.mins(binding.duration.value.toLong()).msecs() therapyEvent.duration = T.mins(binding.duration.value.toLong()).msecs()
valuesWithUnit.add(ValueWithUnit(binding.duration.value.toInt(), Units.M, !binding.duration.value.equals(0.0))) valuesWithUnit.add(ValueWithUnit.Minute(binding.duration.value.toInt()).takeIf { !binding.duration.value.equals(0.0) } )
} }
val notes = binding.notesLayout.notes.text.toString() val notes = binding.notesLayout.notes.text.toString()
if (notes.isNotEmpty()) { if (notes.isNotEmpty()) {
@ -220,16 +221,26 @@ class CareDialog : DialogFragmentWithDate() {
therapyEvent.enteredBy = enteredBy therapyEvent.enteredBy = enteredBy
var source = when (options) {
EventType.BGCHECK -> Sources.BgCheck
EventType.SENSOR_INSERT -> Sources.SensorInsert
EventType.BATTERY_CHANGE -> Sources.BatteryChange
EventType.NOTE -> Sources.Note
EventType.EXERCISE -> Sources.Exercise
EventType.QUESTION -> Sources.Question
EventType.ANNOUNCEMENT -> Sources.Announcement
}
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction(therapyEvent)).subscribe({ result -> disposable += repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent))
result.inserted.forEach { nsUpload.uploadEvent(it) } .subscribe(
}, { { result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
aapsLogger.error(LTag.BGSOURCE, "Error while saving therapy event", it) { aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
}) )
valuesWithUnit.add(0, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged)) valuesWithUnit.add(0, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged })
valuesWithUnit.add(1, ValueWithUnit(therapyEvent.type.text, Units.TherapyEvent)) valuesWithUnit.add(1, ValueWithUnit.TherapyEventType(therapyEvent.type))
uel.log(Action.CAREPORTAL, notes, valuesWithUnit) uel.log(Action.CAREPORTAL, source, notes, valuesWithUnit)
}, null) }, null)
} }
return true return true

View file

@ -8,9 +8,11 @@ import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogExtendedbolusBinding import info.nightscout.androidaps.databinding.DialogExtendedbolusBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -19,7 +21,7 @@ import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
@ -32,7 +34,7 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private var _binding: DialogExtendedbolusBinding? = null private var _binding: DialogExtendedbolusBinding? = null
@ -88,7 +90,9 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log(Action.EXTENDED_BOLUS, ValueWithUnit(insulinAfterConstraint, Units.U), ValueWithUnit(durationInMinutes, Units.M)) uel.log(Action.EXTENDED_BOLUS, Sources.ExtendedBolusDialog,
ValueWithUnit.Insulin(insulinAfterConstraint),
ValueWithUnit.Minute(durationInMinutes))
commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() { commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {

View file

@ -10,24 +10,24 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction
import info.nightscout.androidaps.databinding.DialogFillBinding import info.nightscout.androidaps.databinding.DialogFillBinding
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
@ -40,9 +40,8 @@ class FillDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var ctx: Context @Inject lateinit var ctx: Context
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@ -124,7 +123,7 @@ class FillDialog : DialogFragmentWithDate() {
val insulinChange = binding.fillCartridgeChange.isChecked val insulinChange = binding.fillCartridgeChange.isChecked
if (insulinChange) if (insulinChange)
actions.add(resourceHelper.gs(R.string.record_insulin_cartridge_change).formatColor(resourceHelper, R.color.actionsConfirm)) actions.add(resourceHelper.gs(R.string.record_insulin_cartridge_change).formatColor(resourceHelper, R.color.actionsConfirm))
val notes = binding.notesLayout.notes.text.toString() val notes: String = binding.notesLayout.notes.text.toString()
if (notes.isNotEmpty()) if (notes.isNotEmpty())
actions.add(resourceHelper.gs(R.string.notes_label) + ": " + notes) actions.add(resourceHelper.gs(R.string.notes_label) + ": " + notes)
eventTime -= eventTime % 1000 eventTime -= eventTime % 1000
@ -136,35 +135,41 @@ class FillDialog : DialogFragmentWithDate() {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
uel.log(Action.PRIME_BOLUS, notes, ValueWithUnit(insulinAfterConstraints, Units.U, insulinAfterConstraints != 0.0)) uel.log(Action.PRIME_BOLUS, Sources.FillDialog,
notes,
ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 })
requestPrimeBolus(insulinAfterConstraints, notes) requestPrimeBolus(insulinAfterConstraints, notes)
} }
if (siteChange) { if (siteChange) {
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(TherapyEvent.Type.CANNULA_CHANGE.text, Units.TherapyEvent)) uel.log(Action.SITE_CHANGE, Sources.FillDialog,
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction( notes,
ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged },
ValueWithUnit.TherapyEventType(TherapyEvent.Type.CANNULA_CHANGE))
disposable += repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(
timestamp = eventTime, timestamp = eventTime,
type = TherapyEvent.Type.CANNULA_CHANGE, type = TherapyEvent.Type.CANNULA_CHANGE,
note = notes, note = notes,
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result -> )).subscribe(
result.inserted.forEach { nsUpload.uploadEvent(it) } { result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
}, { { aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
aapsLogger.error(LTag.BGSOURCE, "Error while saving therapy event", it) )
})
} }
if (insulinChange) { if (insulinChange) {
// add a second for case of both checked // add a second for case of both checked
uel.log(Action.CAREPORTAL, notes, ValueWithUnit(TherapyEvent.Type.INSULIN_CHANGE.text, Units.TherapyEvent)) uel.log(Action.RESERVOIR_CHANGE, Sources.FillDialog,
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction( notes,
ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged },
ValueWithUnit.TherapyEventType(TherapyEvent.Type.INSULIN_CHANGE))
disposable += repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(
timestamp = eventTime + 1000, timestamp = eventTime + 1000,
type = TherapyEvent.Type.INSULIN_CHANGE, type = TherapyEvent.Type.INSULIN_CHANGE,
note = notes, note = notes,
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result -> )).subscribe(
result.inserted.forEach { nsUpload.uploadEvent(it) } { result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
}, { { aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
aapsLogger.error(LTag.BGSOURCE, "Error while saving therapy event", it) )
})
} }
}, null) }, null)
} }
@ -181,8 +186,7 @@ class FillDialog : DialogFragmentWithDate() {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = insulin detailedBolusInfo.insulin = insulin
detailedBolusInfo.context = context detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.PRIMING
detailedBolusInfo.isValid = false // do not count it in IOB (for pump history)
detailedBolusInfo.notes = notes detailedBolusInfo.notes = notes
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {

View file

@ -8,33 +8,32 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogInsulinBinding import info.nightscout.androidaps.databinding.DialogInsulinBinding
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.extensions.toSignedString import info.nightscout.androidaps.utils.extensions.toSignedString
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
@ -52,12 +51,11 @@ class InsulinDialog : DialogFragmentWithDate() {
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var ctx: Context @Inject lateinit var ctx: Context
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var nsUpload: NSUpload
companion object { companion object {
@ -177,7 +175,7 @@ class InsulinDialog : DialogFragmentWithDate() {
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, eatingSoonTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation)) 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 = binding.time.value.toInt() val timeOffset = binding.time.value.toInt()
val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs() val time = dateUtil.now() + T.mins(timeOffset.toLong()).msecs()
if (timeOffset != 0) if (timeOffset != 0)
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(time)) actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(time))
@ -189,7 +187,11 @@ class InsulinDialog : DialogFragmentWithDate() {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
if (eatingSoonChecked) { if (eatingSoonChecked) {
uel.log(Action.TT, notes, ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(eatingSoonTT, units), ValueWithUnit(eatingSoonTTDuration, Units.M)) uel.log(Action.TT, Sources.InsulinDialog,
notes,
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON),
ValueWithUnit.fromGlucoseUnit(eatingSoonTT, units),
ValueWithUnit.Minute(eatingSoonTTDuration))
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
timestamp = System.currentTimeMillis(), timestamp = System.currentTimeMillis(),
duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()), duration = TimeUnit.MINUTES.toMillis(eatingSoonTTDuration.toLong()),
@ -197,26 +199,34 @@ class InsulinDialog : DialogFragmentWithDate() {
lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()), lowTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()),
highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()) highTarget = Profile.toMgdl(eatingSoonTT, profileFunction.getUnits())
)).subscribe({ result -> )).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { nsUpload.updateTempTarget(it) } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
} }
if (insulinAfterConstraints > 0) { if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS.text detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
detailedBolusInfo.insulin = insulinAfterConstraints detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.context = context detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
detailedBolusInfo.notes = notes detailedBolusInfo.notes = notes
detailedBolusInfo.timestamp = time
if (recordOnlyChecked) { if (recordOnlyChecked) {
uel.log(Action.BOLUS_RECORD, notes, ValueWithUnit(insulinAfterConstraints, Units.U), ValueWithUnit(timeOffset, Units.M, timeOffset!= 0)) uel.log(Action.BOLUS, Sources.InsulinDialog,
detailedBolusInfo.date = time resourceHelper.gs(R.string.record) + if (notes.isNotEmpty()) ": " + notes else "",
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) ValueWithUnit.SimpleString(resourceHelper.gsNotLocalised(R.string.record)),
ValueWithUnit.Insulin(insulinAfterConstraints),
ValueWithUnit.Minute(timeOffset).takeIf { timeOffset!= 0 })
disposable += repository.runTransactionForResult(detailedBolusInfo.insertBolusTransaction())
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) }
)
} else { } else {
uel.log(Action.BOLUS, notes, ValueWithUnit(insulinAfterConstraints, Units.U)) uel.log(Action.BOLUS, Sources.InsulinDialog,
detailedBolusInfo.date = DateUtil.now() notes,
ValueWithUnit.Insulin(insulinAfterConstraints))
commandQueue.bolus(detailedBolusInfo, object : Callback() { commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {

View file

@ -12,7 +12,9 @@ import androidx.fragment.app.FragmentManager
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogLoopBinding import info.nightscout.androidaps.databinding.DialogLoopBinding
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
@ -21,13 +23,12 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
@ -42,10 +43,10 @@ class LoopDialog : DaggerDialogFragment() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var loopPlugin: LoopPlugin @Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin @Inject lateinit var configBuilder: ConfigBuilder
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private var showOkCancel: Boolean = true private var showOkCancel: Boolean = true
@ -197,7 +198,7 @@ class LoopDialog : DaggerDialogFragment() {
} }
} }
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()
val profileStore = activePlugin.activeProfileInterface.profile val profileStore = activePlugin.activeProfileSource.profile
if (profile == null || profileStore == null) { if (profile == null || profileStore == null) {
ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofile)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofile))
@ -239,31 +240,31 @@ class LoopDialog : DaggerDialogFragment() {
val profile = profileFunction.getProfile() ?: return true val profile = profileFunction.getProfile() ?: return true
when (v.id) { when (v.id) {
R.id.overview_closeloop -> { R.id.overview_closeloop -> {
uel.log(Action.CLOSED_LOOP_MODE) uel.log(Action.CLOSED_LOOP_MODE, Sources.LoopDialog)
sp.putString(R.string.key_aps_mode, "closed") sp.putString(R.string.key_aps_mode, "closed")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.closedloop))) rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.closedloop)))
return true return true
} }
R.id.overview_lgsloop -> { R.id.overview_lgsloop -> {
uel.log(Action.LGS_LOOP_MODE) uel.log(Action.LGS_LOOP_MODE, Sources.LoopDialog)
sp.putString(R.string.key_aps_mode, "lgs") sp.putString(R.string.key_aps_mode, "lgs")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend))) rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
return true return true
} }
R.id.overview_openloop -> { R.id.overview_openloop -> {
uel.log(Action.OPEN_LOOP_MODE) uel.log(Action.OPEN_LOOP_MODE, Sources.LoopDialog)
sp.putString(R.string.key_aps_mode, "open") sp.putString(R.string.key_aps_mode, "open")
rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend))) rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend)))
return true return true
} }
R.id.overview_disable -> { R.id.overview_disable -> {
uel.log(Action.LOOP_DISABLED) uel.log(Action.LOOP_DISABLED, Sources.LoopDialog)
loopPlugin.setPluginEnabled(PluginType.LOOP, false) loopPlugin.setPluginEnabled(PluginType.LOOP, false)
loopPlugin.setFragmentVisible(PluginType.LOOP, false) loopPlugin.setFragmentVisible(PluginType.LOOP, false)
configBuilderPlugin.storeSettings("DisablingLoop") configBuilder.storeSettings("DisablingLoop")
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
commandQueue.cancelTempBasal(true, object : Callback() { commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() { override fun run() {
@ -277,17 +278,17 @@ class LoopDialog : DaggerDialogFragment() {
} }
R.id.overview_enable -> { R.id.overview_enable -> {
uel.log(Action.LOOP_ENABLED) uel.log(Action.LOOP_ENABLED, Sources.LoopDialog)
loopPlugin.setPluginEnabled(PluginType.LOOP, true) loopPlugin.setPluginEnabled(PluginType.LOOP, true)
loopPlugin.setFragmentVisible(PluginType.LOOP, true) loopPlugin.setFragmentVisible(PluginType.LOOP, true)
configBuilderPlugin.storeSettings("EnablingLoop") configBuilder.storeSettings("EnablingLoop")
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
loopPlugin.createOfflineEvent(0) loopPlugin.createOfflineEvent(0)
return true return true
} }
R.id.overview_resume, R.id.overview_reconnect -> { R.id.overview_resume, R.id.overview_reconnect -> {
uel.log(if (v.id==R.id.overview_resume) Action.RESUME else Action.RECONNECT ) uel.log(if (v.id==R.id.overview_resume) Action.RESUME else Action.RECONNECT, Sources.LoopDialog)
loopPlugin.suspendTo(0L) loopPlugin.suspendTo(0L)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
commandQueue.cancelTempBasal(true, object : Callback() { commandQueue.cancelTempBasal(true, object : Callback() {
@ -303,49 +304,49 @@ class LoopDialog : DaggerDialogFragment() {
} }
R.id.overview_suspend_1h -> { R.id.overview_suspend_1h -> {
uel.log(Action.SUSPEND, ValueWithUnit(1, Units.H)) uel.log(Action.SUSPEND, Sources.LoopDialog, ValueWithUnit.Hour(1))
loopPlugin.suspendLoop(60) loopPlugin.suspendLoop(60)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true
} }
R.id.overview_suspend_2h -> { R.id.overview_suspend_2h -> {
uel.log(Action.SUSPEND, ValueWithUnit(2, Units.H)) uel.log(Action.SUSPEND, Sources.LoopDialog, ValueWithUnit.Hour(2))
loopPlugin.suspendLoop(120) loopPlugin.suspendLoop(120)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true
} }
R.id.overview_suspend_3h -> { R.id.overview_suspend_3h -> {
uel.log(Action.SUSPEND, ValueWithUnit(3, Units.H)) uel.log(Action.SUSPEND, Sources.LoopDialog, ValueWithUnit.Hour(3))
loopPlugin.suspendLoop(180) loopPlugin.suspendLoop(180)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true
} }
R.id.overview_suspend_10h -> { R.id.overview_suspend_10h -> {
uel.log(Action.SUSPEND, ValueWithUnit(10, Units.H)) uel.log(Action.SUSPEND, Sources.LoopDialog, ValueWithUnit.Hour(10))
loopPlugin.suspendLoop(600) loopPlugin.suspendLoop(600)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true
} }
R.id.overview_disconnect_15m -> { R.id.overview_disconnect_15m -> {
uel.log(Action.DISCONNECT, ValueWithUnit(15, Units.M)) uel.log(Action.DISCONNECT, Sources.LoopDialog, ValueWithUnit.Minute(15))
loopPlugin.disconnectPump(15, profile) loopPlugin.disconnectPump(15, profile)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true
} }
R.id.overview_disconnect_30m -> { R.id.overview_disconnect_30m -> {
uel.log(Action.DISCONNECT, ValueWithUnit(30, Units.M)) uel.log(Action.DISCONNECT, Sources.LoopDialog, ValueWithUnit.Minute(30))
loopPlugin.disconnectPump(30, profile) loopPlugin.disconnectPump(30, profile)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true
} }
R.id.overview_disconnect_1h -> { R.id.overview_disconnect_1h -> {
uel.log(Action.DISCONNECT, ValueWithUnit(1, Units.H)) uel.log(Action.DISCONNECT, Sources.LoopDialog, ValueWithUnit.Hour(1))
loopPlugin.disconnectPump(60, profile) loopPlugin.disconnectPump(60, profile)
sp.putBoolean(R.string.key_objectiveusedisconnect, true) sp.putBoolean(R.string.key_objectiveusedisconnect, true)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
@ -353,14 +354,14 @@ class LoopDialog : DaggerDialogFragment() {
} }
R.id.overview_disconnect_2h -> { R.id.overview_disconnect_2h -> {
uel.log(Action.DISCONNECT, ValueWithUnit(2, Units.H)) uel.log(Action.DISCONNECT, Sources.LoopDialog, ValueWithUnit.Hour(2))
loopPlugin.disconnectPump(120, profile) loopPlugin.disconnectPump(120, profile)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true
} }
R.id.overview_disconnect_3h -> { R.id.overview_disconnect_3h -> {
uel.log(Action.DISCONNECT, ValueWithUnit(3, Units.H)) uel.log(Action.DISCONNECT, Sources.LoopDialog, ValueWithUnit.Hour(3))
loopPlugin.disconnectPump(180, profile) loopPlugin.disconnectPump(180, profile)
rxBus.send(EventRefreshOverview("suspendmenu")) rxBus.send(EventRefreshOverview("suspendmenu"))
return true return true

View file

@ -8,13 +8,14 @@ import android.widget.ArrayAdapter
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogProfileswitchBinding import info.nightscout.androidaps.databinding.DialogProfileswitchBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
@ -27,7 +28,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private var profileIndex: Int? = null private var profileIndex: Int? = null
@ -67,7 +68,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
// profile // profile
context?.let { context -> context?.let { context ->
val profileStore = activePlugin.activeProfileInterface.profile val profileStore = activePlugin.activeProfileSource.profile
?: return ?: return
val profileList = profileStore.getProfileList() val profileList = profileStore.getProfileList()
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
@ -81,7 +82,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
binding.profile.setSelection(p) binding.profile.setSelection(p)
} ?: return } ?: return
treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now())?.let { ps -> treatmentsPlugin.getProfileSwitchFromHistory(dateUtil.now())?.let { ps ->
if (ps.isCPP) { if (ps.isCPP) {
binding.reuselayout.visibility = View.VISIBLE binding.reuselayout.visibility = View.VISIBLE
binding.reusebutton.text = resourceHelper.gs(R.string.reuse_profile_pct_hours, ps.percentage, ps.timeshift) binding.reusebutton.text = resourceHelper.gs(R.string.reuse_profile_pct_hours, ps.percentage, ps.timeshift)
@ -102,7 +103,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
override fun submit(): Boolean { override fun submit(): Boolean {
if (_binding == null) return false if (_binding == null) return false
val profileStore = activePlugin.activeProfileInterface.profile val profileStore = activePlugin.activeProfileSource.profile
?: return false ?: return false
val actions: LinkedList<String> = LinkedList() val actions: LinkedList<String> = LinkedList()
@ -125,7 +126,14 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log(Action.PROFILE_SWITCH, notes, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(profile, Units.None), ValueWithUnit(percent, Units.Percent), ValueWithUnit(timeShift, Units.H, timeShift != 0), ValueWithUnit(duration, Units.M, duration != 0)) uel.log(Action.PROFILE_SWITCH,
Sources.ProfileSwitchDialog,
notes,
ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged },
ValueWithUnit.SimpleString(profile),
ValueWithUnit.Percent(percent),
ValueWithUnit.Hour(timeShift).takeIf { timeShift != 0 },
ValueWithUnit.Minute(duration).takeIf { duration != 0 })
treatmentsPlugin.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime) treatmentsPlugin.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime)
}) })
} }

View file

@ -8,20 +8,18 @@ import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogTempbasalBinding import info.nightscout.androidaps.databinding.DialogTempbasalBinding
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
@ -33,7 +31,7 @@ class TempBasalDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var ctx: Context @Inject lateinit var ctx: Context
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@ -126,11 +124,15 @@ class TempBasalDialog : DialogFragmentWithDate() {
} }
} }
if (isPercentPump) { if (isPercentPump) {
uel.log(Action.TEMP_BASAL, ValueWithUnit(percent, Units.Percent), ValueWithUnit(durationInMinutes, Units.M)) uel.log(Action.TEMP_BASAL, Sources.TempBasalDialog,
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback) ValueWithUnit.Percent(percent),
ValueWithUnit.Minute(durationInMinutes))
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} else { } else {
uel.log(Action.TEMP_BASAL, ValueWithUnit(absolute, Units.U), ValueWithUnit(durationInMinutes, Units.M)) uel.log(Action.TEMP_BASAL, Sources.TempBasalDialog,
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback) ValueWithUnit.Insulin(absolute),
ValueWithUnit.Minute(durationInMinutes))
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} }
}) })
} }

View file

@ -12,8 +12,10 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction import info.nightscout.androidaps.database.transactions.InsertTemporaryTargetAndCancelCurrentTransaction
import info.nightscout.androidaps.databinding.DialogTemptargetBinding import info.nightscout.androidaps.databinding.DialogTemptargetBinding
@ -21,7 +23,6 @@ import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
@ -41,7 +42,6 @@ class TempTargetDialog : DialogFragmentWithDate() {
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var nsUpload: NSUpload
private lateinit var reasonList: List<String> private lateinit var reasonList: List<String>
@ -88,7 +88,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
// temp target // temp target
context?.let { context -> context?.let { context ->
if (repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing) if (repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing)
binding.targetCancel.visibility = View.VISIBLE binding.targetCancel.visibility = View.VISIBLE
else else
binding.targetCancel.visibility = View.GONE binding.targetCancel.visibility = View.GONE
@ -135,19 +135,19 @@ class TempTargetDialog : DialogFragmentWithDate() {
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.eatingsoon))) binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.eatingsoon)))
} }
R.id.activity -> { R.id.activity -> {
binding.temptarget.value = defaultValueHelper.determineActivityTT() binding.temptarget.value = defaultValueHelper.determineActivityTT()
binding.duration.value = defaultValueHelper.determineActivityTTDuration().toDouble() binding.duration.value = defaultValueHelper.determineActivityTTDuration().toDouble()
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.activity))) binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.activity)))
} }
R.id.hypo -> { R.id.hypo -> {
binding.temptarget.value = defaultValueHelper.determineHypoTT() binding.temptarget.value = defaultValueHelper.determineHypoTT()
binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble() binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo))) binding.reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo)))
} }
R.id.cancel -> { R.id.cancel -> {
binding.duration.value = 0.0 binding.duration.value = 0.0
} }
} }
@ -181,18 +181,18 @@ class TempTargetDialog : DialogFragmentWithDate() {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
when(reason) { when(reason) {
resourceHelper.gs(R.string.eatingsoon) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.EATING_SOON.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M)) resourceHelper.gs(R.string.eatingsoon) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.EATING_SOON), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.activity) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.ACTIVITY.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M)) resourceHelper.gs(R.string.activity) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.ACTIVITY), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.hypo) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.HYPOGLYCEMIA.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M)) resourceHelper.gs(R.string.hypo) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.HYPOGLYCEMIA), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.manual) -> uel.log(Action.TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged), ValueWithUnit(TemporaryTarget.Reason.CUSTOM.text, Units.TherapyEvent), ValueWithUnit(target, units), ValueWithUnit(duration, Units.M)) resourceHelper.gs(R.string.manual) -> uel.log(Action.TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged }, ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.CUSTOM), ValueWithUnit.fromGlucoseUnit(target, units), ValueWithUnit.Minute(duration))
resourceHelper.gs(R.string.stoptemptarget) -> uel.log(Action.CANCEL_TT, ValueWithUnit(eventTime, Units.Timestamp, eventTimeChanged)) resourceHelper.gs(R.string.stoptemptarget) -> uel.log(Action.CANCEL_TT, Sources.TTDialog, ValueWithUnit.Timestamp(eventTime).takeIf { eventTimeChanged })
} }
if (target == 0.0 || duration == 0) { if (target == 0.0 || duration == 0) {
disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(eventTime)) disposable += repository.runTransactionForResult(CancelCurrentTemporaryTargetIfAnyTransaction(eventTime))
.subscribe({ result -> .subscribe({ result ->
result.updated.forEach { nsUpload.updateTempTarget(it) } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
} else { } else {
disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction( disposable += repository.runTransactionForResult(InsertTemporaryTargetAndCancelCurrentTransaction(
@ -200,17 +200,17 @@ class TempTargetDialog : DialogFragmentWithDate() {
duration = TimeUnit.MINUTES.toMillis(duration.toLong()), duration = TimeUnit.MINUTES.toMillis(duration.toLong()),
reason = when (reason) { reason = when (reason) {
resourceHelper.gs(R.string.eatingsoon) -> TemporaryTarget.Reason.EATING_SOON resourceHelper.gs(R.string.eatingsoon) -> TemporaryTarget.Reason.EATING_SOON
resourceHelper.gs(R.string.activity) -> TemporaryTarget.Reason.ACTIVITY resourceHelper.gs(R.string.activity) -> TemporaryTarget.Reason.ACTIVITY
resourceHelper.gs(R.string.hypo) -> TemporaryTarget.Reason.HYPOGLYCEMIA resourceHelper.gs(R.string.hypo) -> TemporaryTarget.Reason.HYPOGLYCEMIA
else -> TemporaryTarget.Reason.CUSTOM else -> TemporaryTarget.Reason.CUSTOM
}, },
lowTarget = Profile.toMgdl(target, profileFunction.getUnits()), lowTarget = Profile.toMgdl(target, profileFunction.getUnits()),
highTarget = Profile.toMgdl(target, profileFunction.getUnits()) highTarget = Profile.toMgdl(target, profileFunction.getUnits())
)).subscribe({ result -> )).subscribe({ result ->
result.inserted.forEach { nsUpload.uploadTempTarget(it) } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { nsUpload.updateTempTarget(it) } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
}, { }, {
aapsLogger.error(LTag.BGSOURCE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
} }

View file

@ -8,17 +8,19 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.common.base.Joiner import com.google.common.base.Joiner
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.DialogTreatmentBinding import info.nightscout.androidaps.databinding.DialogTreatmentBinding
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
@ -27,8 +29,10 @@ import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -38,11 +42,14 @@ class TreatmentDialog : DialogFragmentWithDate() {
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var ctx: Context @Inject lateinit var ctx: Context
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
private val disposable = CompositeDisposable()
private val textWatcher: TextWatcher = object : TextWatcher { private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {} override fun afterTextChanged(s: Editable) {}
@ -130,24 +137,51 @@ class TreatmentDialog : DialogFragmentWithDate() {
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) { if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
uel.log(Action.TREATMENT, ValueWithUnit(insulin, Units.U, insulin != 0.0), ValueWithUnit(carbs, Units.G, carbs != 0)) val action = when {
insulinAfterConstraints.equals(0.0) -> Action.CARBS
carbsAfterConstraints.equals(0) -> Action.BOLUS
else -> Action.TREATMENT
}
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = TherapyEvent.Type.CARBS_CORRECTION.text if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CARBS_CORRECTION
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS.text if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
detailedBolusInfo.insulin = insulinAfterConstraints detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.carbs = carbsAfterConstraints.toDouble() detailedBolusInfo.carbs = carbsAfterConstraints.toDouble()
detailedBolusInfo.context = context detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER if (recordOnlyChecked) {
if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) { uel.log(action, Sources.TreatmentDialog, if (insulinAfterConstraints != 0.0) resourceHelper.gs(R.string.record) else "",
commandQueue.bolus(detailedBolusInfo, object : Callback() { ValueWithUnit.Timestamp(detailedBolusInfo.timestamp).takeIf { eventTimeChanged },
override fun run() { ValueWithUnit.SimpleString(resourceHelper.gsNotLocalised(R.string.record)).takeIf { insulinAfterConstraints != 0.0 },
if (!result.success) { ValueWithUnit.Insulin(insulinAfterConstraints).takeIf { insulinAfterConstraints != 0.0 },
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) ValueWithUnit.Gram(carbsAfterConstraints).takeIf { carbsAfterConstraints != 0 })
if (detailedBolusInfo.insulin > 0)
disposable += repository.runTransactionForResult(detailedBolusInfo.insertBolusTransaction())
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) }
)
if (detailedBolusInfo.carbs > 0)
disposable += repository.runTransactionForResult(detailedBolusInfo.insertCarbsTransaction())
.subscribe(
{ result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } },
{ aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) }
)
} else {
if (detailedBolusInfo.insulin > 0) {
uel.log(action, Sources.TreatmentDialog,
ValueWithUnit.Insulin(insulinAfterConstraints),
ValueWithUnit.Gram(carbsAfterConstraints).takeIf { carbsAfterConstraints != 0 })
commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
ErrorHelperActivity.runAlarm(ctx, result.comment, resourceHelper.gs(R.string.treatmentdeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
}
} }
} })
}) } else
} else uel.log(action, Sources.TreatmentDialog,
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) ValueWithUnit.Gram(carbsAfterConstraints).takeIf { carbs != 0 })
}
}) })
} }
} else } else

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.dialogs package info.nightscout.androidaps.dialogs
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@ -16,25 +17,27 @@ import androidx.fragment.app.FragmentManager
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.databinding.DialogWizardBinding import info.nightscout.androidaps.databinding.DialogWizardBinding
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.TreatmentsInterface
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.extensions.valueToUnits import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.valueToUnits
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -51,16 +54,15 @@ class WizardDialog : DaggerDialogFragment() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var mainApp: MainApp @Inject lateinit var ctx: Context
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var treatmentsPlugin: TreatmentsInterface
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
private var wizard: BolusWizard? = null private var wizard: BolusWizard? = null
@ -180,7 +182,7 @@ class WizardDialog : DaggerDialogFragment() {
// profile spinner // profile spinner
binding.profile.onItemSelectedListener = object : OnItemSelectedListener { binding.profile.onItemSelectedListener = object : OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) { override fun onNothingSelected(parent: AdapterView<*>?) {
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofileselected)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofileselected))
binding.ok.visibility = View.GONE binding.ok.visibility = View.GONE
} }
@ -208,7 +210,7 @@ class WizardDialog : DaggerDialogFragment() {
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) { private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
saveCheckedStates() saveCheckedStates()
binding.ttcheckbox.isEnabled = binding.bgcheckbox.isChecked && repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing binding.ttcheckbox.isEnabled = binding.bgcheckbox.isChecked && repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
if (buttonView.id == binding.cobcheckbox.id) if (buttonView.id == binding.cobcheckbox.id)
processCobCheckBox() processCobCheckBox()
calculateInsulin() calculateInsulin()
@ -242,10 +244,10 @@ class WizardDialog : DaggerDialogFragment() {
private fun initDialog() { private fun initDialog() {
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()
val profileStore = activePlugin.activeProfileInterface.profile val profileStore = activePlugin.activeProfileSource.profile
if (profile == null || profileStore == null) { if (profile == null || profileStore == null) {
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofile)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofile))
dismiss() dismiss()
return return
} }
@ -265,20 +267,12 @@ class WizardDialog : DaggerDialogFragment() {
binding.bgInput.setStep(0.1) binding.bgInput.setStep(0.1)
// Set BG if not old // Set BG if not old
val lastBg = iobCobCalculatorPlugin.actualBg() binding.bgInput.value = iobCobCalculator.ads.actualBg()?.valueToUnits(units) ?: 0.0
binding.ttcheckbox.isEnabled = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
if (lastBg != null) {
binding.bgInput.value = lastBg.valueToUnits(units)
} else {
binding.bgInput.value = 0.0
}
binding.ttcheckbox.isEnabled = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing
// IOB calculation // IOB calculation
treatmentsPlugin.updateTotalIOBTreatments() val bolusIob = iobCobCalculator.calculateIobFromBolus().round()
val bolusIob = treatmentsPlugin.lastCalculationTreatments.round() val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
treatmentsPlugin.updateTotalIOBTempBasals()
val basalIob = treatmentsPlugin.lastCalculationTempBasals.round()
binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob) binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob)
binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob) binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob)
@ -289,7 +283,7 @@ class WizardDialog : DaggerDialogFragment() {
} }
private fun calculateInsulin() { private fun calculateInsulin() {
val profileStore = activePlugin.activeProfileInterface.profile val profileStore = activePlugin.activeProfileSource.profile
if (binding.profile.selectedItem == null || profileStore == null) if (binding.profile.selectedItem == null || profileStore == null)
return // not initialized yet return // not initialized yet
var profileName = binding.profile.selectedItem.toString() var profileName = binding.profile.selectedItem.toString()
@ -309,25 +303,25 @@ class WizardDialog : DaggerDialogFragment() {
val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value() val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
if (abs(carbs - carbsAfterConstraint) > 0.01) { if (abs(carbs - carbsAfterConstraint) > 0.01) {
binding.carbsInput.value = 0.0 binding.carbsInput.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied)) ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.carbsconstraintapplied))
return return
} }
bg = if (binding.bgcheckbox.isChecked) bg else 0.0 bg = if (binding.bgcheckbox.isChecked) bg else 0.0
val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
val tempTarget = if (binding.ttcheckbox.isChecked && dbRecord is ValueWrapper.Existing) dbRecord.value else null val tempTarget = if (binding.ttcheckbox.isChecked && dbRecord is ValueWrapper.Existing) dbRecord.value else null
// COB // COB
var cob = 0.0 var cob = 0.0
if (binding.cobcheckbox.isChecked) { if (binding.cobcheckbox.isChecked) {
val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Wizard COB") val cobInfo = iobCobCalculator.getCobInfo(false, "Wizard COB")
cobInfo.displayCob?.let { cob = it } cobInfo.displayCob?.let { cob = it }
} }
val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text) val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text)
wizard = BolusWizard(mainApp).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction, wizard = BolusWizard(injector).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction,
sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble(), sp.getInt(R.string.key_boluswizard_percentage, 100),
binding.bgcheckbox.isChecked, binding.bgcheckbox.isChecked,
binding.cobcheckbox.isChecked, binding.cobcheckbox.isChecked,
binding.bolusiobcheckbox.isChecked, binding.bolusiobcheckbox.isChecked,

View file

@ -9,12 +9,12 @@ import android.view.WindowManager
import dagger.android.support.DaggerDialogFragment import dagger.android.support.DaggerDialogFragment
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.databinding.DialogWizardinfoBinding import info.nightscout.androidaps.databinding.DialogWizardinfoBinding
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
class WizardInfoDialog : DaggerDialogFragment() { class WizardInfoDialog : DaggerDialogFragment() {
@ -22,10 +22,10 @@ class WizardInfoDialog : DaggerDialogFragment() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
private var json: JSONObject? = null private lateinit var data: BolusCalculatorResult
fun setData(json: JSONObject) { fun setData(bolusCalculatorResult: BolusCalculatorResult) {
this.json = json this.data = bolusCalculatorResult
} }
private var _binding: DialogWizardinfoBinding? = null private var _binding: DialogWizardinfoBinding? = null
@ -49,44 +49,42 @@ class WizardInfoDialog : DaggerDialogFragment() {
binding.close.setOnClickListener { dismiss() } binding.close.setOnClickListener { dismiss() }
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val bgString = val bgString = Profile.toUnitsString(data.glucoseValue, data.glucoseValue * Constants.MGDL_TO_MMOLL, units)
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "bg"))
else DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg"))
// BG // BG
binding.bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, JsonHelper.safeGetDouble(json, "isf")) binding.bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, data.isf)
binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinbg")) binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.glucoseInsulin)
binding.bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused") binding.bgcheckbox.isChecked = data.wasGlucoseUsed
binding.ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused") binding.ttcheckbox.isChecked = data.wasTempTargetUsed
// Trend // Trend
binding.bgtrend.text = JsonHelper.safeGetString(json, "trend") binding.bgtrend.text = DecimalFormatter.to1Decimal(data.glucoseTrend)
binding.bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulintrend")) binding.bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.trendInsulin)
binding.bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused") binding.bgtrendcheckbox.isChecked = data.wasTrendUsed
// COB // COB
binding.cob.text = resourceHelper.gs(R.string.format_cob_ic, JsonHelper.safeGetDouble(json, "cob"), JsonHelper.safeGetDouble(json, "ic")) binding.cob.text = resourceHelper.gs(R.string.format_cob_ic, data.cob, data.ic)
binding.cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincob")) binding.cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.cobInsulin)
binding.cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused") binding.cobcheckbox.isChecked = data.wasCOBUsed
// Bolus IOB // Bolus IOB
binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "bolusiob")) binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.bolusIOB)
binding.bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused") binding.bolusiobcheckbox.isChecked = data.wasBolusIOBUsed
// Basal IOB // Basal IOB
binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "basaliob")) binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.basalIOB)
binding.basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused") binding.basaliobcheckbox.isChecked = data.wasBasalIOBUsed
// Superbolus // Superbolus
binding.sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinsuperbolus")) binding.sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.superbolusInsulin)
binding.sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused") binding.sbcheckbox.isChecked = data.wasSuperbolusUsed
// Carbs // Carbs
binding.carbs.text = resourceHelper.gs(R.string.format_carbs_ic, JsonHelper.safeGetDouble(json, "carbs"), JsonHelper.safeGetDouble(json, "ic")) binding.carbs.text = resourceHelper.gs(R.string.format_carbs_ic, data.carbs, data.ic)
binding.carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincarbs")) binding.carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.carbsInsulin)
// Correction // Correction
binding.correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "othercorrection")) binding.correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.otherCorrection)
// Profile // Profile
binding.profile.text = JsonHelper.safeGetString(json, "profile") binding.profile.text = data.profileName
// Notes // Notes
binding.notes.text = JsonHelper.safeGetString(json, "notes") binding.notes.text = data.note
// Percentage // Percentage
binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, (JsonHelper.safeGetInt(json, "percentageCorrection", 100))) binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, data.percentageCorrection)
// Total // Total
binding.totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulin")) binding.totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, data.totalInsulin)
} }
override fun onStart() { override fun onStart() {

View file

@ -1,21 +0,0 @@
package info.nightscout.androidaps.events
import org.json.JSONObject
/**
* Event which is published with data fetched from NightScout specific for the
* Treatment-class.
*
*
* Payload is the from NS retrieved JSON-String which should be handled by all
* subscriber.
*/
class EventNsTreatment(val mode: Int, val payload: JSONObject) : Event() {
companion object {
val ADD = 0
val UPDATE = 1
val REMOVE = 2
}
}

View file

@ -1,3 +0,0 @@
package info.nightscout.androidaps.events
class EventReloadTempBasalData : Event()

View file

@ -1,3 +0,0 @@
package info.nightscout.androidaps.events
class EventReloadTreatmentData(var next: Event) : Event()

View file

@ -1,5 +1,3 @@
package info.nightscout.androidaps.events package info.nightscout.androidaps.events
import info.nightscout.androidaps.db.Treatment class EventTreatmentChange : EventLoop()
class EventTreatmentChange(val treatment: Treatment?) : EventLoop()

View file

@ -16,14 +16,13 @@ import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.databinding.ActivityHistorybrowseBinding import info.nightscout.androidaps.databinding.ActivityHistorybrowseBinding
import info.nightscout.androidaps.events.EventCustomCalculationFinished import info.nightscout.androidaps.events.EventCustomCalculationFinished
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensBgLoaded
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
@ -31,7 +30,7 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -52,7 +51,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory @Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory
@Inject lateinit var treatmentsPluginHistory: TreatmentsPluginHistory @Inject lateinit var treatmentsPluginHistory: TreatmentsPluginHistory
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var overviewMenus: OverviewMenus @Inject lateinit var overviewMenus: OverviewMenus
@ -181,16 +180,6 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
} }
}, fabricPrivacy::logException) }, fabricPrivacy::logException)
) )
disposable.add(rxBus
.toObservable(EventAutosensBgLoaded::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
// catch only events from iobCobCalculatorPluginHistory
if (it.cause is EventCustomCalculationFinished) {
updateGUI("EventAutosensCalculationFinished", bgOnly = true)
}
}, fabricPrivacy::logException)
)
disposable.add(rxBus disposable.add(rxBus
.toObservable(EventIobCalculationProgress::class.java) .toObservable(EventIobCalculationProgress::class.java)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
@ -306,7 +295,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
graphData.addInRangeArea(fromTime, toTime, lowLine, highLine) graphData.addInRangeArea(fromTime, toTime, lowLine, highLine)
// **** BG **** // **** BG ****
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null) graphData.addBgReadings(fromTime, toTime, highLine, null)
if (buildHelper.isDev()) graphData.addBucketedData(fromTime, toTime)
// add target line // add target line
graphData.addTargetLine(fromTime, toTime, profile, null) graphData.addTargetLine(fromTime, toTime, profile, null)

View file

@ -2,7 +2,7 @@ package info.nightscout.androidaps.historyBrowser
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
@ -27,8 +27,7 @@ class IobCobCalculatorPluginHistory @Inject constructor(
sp: SP, sp: SP,
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
profileFunction: ProfileFunction, profileFunction: ProfileFunction,
activePlugin: ActivePluginProvider, activePlugin: ActivePlugin,
treatmentsPluginHistory: TreatmentsPluginHistory,
sensitivityOref1Plugin: SensitivityOref1Plugin, sensitivityOref1Plugin: SensitivityOref1Plugin,
sensitivityAAPSPlugin: SensitivityAAPSPlugin, sensitivityAAPSPlugin: SensitivityAAPSPlugin,
sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin, sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin,
@ -36,7 +35,7 @@ class IobCobCalculatorPluginHistory @Inject constructor(
dateUtil: DateUtil, dateUtil: DateUtil,
repository: AppRepository repository: AppRepository
) : IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction, ) : IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction,
activePlugin, treatmentsPluginHistory, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) { activePlugin, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) {
override fun onStart() { // do not attach to rxbus override fun onStart() { // do not attach to rxbus
} }

View file

@ -3,10 +3,9 @@ package info.nightscout.androidaps.historyBrowser
import android.content.Context import android.content.Context
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.UploadQueueInterface
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
@ -30,14 +29,13 @@ class TreatmentsPluginHistory @Inject constructor(
context: Context, context: Context,
sp: SP, sp: SP,
profileFunction: ProfileFunction, profileFunction: ProfileFunction,
activePlugin: ActivePluginProvider, activePlugin: ActivePlugin,
nsUpload: NSUpload, nsUpload: NSUpload,
fabricPrivacy: FabricPrivacy, fabricPrivacy: FabricPrivacy,
dateUtil: DateUtil, dateUtil: DateUtil,
uploadQueue: UploadQueueInterface,
databaseHelper: DatabaseHelperInterface, databaseHelper: DatabaseHelperInterface,
repository: AppRepository repository: AppRepository
) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue, databaseHelper, repository) { ) : TreatmentsPlugin(injector, aapsLogger, rxBus, aapsSchedulers, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, databaseHelper, repository) {
init { init {
onStart() onStart()

View file

@ -98,7 +98,6 @@ class LoopFragment : DaggerFragment() {
binding.constraintsprocessed.text = it.constraintsProcessed?.toSpanned() ?: "" binding.constraintsprocessed.text = it.constraintsProcessed?.toSpanned() ?: ""
binding.source.text = it.source ?: "" binding.source.text = it.source ?: ""
binding.lastrun.text = dateUtil.dateAndTimeString(it.lastAPSRun) binding.lastrun.text = dateUtil.dateAndTimeString(it.lastAPSRun)
?: ""
binding.smbrequestTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBRequest) binding.smbrequestTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBRequest)
binding.smbexecutionTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBEnact) binding.smbexecutionTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastSMBEnact)
binding.tbrrequestTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastTBRRequest) binding.tbrrequestTime.text = dateUtil.dateAndTimeAndSecondsString(it.lastTBRRequest)

View file

@ -17,8 +17,11 @@ import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.transactions.InsertTherapyEventIfNewTransaction import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
import info.nightscout.androidaps.events.EventAutosensCalculationFinished import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.events.EventNewBG
@ -27,20 +30,19 @@ import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.LoopInterface.LastRun import info.nightscout.androidaps.interfaces.LoopInterface.LastRun
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.configBuilder.RunningConfiguration
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification 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.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearConfirmAction
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.receivers.ReceiverStatusStore import info.nightscout.androidaps.receivers.ReceiverStatusStore
@ -48,6 +50,10 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.extensions.buildDeviceStatus
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.convertedToPercent
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -70,15 +76,15 @@ open class LoopPlugin @Inject constructor(
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val context: Context, private val context: Context,
private val commandQueue: CommandQueueProvider, private val commandQueue: CommandQueueProvider,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePlugin,
private val treatmentsPlugin: TreatmentsPlugin,
private val virtualPumpPlugin: VirtualPumpPlugin, private val virtualPumpPlugin: VirtualPumpPlugin,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val iobCobCalculator: IobCobCalculator,
private val receiverStatusStore: ReceiverStatusStore, private val receiverStatusStore: ReceiverStatusStore,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val nsUpload: NSUpload,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val repository: AppRepository private val uel: UserEntryLogger,
private val repository: AppRepository,
private val runningConfiguration: RunningConfiguration
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.LOOP) .mainType(PluginType.LOOP)
.fragmentClass(LoopFragment::class.java.name) .fragmentClass(LoopFragment::class.java.name)
@ -96,6 +102,7 @@ open class LoopPlugin @Inject constructor(
private var carbsSuggestionsSuspendedUntil: Long = 0 private var carbsSuggestionsSuspendedUntil: Long = 0
private var prevCarbsreq = 0 private var prevCarbsreq = 0
override var lastRun: LastRun? = null override var lastRun: LastRun? = null
override fun onStart() { override fun onStart() {
createNotificationChannel() createNotificationChannel()
super.onStart() super.onStart()
@ -117,7 +124,7 @@ open class LoopPlugin @Inject constructor(
.subscribe({ event: EventAutosensCalculationFinished -> .subscribe({ event: EventAutosensCalculationFinished ->
// Autosens calculation not triggered by a new BG // Autosens calculation not triggered by a new BG
if (event.cause !is EventNewBG) return@subscribe if (event.cause !is EventNewBG) return@subscribe
val glucoseValue = iobCobCalculatorPlugin.actualBg() ?: return@subscribe val glucoseValue = iobCobCalculator.ads.actualBg() ?: return@subscribe
// BG outdated // BG outdated
// already looped with that value // already looped with that value
if (glucoseValue.timestamp <= lastBgTriggeredRun) return@subscribe if (glucoseValue.timestamp <= lastBgTriggeredRun) return@subscribe
@ -233,7 +240,9 @@ open class LoopPlugin @Inject constructor(
private fun treatmentTimeThreshold(durationMinutes: Int): Boolean { private fun treatmentTimeThreshold(durationMinutes: Int): Boolean {
val threshold = System.currentTimeMillis() + durationMinutes * 60 * 1000 val threshold = System.currentTimeMillis() + durationMinutes * 60 * 1000
var bool = false var bool = false
if (treatmentsPlugin.lastBolusTime > threshold || treatmentsPlugin.lastCarbTime > threshold) bool = true val lastBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L
val lastCarbsTime = repository.getLastCarbsRecord()?.timestamp ?: 0L
if (lastBolusTime > threshold || lastCarbsTime > threshold) bool = true
return bool return bool
} }
@ -295,155 +304,162 @@ open class LoopPlugin @Inject constructor(
resultAfterConstraints.smb = constraintChecker.applyBolusConstraints(resultAfterConstraints.smbConstraint!!).value() resultAfterConstraints.smb = constraintChecker.applyBolusConstraints(resultAfterConstraints.smbConstraint!!).value()
// safety check for multiple SMBs // safety check for multiple SMBs
val lastBolusTime = treatmentsPlugin.lastBolusTime val lastBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L
if (lastBolusTime != 0L && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) { if (lastBolusTime != 0L && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) {
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval") aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
resultAfterConstraints.smb = 0.0 resultAfterConstraints.smb = 0.0
} }
if (lastRun != null && lastRun!!.constraintsProcessed != null) { prevCarbsreq = lastRun?.constraintsProcessed?.carbsReq ?: prevCarbsreq
prevCarbsreq = lastRun!!.constraintsProcessed!!.carbsReq lastRun = (lastRun ?: LastRun()).also { lastRun ->
} lastRun.request = apsResult
if (lastRun == null) lastRun = LastRun() lastRun.constraintsProcessed = resultAfterConstraints
lastRun!!.request = apsResult lastRun.lastAPSRun = dateUtil.now()
lastRun!!.constraintsProcessed = resultAfterConstraints lastRun.source = (usedAPS as PluginBase).name
lastRun!!.lastAPSRun = DateUtil.now() lastRun.tbrSetByPump = null
lastRun!!.source = (usedAPS as PluginBase).name lastRun.smbSetByPump = null
lastRun!!.tbrSetByPump = null lastRun.lastTBREnact = 0
lastRun!!.smbSetByPump = null lastRun.lastTBRRequest = 0
lastRun!!.lastTBREnact = 0 lastRun.lastSMBEnact = 0
lastRun!!.lastTBRRequest = 0 lastRun.lastSMBRequest = 0
lastRun!!.lastSMBEnact = 0 buildDeviceStatus(dateUtil, this, iobCobCalculator, profileFunction,
lastRun!!.lastSMBRequest = 0 activePlugin.activePump, receiverStatusStore, runningConfiguration,
nsUpload.uploadDeviceStatus(this, iobCobCalculatorPlugin, profileFunction, activePlugin.activePump, receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION) BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
if (isSuspended) { repository.insert(it)
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. if (isSuspended) {
mNotificationManager.notify(Constants.notificationID, builder.build()) aapsLogger.debug(LTag.APS, resourceHelper.gs(R.string.loopsuspended))
rxBus.send(EventNewOpenLoopNotification()) 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)) {
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(resultAfterConstraints.carbsRequiredText)).subscribe()
}
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
//only send to wear if Native notifications are turned off // mId allows you to update the notification later on.
if (!sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) { mNotificationManager.notify(Constants.notificationID, builder.build())
// Send to Wear uel.log(Action.CAREPORTAL, Sources.Loop, resourceHelper.gs(R.string.carbsreq, resultAfterConstraints.carbsReq, resultAfterConstraints.carbsReqWithin),
rxBus.send(EventWearInitiateAction("changeRequest")) ValueWithUnit.Gram(resultAfterConstraints.carbsReq),
ValueWithUnit.Minute(resultAfterConstraints.carbsReqWithin))
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(EventWearInitiateAction("changeRequest"))
}
}
} else {
//If carbs were required previously, but are no longer needed, dismiss notifications
if (prevCarbsreq > 0) {
dismissSuggestion()
rxBus.send(EventDismissNotification(Notification.CARBS_REQUIRED))
} }
} }
} 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
if (resultAfterConstraints.isChangeRequested && !commandQueue.bolusInQueue()
&& !commandQueue.bolusInQueue() && !commandQueue.isRunning(Command.CommandType.BOLUS)) {
&& !commandQueue.isRunning(Command.CommandType.BOLUS)) { val waiting = PumpEnactResult(injector)
val waiting = PumpEnactResult(injector) waiting.queued = true
waiting.queued = true if (resultAfterConstraints.tempBasalRequested) lastRun.tbrSetByPump = waiting
if (resultAfterConstraints.tempBasalRequested) lastRun!!.tbrSetByPump = waiting if (resultAfterConstraints.bolusRequested) lastRun.smbSetByPump = waiting
if (resultAfterConstraints.bolusRequested) lastRun!!.smbSetByPump = waiting rxBus.send(EventLoopUpdateGui())
rxBus.send(EventLoopUpdateGui()) fabricPrivacy.logCustom("APSRequest")
fabricPrivacy.logCustom("APSRequest") applyTBRRequest(resultAfterConstraints, profile, object : Callback() {
applyTBRRequest(resultAfterConstraints, profile, object : Callback() { override fun run() {
override fun run() { if (result.enacted || result.success) {
if (result.enacted || result.success) { lastRun.tbrSetByPump = result
lastRun!!.tbrSetByPump = result lastRun.lastTBRRequest = lastRun.lastAPSRun
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun lastRun.lastTBREnact = dateUtil.now()
lastRun!!.lastTBREnact = DateUtil.now() rxBus.send(EventLoopUpdateGui())
rxBus.send(EventLoopUpdateGui()) applySMBRequest(resultAfterConstraints, object : Callback() {
applySMBRequest(resultAfterConstraints, object : Callback() { override fun run() {
override fun run() { // Callback is only called if a bolus was actually requested
// Callback is only called if a bolus was actually requested if (result.enacted || result.success) {
if (result.enacted || result.success) { lastRun.smbSetByPump = result
lastRun!!.smbSetByPump = result lastRun.lastSMBRequest = lastRun.lastAPSRun
lastRun!!.lastSMBRequest = lastRun!!.lastAPSRun lastRun.lastSMBEnact = dateUtil.now()
lastRun!!.lastSMBEnact = DateUtil.now() } else {
} else { Thread {
Thread { SystemClock.sleep(1000)
SystemClock.sleep(1000) invoke("tempBasalFallback", allowNotification, true)
invoke("tempBasalFallback", allowNotification, true) }.start()
}.start() }
rxBus.send(EventLoopUpdateGui())
} }
rxBus.send(EventLoopUpdateGui()) })
} } else {
}) lastRun.tbrSetByPump = result
} else { lastRun.lastTBRRequest = lastRun.lastAPSRun
lastRun!!.tbrSetByPump = result }
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun rxBus.send(EventLoopUpdateGui())
} }
rxBus.send(EventLoopUpdateGui()) })
} } else {
}) lastRun.tbrSetByPump = null
} else { lastRun.smbSetByPump = null
lastRun!!.tbrSetByPump = null }
lastRun!!.smbSetByPump = null } else {
} if (resultAfterConstraints.isChangeRequested && allowNotification) {
} else { val builder = NotificationCompat.Builder(context, CHANNEL_ID)
if (resultAfterConstraints.isChangeRequested && allowNotification) { builder.setSmallIcon(R.drawable.notif_icon)
val builder = NotificationCompat.Builder(context, CHANNEL_ID) .setContentTitle(resourceHelper.gs(R.string.openloop_newsuggestion))
builder.setSmallIcon(R.drawable.notif_icon) .setContentText(resultAfterConstraints.toString())
.setContentTitle(resourceHelper.gs(R.string.openloop_newsuggestion)) .setAutoCancel(true)
.setContentText(resultAfterConstraints.toString()) .setPriority(Notification.IMPORTANCE_HIGH)
.setAutoCancel(true) .setCategory(Notification.CATEGORY_ALARM)
.setPriority(Notification.IMPORTANCE_HIGH) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setCategory(Notification.CATEGORY_ALARM) if (sp.getBoolean(R.string.key_wear_control, false)) {
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) builder.setLocalOnly(true)
if (sp.getBoolean(R.string.key_wear_control, false)) { }
builder.setLocalOnly(true) presentSuggestion(builder)
} else if (allowNotification) {
dismissSuggestion()
} }
presentSuggestion(builder)
} else if (allowNotification) {
dismissSuggestion()
} }
rxBus.send(EventLoopUpdateGui())
} }
rxBus.send(EventLoopUpdateGui())
} finally { } finally {
aapsLogger.debug(LTag.APS, "invoke end") aapsLogger.debug(LTag.APS, "invoke end")
} }
@ -486,21 +502,28 @@ open class LoopPlugin @Inject constructor(
} }
fun acceptChangeRequest() { fun acceptChangeRequest() {
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile() ?: return
val lp = this lastRun?.let { lastRun ->
applyTBRRequest(lastRun!!.constraintsProcessed, profile, object : Callback() { lastRun.constraintsProcessed?.let { constraintsProcessed ->
override fun run() { applyTBRRequest(constraintsProcessed, profile, object : Callback() {
if (result.enacted) { override fun run() {
lastRun!!.tbrSetByPump = result if (result.enacted) {
lastRun!!.lastTBRRequest = lastRun!!.lastAPSRun lastRun.tbrSetByPump = result
lastRun!!.lastTBREnact = DateUtil.now() lastRun.lastTBRRequest = lastRun.lastAPSRun
lastRun!!.lastOpenModeAccept = DateUtil.now() lastRun.lastTBREnact = dateUtil.now()
nsUpload.uploadDeviceStatus(lp, iobCobCalculatorPlugin, profileFunction, activePlugin.activePump, receiverStatusStore, BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION) lastRun.lastOpenModeAccept = dateUtil.now()
sp.incInt(R.string.key_ObjectivesmanualEnacts) buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculator, profileFunction,
} activePlugin.activePump, receiverStatusStore, runningConfiguration,
rxBus.send(EventAcceptOpenLoopChange()) BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
repository.insert(it)
}
sp.incInt(R.string.key_ObjectivesmanualEnacts)
}
rxBus.send(EventAcceptOpenLoopChange())
}
})
} }
}) }
fabricPrivacy.logCustom("AcceptTemp") fabricPrivacy.logCustom("AcceptTemp")
} }
@ -508,8 +531,8 @@ open class LoopPlugin @Inject constructor(
* expect absolute request and allow both absolute and percent response based on pump capabilities * expect absolute request and allow both absolute and percent response based on pump capabilities
* TODO: update pump drivers to support APS request in % * TODO: update pump drivers to support APS request in %
*/ */
private fun applyTBRRequest(request: APSResult?, profile: Profile?, callback: Callback?) { private fun applyTBRRequest(request: APSResult, profile: Profile, callback: Callback?) {
if (!request!!.tempBasalRequested) { if (!request.tempBasalRequested) {
callback?.result(PumpEnactResult(injector).enacted(false).success(true).comment(R.string.nochangerequested))?.run() callback?.result(PumpEnactResult(injector).enacted(false).success(true).comment(R.string.nochangerequested))?.run()
return return
} }
@ -526,44 +549,52 @@ open class LoopPlugin @Inject constructor(
} }
aapsLogger.debug(LTag.APS, "applyAPSRequest: $request") aapsLogger.debug(LTag.APS, "applyAPSRequest: $request")
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
val activeTemp = treatmentsPlugin.getTempBasalFromHistory(now) val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(now)
if (request.usePercent && allowPercentage()) { if (request.usePercent && allowPercentage()) {
if (request.percent == 100 && request.duration == 0) { if (request.percent == 100 && request.duration == 0) {
if (activeTemp != null) { if (activeTemp != null) {
aapsLogger.debug(LTag.APS, "applyAPSRequest: cancelTempBasal()") aapsLogger.debug(LTag.APS, "applyAPSRequest: cancelTempBasal()")
uel.log(Action.CANCEL_TEMP_BASAL, Sources.Loop)
commandQueue.cancelTempBasal(false, callback) commandQueue.cancelTempBasal(false, callback)
} else { } else {
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly") aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
callback?.result(PumpEnactResult(injector).percent(request.percent).duration(0) callback?.result(PumpEnactResult(injector).percent(request.percent).duration(0)
.enacted(false).success(true).comment(R.string.basal_set_correctly))?.run() .enacted(false).success(true).comment(R.string.basal_set_correctly))?.run()
} }
} else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.percentRate) { } else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.convertedToPercent(now, profile)) {
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly") aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
callback?.result(PumpEnactResult(injector).percent(request.percent) callback?.result(PumpEnactResult(injector).percent(request.percent)
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes) .enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
.comment(R.string.let_temp_basal_run))?.run() .comment(R.string.let_temp_basal_run))?.run()
} else { } else {
aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()") aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()")
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile!!, callback) uel.log(Action.TEMP_BASAL, Sources.Loop,
ValueWithUnit.Percent(request.percent),
ValueWithUnit.Minute(request.duration))
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} }
} else { } else {
if (request.rate == 0.0 && request.duration == 0 || abs(request.rate - pump.baseBasalRate) < pump.pumpDescription.basalStep) { if (request.rate == 0.0 && request.duration == 0 || abs(request.rate - pump.baseBasalRate) < pump.pumpDescription.basalStep) {
if (activeTemp != null) { if (activeTemp != null) {
aapsLogger.debug(LTag.APS, "applyAPSRequest: cancelTempBasal()") aapsLogger.debug(LTag.APS, "applyAPSRequest: cancelTempBasal()")
uel.log(Action.CANCEL_TEMP_BASAL, Sources.Loop)
commandQueue.cancelTempBasal(false, callback) commandQueue.cancelTempBasal(false, callback)
} else { } else {
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly") aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
callback?.result(PumpEnactResult(injector).absolute(request.rate).duration(0) callback?.result(PumpEnactResult(injector).absolute(request.rate).duration(0)
.enacted(false).success(true).comment(R.string.basal_set_correctly))?.run() .enacted(false).success(true).comment(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) { } else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(request.rate - activeTemp.convertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) {
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly") aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
callback?.result(PumpEnactResult(injector).absolute(activeTemp.tempBasalConvertedToAbsolute(now, profile)) callback?.result(PumpEnactResult(injector).absolute(activeTemp.convertedToAbsolute(now, profile))
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes) .enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
.comment(R.string.let_temp_basal_run))?.run() .comment(R.string.let_temp_basal_run))?.run()
} else { } else {
aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()") aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()")
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile!!, callback) uel.log(Action.TEMP_BASAL, Sources.Loop,
ValueWithUnit.UnitPerHour(request.rate),
ValueWithUnit.Minute(request.duration))
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
} }
} }
} }
@ -573,7 +604,7 @@ open class LoopPlugin @Inject constructor(
return return
} }
val pump = activePlugin.activePump val pump = activePlugin.activePump
val lastBolusTime = treatmentsPlugin.lastBolusTime val lastBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L
if (lastBolusTime != 0L && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) { if (lastBolusTime != 0L && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval") aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
callback?.result(PumpEnactResult(injector) callback?.result(PumpEnactResult(injector)
@ -595,13 +626,14 @@ open class LoopPlugin @Inject constructor(
// deliver SMB // deliver SMB
val detailedBolusInfo = DetailedBolusInfo() val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.lastBolusTime detailedBolusInfo.lastKnownBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L
detailedBolusInfo.eventType = TherapyEvent.Type.CORRECTION_BOLUS.text detailedBolusInfo.eventType = DetailedBolusInfo.EventType.CORRECTION_BOLUS
detailedBolusInfo.insulin = request.smb detailedBolusInfo.insulin = request.smb
detailedBolusInfo.isSMB = true detailedBolusInfo.bolusType = DetailedBolusInfo.BolusType.SMB
detailedBolusInfo.source = Source.USER detailedBolusInfo.deliverAtTheLatest = request.deliverAt
detailedBolusInfo.deliverAt = request.deliverAt
aapsLogger.debug(LTag.APS, "applyAPSRequest: bolus()") aapsLogger.debug(LTag.APS, "applyAPSRequest: bolus()")
if (request.smb > 0.0)
uel.log(Action.SMB, Sources.Loop, ValueWithUnit.Insulin(detailedBolusInfo.insulin))
commandQueue.bolus(detailedBolusInfo, callback) commandQueue.bolus(detailedBolusInfo, callback)
} }
@ -613,7 +645,7 @@ open class LoopPlugin @Inject constructor(
val pump = activePlugin.activePump val pump = activePlugin.activePump
disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L) disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L)
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
commandQueue.tempBasalAbsolute(0.0, durationInMinutes, true, profile!!, object : Callback() { commandQueue.tempBasalAbsolute(0.0, durationInMinutes, true, profile!!, PumpSync.TemporaryBasalType.EMULATED_PUMP_SUSPEND, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
@ -621,7 +653,7 @@ open class LoopPlugin @Inject constructor(
} }
}) })
} else { } else {
commandQueue.tempBasalPercent(0, durationInMinutes, true, profile!!, object : Callback() { commandQueue.tempBasalPercent(0, durationInMinutes, true, profile!!, PumpSync.TemporaryBasalType.EMULATED_PUMP_SUSPEND, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror) ErrorHelperActivity.runAlarm(context, result.comment, resourceHelper.gs(R.string.tempbasaldeliveryerror), info.nightscout.androidaps.dana.R.raw.boluserror)
@ -629,7 +661,7 @@ open class LoopPlugin @Inject constructor(
} }
}) })
} }
if (pump.pumpDescription.isExtendedBolusCapable && treatmentsPlugin.isInHistoryExtendedBolusInProgress) { if (pump.pumpDescription.isExtendedBolusCapable && iobCobCalculator.getExtendedBolus(dateUtil.now()) != null) {
commandQueue.cancelExtended(object : Callback() { commandQueue.cancelExtended(object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
@ -654,17 +686,16 @@ open class LoopPlugin @Inject constructor(
} }
override fun createOfflineEvent(durationInMinutes: Int) { override fun createOfflineEvent(durationInMinutes: Int) {
disposable += repository.runTransactionForResult(InsertTherapyEventIfNewTransaction( disposable += repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(
timestamp = dateUtil._now(), timestamp = dateUtil.now(),
type = TherapyEvent.Type.APS_OFFLINE, type = TherapyEvent.Type.APS_OFFLINE,
duration = T.mins(durationInMinutes.toLong()).msecs(), duration = T.mins(durationInMinutes.toLong()).msecs(),
enteredBy = "openaps://" + "AndroidAPS", enteredBy = "openaps://" + "AndroidAPS",
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
)).subscribe({ result -> )).subscribe(
result.inserted.forEach { nsUpload.uploadEvent(it) } { result -> result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } },
}, { { aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) }
aapsLogger.error(LTag.BGSOURCE, "Error while saving therapy event", it) )
})
} }
companion object { companion object {

View file

@ -6,6 +6,10 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -15,8 +19,6 @@ import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONException import org.json.JSONException
@ -37,7 +39,7 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
@Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var openHumansUploader: OpenHumansUploader @Inject lateinit var openHumansUploader: OpenHumansUploader
private val mScriptReader: ScriptReader private val mScriptReader: ScriptReader
@ -183,18 +185,15 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
this.profile.put("out_units", "mmol/L") this.profile.put("out_units", "mmol/L")
} }
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
val tb = treatmentsPlugin.getTempBasalFromHistory(now) val tb = iobCobCalculator.getTempBasalIncludingConvertedExtended(now)
currentTemp = JSONObject() currentTemp = JSONObject()
currentTemp.put("temp", "absolute") currentTemp.put("temp", "absolute")
currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0) currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0)
currentTemp.put("rate", tb?.tempBasalConvertedToAbsolute(now, profile) ?: 0.0) currentTemp.put("rate", tb?.convertedToAbsolute(now, profile) ?: 0.0)
// as we have non default temps longer than 30 minutes // as we have non default temps longer than 30 minutes
val tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) if (tb != null) currentTemp.put("minutesrunning", tb.getPassedDurationToTimeInMinutes(now))
if (tempBasal != null) {
currentTemp.put("minutesrunning", tempBasal.realDuration) iobData = iobCobCalculator.convertToJSONArray(iobArray)
}
iobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray)
this.glucoseStatus = JSONObject() this.glucoseStatus = JSONObject()
this.glucoseStatus.put("glucose", glucoseStatus.glucose) this.glucoseStatus.put("glucose", glucoseStatus.glucose)
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) { if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
@ -206,7 +205,6 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
this.glucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta) this.glucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta)
this.mealData = JSONObject() this.mealData = JSONObject()
this.mealData.put("carbs", mealData.carbs) this.mealData.put("carbs", mealData.carbs)
this.mealData.put("boluses", mealData.boluses)
this.mealData.put("mealCOB", mealData.mealCOB) this.mealData.put("mealCOB", mealData.mealCOB)
if (constraintChecker.isAutosensModeEnabled().value()) { if (constraintChecker.isAutosensModeEnabled().value()) {
autosensData.put("ratio", autosensDataRatio) autosensData.put("ratio", autosensDataRatio)

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.aps.openAPSAMA
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.loop.APSResult import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import org.mozilla.javascript.NativeObject import org.mozilla.javascript.NativeObject
@ -14,7 +13,7 @@ class DetermineBasalResultAMA private constructor(injector: HasAndroidInjector)
private var snoozeBG = 0.0 private var snoozeBG = 0.0
internal constructor(injector: HasAndroidInjector, result: NativeObject, j: JSONObject) : this(injector) { internal constructor(injector: HasAndroidInjector, result: NativeObject, j: JSONObject) : this(injector) {
date = DateUtil.now() date = dateUtil.now()
json = j json = j
if (result.containsKey("error")) { if (result.containsKey("error")) {
reason = result["error"].toString() reason = result["error"].toString()

View file

@ -35,6 +35,7 @@ class OpenAPSAMAFragment : DaggerFragment() {
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var openAPSAMAPlugin: OpenAPSAMAPlugin @Inject lateinit var openAPSAMAPlugin: OpenAPSAMAPlugin
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var jsonFormatter: JSONFormatter
private var _binding: OpenapsamaFragmentBinding? = null private var _binding: OpenapsamaFragmentBinding? = null
@ -92,30 +93,30 @@ class OpenAPSAMAFragment : DaggerFragment() {
private fun updateGUI() { private fun updateGUI() {
if (_binding == null) return if (_binding == null) return
openAPSAMAPlugin.lastAPSResult?.let { lastAPSResult -> openAPSAMAPlugin.lastAPSResult?.let { lastAPSResult ->
binding.result.text = JSONFormatter.format(lastAPSResult.json) binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned() binding.request.text = lastAPSResult.toSpanned()
} }
openAPSAMAPlugin.lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS -> openAPSAMAPlugin.lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS ->
binding.glucosestatus.text = JSONFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam) binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam)
binding.currenttemp.text = JSONFormatter.format(determineBasalAdapterAMAJS.currentTempParam) binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterAMAJS.currentTempParam)
try { try {
val iobArray = JSONArray(determineBasalAdapterAMAJS.iobDataParam) val iobArray = JSONArray(determineBasalAdapterAMAJS.iobDataParam)
binding.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) { } catch (e: JSONException) {
aapsLogger.error(LTag.APS, "Unhandled exception", e) aapsLogger.error(LTag.APS, "Unhandled exception", e)
@Suppress("SetTextI18n") @Suppress("SetTextI18n")
binding.iobdata.text = "JSONException see log for details" binding.iobdata.text = "JSONException see log for details"
} }
binding.profile.text = JSONFormatter.format(determineBasalAdapterAMAJS.profileParam) binding.profile.text = jsonFormatter.format(determineBasalAdapterAMAJS.profileParam)
binding.mealdata.text = JSONFormatter.format(determineBasalAdapterAMAJS.mealDataParam) binding.mealdata.text = jsonFormatter.format(determineBasalAdapterAMAJS.mealDataParam)
binding.scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug binding.scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug
} }
if (openAPSAMAPlugin.lastAPSRun != 0L) { if (openAPSAMAPlugin.lastAPSRun != 0L) {
binding.lastrun.text = dateUtil.dateAndTimeString(openAPSAMAPlugin.lastAPSRun) binding.lastrun.text = dateUtil.dateAndTimeString(openAPSAMAPlugin.lastAPSRun)
} }
openAPSAMAPlugin.lastAutosensResult.let { openAPSAMAPlugin.lastAutosensResult.let {
binding.autosensdata.text = JSONFormatter.format(it.json()) binding.autosensdata.text = jsonFormatter.format(it.json())
} }
} }

View file

@ -15,15 +15,13 @@ import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.extensions.target import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONException import org.json.JSONException
import javax.inject.Inject import javax.inject.Inject
@ -38,9 +36,8 @@ open class OpenAPSAMAPlugin @Inject constructor(
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val context: Context, private val context: Context,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePlugin,
private val treatmentsPlugin: TreatmentsInterface, private val iobCobCalculator: IobCobCalculator,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
private val profiler: Profiler, private val profiler: Profiler,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
@ -56,7 +53,7 @@ open class OpenAPSAMAPlugin @Inject constructor(
.preferencesId(R.xml.pref_openapsama) .preferencesId(R.xml.pref_openapsama)
.description(R.string.description_ama), .description(R.string.description_ama),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), APSInterface { ), APS {
// last values // last values
override var lastAPSRun: Long = 0 override var lastAPSRun: Long = 0
@ -107,10 +104,10 @@ open class OpenAPSAMAPlugin @Inject constructor(
}.value() }.value()
var start = System.currentTimeMillis() var start = System.currentTimeMillis()
var startPart = System.currentTimeMillis() var startPart = System.currentTimeMillis()
val iobArray = iobCobCalculatorPlugin.calculateIobArrayInDia(profile) val iobArray = iobCobCalculator.calculateIobArrayInDia(profile)
profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart) profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart)
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
val mealData = iobCobCalculatorPlugin.mealData val mealData = iobCobCalculator.getMealDataWithWaitingForCalculationFinish()
profiler.log(LTag.APS, "getMealData()", startPart) profiler.log(LTag.APS, "getMealData()", startPart)
val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint -> val maxIob = constraintChecker.getMaxIOBAllowed().also { maxIOBAllowedConstraint ->
inputConstraints.copyReasons(maxIOBAllowedConstraint) inputConstraints.copyReasons(maxIOBAllowedConstraint)
@ -119,7 +116,7 @@ open class OpenAPSAMAPlugin @Inject constructor(
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble()) var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
var isTempTarget = false var isTempTarget = false
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) { if (tempTarget is ValueWrapper.Existing) {
isTempTarget = true isTempTarget = true
minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()) minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
@ -133,7 +130,7 @@ open class OpenAPSAMAPlugin @Inject constructor(
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) { if (constraintChecker.isAutosensModeEnabled().value()) {
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin") val autosensData = iobCobCalculator.getLastAutosensDataWithWaitForCalculationFinish("OpenAPSPlugin")
if (autosensData == null) { if (autosensData == null) {
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata))) rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata)))
return return
@ -163,10 +160,10 @@ open class OpenAPSAMAPlugin @Inject constructor(
lastAPSResult = null lastAPSResult = null
lastAPSRun = 0 lastAPSRun = 0
} else { } else {
if (determineBasalResultAMA.rate == 0.0 && determineBasalResultAMA.duration == 0 && !treatmentsPlugin.isTempBasalInProgress) determineBasalResultAMA.tempBasalRequested = false if (determineBasalResultAMA.rate == 0.0 && determineBasalResultAMA.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultAMA.tempBasalRequested = false
determineBasalResultAMA.iob = iobArray[0] determineBasalResultAMA.iob = iobArray[0]
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
determineBasalResultAMA.json?.put("timestamp", DateUtil.toISOString(now)) determineBasalResultAMA.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultAMA.inputConstraints = inputConstraints determineBasalResultAMA.inputConstraints = inputConstraints
lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS
lastAPSResult = determineBasalResultAMA lastAPSResult = determineBasalResultAMA

View file

@ -6,7 +6,8 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.MealData import info.nightscout.androidaps.data.MealData
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -15,9 +16,10 @@ import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.extensions.convertedToAbsolute
import info.nightscout.androidaps.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONArray import org.json.JSONArray
@ -37,8 +39,8 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var activePluginProvider: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var openHumansUploader: OpenHumansUploader @Inject lateinit var openHumansUploader: OpenHumansUploader
private var profile = JSONObject() private var profile = JSONObject()
@ -173,7 +175,7 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
advancedFiltering: Boolean, advancedFiltering: Boolean,
isSaveCgmSource: Boolean isSaveCgmSource: Boolean
) { ) {
val pump = activePluginProvider.activePump val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep val pumpBolusStep = pump.pumpDescription.bolusStep
this.profile.put("max_iob", maxIob) this.profile.put("max_iob", maxIob)
//mProfile.put("dia", profile.getDia()); //mProfile.put("dia", profile.getDia());
@ -227,17 +229,14 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
this.profile.put("out_units", "mmol/L") this.profile.put("out_units", "mmol/L")
} }
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
val tb = treatmentsPlugin.getTempBasalFromHistory(now) val tb = iobCobCalculator.getTempBasalIncludingConvertedExtended(now)
currentTemp.put("temp", "absolute") currentTemp.put("temp", "absolute")
currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0) currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0)
currentTemp.put("rate", tb?.tempBasalConvertedToAbsolute(now, profile) ?: 0.0) currentTemp.put("rate", tb?.convertedToAbsolute(now, profile) ?: 0.0)
// as we have non default temps longer than 30 mintues // as we have non default temps longer than 30 mintues
val tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) if (tb != null) currentTemp.put("minutesrunning", tb.getPassedDurationToTimeInMinutes(now))
if (tempBasal != null) {
currentTemp.put("minutesrunning", tempBasal.realDuration) iobData = iobCobCalculator.convertToJSONArray(iobArray)
}
iobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray)
mGlucoseStatus.put("glucose", glucoseStatus.glucose) mGlucoseStatus.put("glucose", glucoseStatus.glucose)
mGlucoseStatus.put("noise", glucoseStatus.noise) mGlucoseStatus.put("noise", glucoseStatus.noise)
if (sp.getBoolean(R.string.key_always_use_shortavg, false)) { if (sp.getBoolean(R.string.key_always_use_shortavg, false)) {
@ -249,7 +248,6 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta) mGlucoseStatus.put("long_avgdelta", glucoseStatus.longAvgDelta)
mGlucoseStatus.put("date", glucoseStatus.date) mGlucoseStatus.put("date", glucoseStatus.date)
this.mealData.put("carbs", mealData.carbs) this.mealData.put("carbs", mealData.carbs)
this.mealData.put("boluses", mealData.boluses)
this.mealData.put("mealCOB", mealData.mealCOB) this.mealData.put("mealCOB", mealData.mealCOB)
this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation) this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation)
this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation) this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation)

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.aps.openAPSSMB
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.loop.APSResult import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.utils.DateUtil
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
@ -13,7 +12,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
private var snoozeBG = 0.0 private var snoozeBG = 0.0
internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) { internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) {
date = DateUtil.now() date = dateUtil.now()
json = result json = result
try { try {
if (result.has("error")) { if (result.has("error")) {
@ -47,7 +46,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
if (result.has("deliverAt")) { if (result.has("deliverAt")) {
val date = result.getString("deliverAt") val date = result.getString("deliverAt")
try { try {
deliverAt = DateUtil.fromISODateString(date).time deliverAt = dateUtil.fromISODateString(date)
} catch (e: Exception) { } catch (e: Exception) {
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e) aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
} }

View file

@ -36,6 +36,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin @Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var jsonFormatter: JSONFormatter
private var _binding: OpenapsamaFragmentBinding? = null private var _binding: OpenapsamaFragmentBinding? = null
@ -92,23 +93,23 @@ class OpenAPSSMBFragment : DaggerFragment() {
fun updateGUI() { fun updateGUI() {
if (_binding == null) return if (_binding == null) return
openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult -> openAPSSMBPlugin.lastAPSResult?.let { lastAPSResult ->
binding.result.text = JSONFormatter.format(lastAPSResult.json) binding.result.text = jsonFormatter.format(lastAPSResult.json)
binding.request.text = lastAPSResult.toSpanned() binding.request.text = lastAPSResult.toSpanned()
} }
openAPSSMBPlugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS -> openAPSSMBPlugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS ->
binding.glucosestatus.text = JSONFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam) binding.glucosestatus.text = jsonFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam)
binding.currenttemp.text = JSONFormatter.format(determineBasalAdapterSMBJS.currentTempParam) binding.currenttemp.text = jsonFormatter.format(determineBasalAdapterSMBJS.currentTempParam)
try { try {
val iobArray = JSONArray(determineBasalAdapterSMBJS.iobDataParam) val iobArray = JSONArray(determineBasalAdapterSMBJS.iobDataParam)
binding.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) { } catch (e: JSONException) {
aapsLogger.error(LTag.APS, "Unhandled exception", e) aapsLogger.error(LTag.APS, "Unhandled exception", e)
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
binding.iobdata.text = "JSONException see log for details" binding.iobdata.text = "JSONException see log for details"
} }
binding.profile.text = JSONFormatter.format(determineBasalAdapterSMBJS.profileParam) binding.profile.text = jsonFormatter.format(determineBasalAdapterSMBJS.profileParam)
binding.mealdata.text = JSONFormatter.format(determineBasalAdapterSMBJS.mealDataParam) binding.mealdata.text = jsonFormatter.format(determineBasalAdapterSMBJS.mealDataParam)
binding.scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug binding.scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug
openAPSSMBPlugin.lastAPSResult?.inputConstraints?.let { openAPSSMBPlugin.lastAPSResult?.inputConstraints?.let {
binding.constraints.text = it.getReasons(aapsLogger) binding.constraints.text = it.getReasons(aapsLogger)
@ -118,7 +119,7 @@ class OpenAPSSMBFragment : DaggerFragment() {
binding.lastrun.text = dateUtil.dateAndTimeString(openAPSSMBPlugin.lastAPSRun) binding.lastrun.text = dateUtil.dateAndTimeString(openAPSSMBPlugin.lastAPSRun)
} }
openAPSSMBPlugin.lastAutosensResult.let { openAPSSMBPlugin.lastAutosensResult.let {
binding.autosensdata.text = JSONFormatter.format(it.json()) binding.autosensdata.text = jsonFormatter.format(it.json())
} }
} }

View file

@ -17,14 +17,12 @@ import info.nightscout.androidaps.plugins.aps.loop.ScriptReader
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.extensions.target import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
@ -39,9 +37,8 @@ open class OpenAPSSMBPlugin @Inject constructor(
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val context: Context, private val context: Context,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePlugin,
private val treatmentsPlugin: TreatmentsInterface, private val iobCobCalculator: IobCobCalculator,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
private val profiler: Profiler, private val profiler: Profiler,
private val sp: SP, private val sp: SP,
@ -58,7 +55,7 @@ open class OpenAPSSMBPlugin @Inject constructor(
.description(R.string.description_smb) .description(R.string.description_smb)
.setDefault(), .setDefault(),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), APSInterface, ConstraintsInterface { ), APS, Constraints {
// last values // last values
override var lastAPSRun: Long = 0 override var lastAPSRun: Long = 0
@ -125,7 +122,7 @@ open class OpenAPSSMBPlugin @Inject constructor(
var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble()) var maxBg = hardLimits.verifyHardLimits(Round.roundTo(profile.targetHighMgdl, 0.1), R.string.profile_high_target, HardLimits.VERY_HARD_LIMIT_MAX_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_MAX_BG[1].toDouble())
var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble()) var targetBg = hardLimits.verifyHardLimits(profile.targetMgdl, R.string.temp_target_value, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble())
var isTempTarget = false var isTempTarget = false
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) { if (tempTarget is ValueWrapper.Existing) {
isTempTarget = true isTempTarget = true
minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble()) minBg = hardLimits.verifyHardLimits(tempTarget.value.lowTarget, R.string.temp_target_low_target, HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1].toDouble())
@ -139,7 +136,7 @@ open class OpenAPSSMBPlugin @Inject constructor(
if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return if (!hardLimits.checkOnlyHardLimits(pump.baseBasalRate, R.string.current_basal_value, 0.01, hardLimits.maxBasal())) return
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
if (constraintChecker.isAutosensModeEnabled().value()) { if (constraintChecker.isAutosensModeEnabled().value()) {
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("OpenAPSPlugin") val autosensData = iobCobCalculator.getLastAutosensDataWithWaitForCalculationFinish("OpenAPSPlugin")
if (autosensData == null) { if (autosensData == null) {
rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata))) rxBus.send(EventOpenAPSUpdateResultGui(resourceHelper.gs(R.string.openaps_noasdata)))
return return
@ -148,7 +145,7 @@ open class OpenAPSSMBPlugin @Inject constructor(
} else { } else {
lastAutosensResult.sensResult = "autosens disabled" lastAutosensResult.sensResult = "autosens disabled"
} }
val iobArray = iobCobCalculatorPlugin.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget) val iobArray = iobCobCalculator.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart) profiler.log(LTag.APS, "calculateIobArrayInDia()", startPart)
startPart = System.currentTimeMillis() startPart = System.currentTimeMillis()
val smbAllowed = Constraint(!tempBasalFallback).also { val smbAllowed = Constraint(!tempBasalFallback).also {
@ -172,7 +169,7 @@ open class OpenAPSSMBPlugin @Inject constructor(
activePlugin.activePump.baseBasalRate, activePlugin.activePump.baseBasalRate,
iobArray, iobArray,
glucoseStatus, glucoseStatus,
iobCobCalculatorPlugin.mealData, iobCobCalculator.getMealDataWithWaitingForCalculationFinish(),
lastAutosensResult.ratio, lastAutosensResult.ratio,
isTempTarget, isTempTarget,
smbAllowed.value(), smbAllowed.value(),
@ -190,9 +187,9 @@ open class OpenAPSSMBPlugin @Inject constructor(
} else { } else {
// TODO still needed with oref1? // TODO still needed with oref1?
// Fix bug determine basal // Fix bug determine basal
if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && !treatmentsPlugin.isTempBasalInProgress) determineBasalResultSMB.tempBasalRequested = false if (determineBasalResultSMB.rate == 0.0 && determineBasalResultSMB.duration == 0 && iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) == null) determineBasalResultSMB.tempBasalRequested = false
determineBasalResultSMB.iob = iobArray[0] determineBasalResultSMB.iob = iobArray[0]
determineBasalResultSMB.json?.put("timestamp", DateUtil.toISOString(now)) determineBasalResultSMB.json?.put("timestamp", dateUtil.toISOString(now))
determineBasalResultSMB.inputConstraints = inputConstraints determineBasalResultSMB.inputConstraints = inputConstraints
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS
lastAPSResult = determineBasalResultSMB lastAPSResult = determineBasalResultSMB

View file

@ -9,7 +9,7 @@ import android.widget.*
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.PreferencesActivity import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.databinding.ConfigbuilderFragmentBinding import info.nightscout.androidaps.databinding.ConfigbuilderFragmentBinding
@ -19,7 +19,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.plusAssign
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -34,7 +34,7 @@ class ConfigBuilderFragment : DaggerFragment() {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin @Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var protectionCheck: ProtectionCheck @Inject lateinit var protectionCheck: ProtectionCheck
@Inject lateinit var config: Config @Inject lateinit var config: Config
@ -101,18 +101,18 @@ class ConfigBuilderFragment : DaggerFragment() {
private fun updateGUI() { private fun updateGUI() {
binding.categories.removeAllViews() binding.categories.removeAllViews()
if (!config.NSCLIENT) { if (!config.NSCLIENT) {
createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, activePlugin.getSpecificPluginsVisibleInListByInterface(ProfileInterface::class.java, PluginType.PROFILE)) createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, activePlugin.getSpecificPluginsVisibleInList(PluginType.PROFILE))
} }
createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, activePlugin.getSpecificPluginsVisibleInListByInterface(InsulinInterface::class.java, PluginType.INSULIN)) createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, activePlugin.getSpecificPluginsVisibleInList(PluginType.INSULIN))
if (!config.NSCLIENT) { if (!config.NSCLIENT) {
createViewsForPlugins(R.string.configbuilder_bgsource, R.string.configbuilder_bgsource_description, PluginType.BGSOURCE, activePlugin.getSpecificPluginsVisibleInListByInterface(BgSourceInterface::class.java, PluginType.BGSOURCE)) createViewsForPlugins(R.string.configbuilder_bgsource, R.string.configbuilder_bgsource_description, PluginType.BGSOURCE, activePlugin.getSpecificPluginsVisibleInList(PluginType.BGSOURCE))
createViewsForPlugins(R.string.configbuilder_pump, R.string.configbuilder_pump_description, PluginType.PUMP, activePlugin.getSpecificPluginsVisibleInList(PluginType.PUMP)) createViewsForPlugins(R.string.configbuilder_pump, R.string.configbuilder_pump_description, PluginType.PUMP, activePlugin.getSpecificPluginsVisibleInList(PluginType.PUMP))
} }
createViewsForPlugins(R.string.configbuilder_sensitivity, R.string.configbuilder_sensitivity_description, PluginType.SENSITIVITY, activePlugin.getSpecificPluginsVisibleInListByInterface(SensitivityInterface::class.java, PluginType.SENSITIVITY)) createViewsForPlugins(R.string.configbuilder_sensitivity, R.string.configbuilder_sensitivity_description, PluginType.SENSITIVITY, activePlugin.getSpecificPluginsVisibleInList(PluginType.SENSITIVITY))
if (config.APS) { if (config.APS) {
createViewsForPlugins(R.string.configbuilder_aps, R.string.configbuilder_aps_description, PluginType.APS, activePlugin.getSpecificPluginsVisibleInList(PluginType.APS)) createViewsForPlugins(R.string.configbuilder_aps, R.string.configbuilder_aps_description, PluginType.APS, activePlugin.getSpecificPluginsVisibleInList(PluginType.APS))
createViewsForPlugins(R.string.configbuilder_loop, R.string.configbuilder_loop_description, PluginType.LOOP, activePlugin.getSpecificPluginsVisibleInList(PluginType.LOOP)) createViewsForPlugins(R.string.configbuilder_loop, R.string.configbuilder_loop_description, PluginType.LOOP, activePlugin.getSpecificPluginsVisibleInList(PluginType.LOOP))
createViewsForPlugins(R.string.constraints, R.string.configbuilder_constraints_description, PluginType.CONSTRAINTS, activePlugin.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface::class.java, PluginType.CONSTRAINTS)) createViewsForPlugins(R.string.constraints, R.string.configbuilder_constraints_description, PluginType.CONSTRAINTS, activePlugin.getSpecificPluginsVisibleInList(PluginType.CONSTRAINTS))
} }
createViewsForPlugins(R.string.configbuilder_treatments, R.string.configbuilder_treatments_description, PluginType.TREATMENT, activePlugin.getSpecificPluginsVisibleInList(PluginType.TREATMENT)) createViewsForPlugins(R.string.configbuilder_treatments, R.string.configbuilder_treatments_description, PluginType.TREATMENT, activePlugin.getSpecificPluginsVisibleInList(PluginType.TREATMENT))
createViewsForPlugins(R.string.configbuilder_general, R.string.configbuilder_general_description, PluginType.GENERAL, activePlugin.getSpecificPluginsVisibleInList(PluginType.GENERAL)) createViewsForPlugins(R.string.configbuilder_general, R.string.configbuilder_general_description, PluginType.GENERAL, activePlugin.getSpecificPluginsVisibleInList(PluginType.GENERAL))

View file

@ -3,7 +3,9 @@ package info.nightscout.androidaps.plugins.configBuilder
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.events.EventAppInitialized import info.nightscout.androidaps.events.EventAppInitialized
import info.nightscout.androidaps.events.EventConfigBuilderChange import info.nightscout.androidaps.events.EventConfigBuilderChange
import info.nightscout.androidaps.events.EventRebuildTabs import info.nightscout.androidaps.events.EventRebuildTabs
@ -27,8 +29,9 @@ class ConfigBuilderPlugin @Inject constructor(
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val sp: SP, private val sp: SP,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePlugin,
private val uel: UserEntryLogger private val uel: UserEntryLogger,
private val pumpSync: PumpSync
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.GENERAL) .mainType(PluginType.GENERAL)
.fragmentClass(ConfigBuilderFragment::class.java.name) .fragmentClass(ConfigBuilderFragment::class.java.name)
@ -40,9 +43,9 @@ class ConfigBuilderPlugin @Inject constructor(
.shortName(R.string.configbuilder_shortname) .shortName(R.string.configbuilder_shortname)
.description(R.string.description_config_builder), .description(R.string.description_config_builder),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConfigBuilderInterface { ), ConfigBuilder {
fun initialize() { override fun initialize() {
(activePlugin as PluginStore).loadDefaults() (activePlugin as PluginStore).loadDefaults()
loadSettings() loadSettings()
setAlwaysEnabledPluginsEnabled() setAlwaysEnabledPluginsEnabled()
@ -66,7 +69,7 @@ class ConfigBuilderPlugin @Inject constructor(
if (p.pluginDescription.alwaysEnabled && p.pluginDescription.neverVisible) continue if (p.pluginDescription.alwaysEnabled && p.pluginDescription.neverVisible) continue
savePref(p, type, true) savePref(p, type, true)
if (type == PluginType.PUMP) { if (type == PluginType.PUMP) {
if (p is ProfileInterface) { // Store state of optional Profile interface if (p is ProfileSource) { // Store state of optional Profile interface
savePref(p, PluginType.PROFILE, false) savePref(p, PluginType.PROFILE, false)
} }
} }
@ -90,7 +93,7 @@ class ConfigBuilderPlugin @Inject constructor(
val type = p.getType() val type = p.getType()
loadPref(p, type, true) loadPref(p, type, true)
if (p.getType() == PluginType.PUMP) { if (p.getType() == PluginType.PUMP) {
if (p is ProfileInterface) { if (p is ProfileSource) {
loadPref(p, PluginType.PROFILE, false) loadPref(p, PluginType.PROFILE, false)
} }
} }
@ -139,13 +142,16 @@ class ConfigBuilderPlugin @Inject constructor(
val allowHardwarePump = sp.getBoolean("allow_hardware_pump", false) val allowHardwarePump = sp.getBoolean("allow_hardware_pump", false)
if (allowHardwarePump || activity == null) { if (allowHardwarePump || activity == null) {
performPluginSwitch(changedPlugin, newState, type) performPluginSwitch(changedPlugin, newState, type)
pumpSync.connectNewPump()
} else { } else {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.allow_hardware_pump_text), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.allow_hardware_pump_text), {
performPluginSwitch(changedPlugin, newState, type) performPluginSwitch(changedPlugin, newState, type)
pumpSync.connectNewPump()
sp.putBoolean("allow_hardware_pump", true) sp.putBoolean("allow_hardware_pump", true)
uel.log(Action.HW_PUMP_ALLOWED) uel.log(Action.HW_PUMP_ALLOWED, Sources.ConfigBuilder, resourceHelper.gs(changedPlugin.pluginDescription.pluginName),
ValueWithUnit.SimpleString(resourceHelper.gsNotLocalised(changedPlugin.pluginDescription.pluginName)))
aapsLogger.debug(LTag.PUMP, "First time HW pump allowed!") aapsLogger.debug(LTag.PUMP, "First time HW pump allowed!")
}, Runnable { }, {
rxBus.send(EventConfigBuilderUpdateGui()) rxBus.send(EventConfigBuilderUpdateGui())
aapsLogger.debug(LTag.PUMP, "User does not allow switching to HW pump!") aapsLogger.debug(LTag.PUMP, "User does not allow switching to HW pump!")
}) })
@ -153,6 +159,14 @@ class ConfigBuilderPlugin @Inject constructor(
} }
override fun performPluginSwitch(changedPlugin: PluginBase, enabled: Boolean, type: PluginType) { override fun performPluginSwitch(changedPlugin: PluginBase, enabled: Boolean, type: PluginType) {
if(enabled && !changedPlugin.isEnabled()) {
uel.log(Action.PLUGIN_ENABLED, Sources.ConfigBuilder, resourceHelper.gs(changedPlugin.pluginDescription.pluginName),
ValueWithUnit.SimpleString(resourceHelper.gsNotLocalised(changedPlugin.pluginDescription.pluginName)))
}
else if(!enabled) {
uel.log(Action.PLUGIN_DISABLED, Sources.ConfigBuilder, resourceHelper.gs(changedPlugin.pluginDescription.pluginName),
ValueWithUnit.SimpleString(resourceHelper.gsNotLocalised(changedPlugin.pluginDescription.pluginName)))
}
changedPlugin.setPluginEnabled(type, enabled) changedPlugin.setPluginEnabled(type, enabled)
changedPlugin.setFragmentVisible(type, enabled) changedPlugin.setFragmentVisible(type, enabled)
processOnEnabledCategoryChanged(changedPlugin, type) processOnEnabledCategoryChanged(changedPlugin, type)
@ -166,13 +180,13 @@ class ConfigBuilderPlugin @Inject constructor(
fun processOnEnabledCategoryChanged(changedPlugin: PluginBase, type: PluginType?) { fun processOnEnabledCategoryChanged(changedPlugin: PluginBase, type: PluginType?) {
var pluginsInCategory: ArrayList<PluginBase>? = null var pluginsInCategory: ArrayList<PluginBase>? = null
when (type) { when (type) {
PluginType.INSULIN -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(InsulinInterface::class.java) PluginType.INSULIN -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Insulin::class.java)
PluginType.SENSITIVITY -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(SensitivityInterface::class.java) PluginType.SENSITIVITY -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Sensitivity::class.java)
PluginType.APS -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(APSInterface::class.java) PluginType.APS -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(APS::class.java)
PluginType.PROFILE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(ProfileInterface::class.java) PluginType.PROFILE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(ProfileSource::class.java)
PluginType.BGSOURCE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(BgSourceInterface::class.java) PluginType.BGSOURCE -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(BgSource::class.java)
PluginType.TREATMENT -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(TreatmentsInterface::class.java) PluginType.TREATMENT -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(TreatmentsInterface::class.java)
PluginType.PUMP -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(PumpInterface::class.java) PluginType.PUMP -> pluginsInCategory = activePlugin.getSpecificPluginsListByInterface(Pump::class.java)
else -> { else -> {
} }

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps.plugins.configBuilder package info.nightscout.androidaps.plugins.configBuilder
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -11,23 +11,23 @@ import javax.inject.Singleton
class PluginStore @Inject constructor( class PluginStore @Inject constructor(
private val aapsLogger: AAPSLogger, private val aapsLogger: AAPSLogger,
private val config: Config private val config: Config
) : ActivePluginProvider { ) : ActivePlugin {
lateinit var plugins: List<@JvmSuppressWildcards PluginBase> lateinit var plugins: List<@JvmSuppressWildcards PluginBase>
private var activeBgSourceStore: BgSourceInterface? = null private var activeBgSourceStore: BgSource? = null
private var activePumpStore: PumpInterface? = null private var activePumpStore: Pump? = null
private var activeProfile: ProfileInterface? = null private var activeProfile: ProfileSource? = null
private var activeAPSStore: APSInterface? = null private var activeAPSStore: APS? = null
private var activeInsulinStore: InsulinInterface? = null private var activeInsulinStore: Insulin? = null
private var activeSensitivityStore: SensitivityInterface? = null private var activeSensitivityStore: Sensitivity? = null
private var activeTreatmentsStore: TreatmentsInterface? = null private var activeTreatmentsStore: TreatmentsInterface? = null
fun loadDefaults() { fun loadDefaults() {
verifySelectionInCategories() verifySelectionInCategories()
} }
fun getDefaultPlugin(type: PluginType): PluginBase { private fun getDefaultPlugin(type: PluginType): PluginBase {
for (p in plugins) for (p in plugins)
if (p.getType() == type && p.isDefault()) return p if (p.getType() == type && p.isDefault()) return p
throw IllegalStateException("Default plugin not found") throw IllegalStateException("Default plugin not found")
@ -41,14 +41,6 @@ class PluginStore @Inject constructor(
return newList return newList
} }
override fun getSpecificPluginsVisibleInList(type: PluginType): ArrayList<PluginBase> {
val newList = ArrayList<PluginBase>()
for (p in plugins) {
if (p.getType() == type) if (p.showInList(type)) newList.add(p)
}
return newList
}
override fun getSpecificPluginsListByInterface(interfaceClass: Class<*>): ArrayList<PluginBase> { override fun getSpecificPluginsListByInterface(interfaceClass: Class<*>): ArrayList<PluginBase> {
val newList = ArrayList<PluginBase>() val newList = ArrayList<PluginBase>()
for (p in plugins) { for (p in plugins) {
@ -57,10 +49,10 @@ class PluginStore @Inject constructor(
return newList return newList
} }
override fun getSpecificPluginsVisibleInListByInterface(interfaceClass: Class<*>, type: PluginType): ArrayList<PluginBase> { override fun getSpecificPluginsVisibleInList(type: PluginType): ArrayList<PluginBase> {
val newList = ArrayList<PluginBase>() val newList = ArrayList<PluginBase>()
for (p in plugins) { for (p in plugins) {
if (p.javaClass != ConfigBuilderPlugin::class.java && interfaceClass.isAssignableFrom(p.javaClass)) if (p.showInList(type)) newList.add(p) if (p.getType() == type) if (p.showInList(type)) newList.add(p)
} }
return newList return newList
} }
@ -71,64 +63,64 @@ class PluginStore @Inject constructor(
// PluginType.APS // PluginType.APS
if (!config.NSCLIENT && !config.PUMPCONTROL) { if (!config.NSCLIENT && !config.PUMPCONTROL) {
pluginsInCategory = getSpecificPluginsList(PluginType.APS) pluginsInCategory = getSpecificPluginsList(PluginType.APS)
activeAPSStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.APS) as APSInterface? activeAPSStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.APS) as APS?
if (activeAPSStore == null) { if (activeAPSStore == null) {
activeAPSStore = getDefaultPlugin(PluginType.APS) as APSInterface activeAPSStore = getDefaultPlugin(PluginType.APS) as APS
(activeAPSStore as PluginBase).setPluginEnabled(PluginType.APS, true) (activeAPSStore as PluginBase).setPluginEnabled(PluginType.APS, true)
aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting APSInterface") aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting APSInterface")
} }
setFragmentVisiblities((activeAPSStore as PluginBase).name, pluginsInCategory, PluginType.APS) setFragmentVisibilities((activeAPSStore as PluginBase).name, pluginsInCategory, PluginType.APS)
} }
// PluginType.INSULIN // PluginType.INSULIN
pluginsInCategory = getSpecificPluginsList(PluginType.INSULIN) pluginsInCategory = getSpecificPluginsList(PluginType.INSULIN)
activeInsulinStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.INSULIN) as InsulinInterface? activeInsulinStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.INSULIN) as Insulin?
if (activeInsulinStore == null) { if (activeInsulinStore == null) {
activeInsulinStore = getDefaultPlugin(PluginType.INSULIN) as InsulinInterface activeInsulinStore = getDefaultPlugin(PluginType.INSULIN) as Insulin
(activeInsulinStore as PluginBase).setPluginEnabled(PluginType.INSULIN, true) (activeInsulinStore as PluginBase).setPluginEnabled(PluginType.INSULIN, true)
aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting InsulinInterface") aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting InsulinInterface")
} }
setFragmentVisiblities((activeInsulinStore as PluginBase).name, pluginsInCategory, PluginType.INSULIN) setFragmentVisibilities((activeInsulinStore as PluginBase).name, pluginsInCategory, PluginType.INSULIN)
// PluginType.SENSITIVITY // PluginType.SENSITIVITY
pluginsInCategory = getSpecificPluginsList(PluginType.SENSITIVITY) pluginsInCategory = getSpecificPluginsList(PluginType.SENSITIVITY)
activeSensitivityStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.SENSITIVITY) as SensitivityInterface? activeSensitivityStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.SENSITIVITY) as Sensitivity?
if (activeSensitivityStore == null) { if (activeSensitivityStore == null) {
activeSensitivityStore = getDefaultPlugin(PluginType.SENSITIVITY) as SensitivityInterface activeSensitivityStore = getDefaultPlugin(PluginType.SENSITIVITY) as Sensitivity
(activeSensitivityStore as PluginBase).setPluginEnabled(PluginType.SENSITIVITY, true) (activeSensitivityStore as PluginBase).setPluginEnabled(PluginType.SENSITIVITY, true)
aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting SensitivityInterface") aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting SensitivityInterface")
} }
setFragmentVisiblities((activeSensitivityStore as PluginBase).name, pluginsInCategory, PluginType.SENSITIVITY) setFragmentVisibilities((activeSensitivityStore as PluginBase).name, pluginsInCategory, PluginType.SENSITIVITY)
// PluginType.PROFILE // PluginType.PROFILE
pluginsInCategory = getSpecificPluginsList(PluginType.PROFILE) pluginsInCategory = getSpecificPluginsList(PluginType.PROFILE)
activeProfile = getTheOneEnabledInArray(pluginsInCategory, PluginType.PROFILE) as ProfileInterface? activeProfile = getTheOneEnabledInArray(pluginsInCategory, PluginType.PROFILE) as ProfileSource?
if (activeProfile == null) { if (activeProfile == null) {
activeProfile = getDefaultPlugin(PluginType.PROFILE) as ProfileInterface activeProfile = getDefaultPlugin(PluginType.PROFILE) as ProfileSource
(activeProfile as PluginBase).setPluginEnabled(PluginType.PROFILE, true) (activeProfile as PluginBase).setPluginEnabled(PluginType.PROFILE, true)
aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting ProfileInterface") aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting ProfileInterface")
} }
setFragmentVisiblities((activeProfile as PluginBase).name, pluginsInCategory, PluginType.PROFILE) setFragmentVisibilities((activeProfile as PluginBase).name, pluginsInCategory, PluginType.PROFILE)
// PluginType.BGSOURCE // PluginType.BGSOURCE
pluginsInCategory = getSpecificPluginsList(PluginType.BGSOURCE) pluginsInCategory = getSpecificPluginsList(PluginType.BGSOURCE)
activeBgSourceStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.BGSOURCE) as BgSourceInterface? activeBgSourceStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.BGSOURCE) as BgSource?
if (activeBgSourceStore == null) { if (activeBgSourceStore == null) {
activeBgSourceStore = getDefaultPlugin(PluginType.BGSOURCE) as BgSourceInterface activeBgSourceStore = getDefaultPlugin(PluginType.BGSOURCE) as BgSource
(activeBgSourceStore as PluginBase).setPluginEnabled(PluginType.BGSOURCE, true) (activeBgSourceStore as PluginBase).setPluginEnabled(PluginType.BGSOURCE, true)
aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting BgInterface") aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting BgInterface")
} }
setFragmentVisiblities((activeBgSourceStore as PluginBase).name, pluginsInCategory, PluginType.BGSOURCE) setFragmentVisibilities((activeBgSourceStore as PluginBase).name, pluginsInCategory, PluginType.PUMP)
// PluginType.PUMP // PluginType.PUMP
pluginsInCategory = getSpecificPluginsList(PluginType.PUMP) pluginsInCategory = getSpecificPluginsList(PluginType.PUMP)
activePumpStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.PUMP) as PumpInterface? activePumpStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.PUMP) as Pump?
if (activePumpStore == null) { if (activePumpStore == null) {
activePumpStore = getDefaultPlugin(PluginType.PUMP) as PumpInterface activePumpStore = getDefaultPlugin(PluginType.PUMP) as Pump
(activePumpStore as PluginBase).setPluginEnabled(PluginType.PUMP, true) (activePumpStore as PluginBase).setPluginEnabled(PluginType.PUMP, true)
aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting PumpInterface") aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting PumpInterface")
} }
setFragmentVisiblities((activePumpStore as PluginBase).name, pluginsInCategory, PluginType.PUMP) setFragmentVisibilities((activePumpStore as PluginBase).name, pluginsInCategory, PluginType.PUMP)
// PluginType.TREATMENT // PluginType.TREATMENT
pluginsInCategory = getSpecificPluginsList(PluginType.TREATMENT) pluginsInCategory = getSpecificPluginsList(PluginType.TREATMENT)
@ -138,50 +130,11 @@ class PluginStore @Inject constructor(
(activeTreatmentsStore as PluginBase).setPluginEnabled(PluginType.TREATMENT, true) (activeTreatmentsStore as PluginBase).setPluginEnabled(PluginType.TREATMENT, true)
aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting PumpInterface") aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting PumpInterface")
} }
setFragmentVisiblities((activeTreatmentsStore as PluginBase).name, pluginsInCategory, PluginType.TREATMENT) setFragmentVisibilities((activeTreatmentsStore as PluginBase).name, pluginsInCategory, PluginType.TREATMENT)
} }
/** private fun setFragmentVisibilities(activePluginName: String, pluginsInCategory: ArrayList<PluginBase>,
* disables the visibility for all fragments of Plugins with the given PluginType pluginType: PluginType) {
* which are not equally named to the Plugin implementing the given Plugin Interface.
*
* @param pluginInterface
* @param pluginType
* @param <T>
* @return
</T> */
private fun <T> determineActivePlugin(pluginInterface: Class<T>, pluginType: PluginType): T? {
val pluginsInCategory: ArrayList<PluginBase> = getSpecificPluginsListByInterface(pluginInterface)
return determineActivePlugin(pluginsInCategory, pluginType)
}
/**
* disables the visibility for all fragments of Plugins in the given pluginsInCategory
* with the given PluginType which are not equally named to the Plugin implementing the
* given Plugin Interface.
*
*
* TODO we are casting an interface to PluginBase, which seems to be rather odd, since
* TODO the interface is not implementing PluginBase (this is just avoiding errors through
* TODO conventions.
*
* @param pluginsInCategory
* @param pluginType
* @param <T>
* @return
</T> */
private fun <T> determineActivePlugin(pluginsInCategory: ArrayList<PluginBase>,
pluginType: PluginType): T? {
@Suppress("UNCHECKED_CAST")
val activePlugin = getTheOneEnabledInArray(pluginsInCategory, pluginType) as T?
if (activePlugin != null) {
setFragmentVisiblities((activePlugin as PluginBase).name, pluginsInCategory, pluginType)
}
return activePlugin
}
private fun setFragmentVisiblities(activePluginName: String, pluginsInCategory: ArrayList<PluginBase>,
pluginType: PluginType) {
aapsLogger.debug(LTag.CONFIGBUILDER, "Selected interface: $activePluginName") aapsLogger.debug(LTag.CONFIGBUILDER, "Selected interface: $activePluginName")
for (p in pluginsInCategory) for (p in pluginsInCategory)
if (p.name != activePluginName) if (p.name != activePluginName)
@ -203,22 +156,22 @@ class PluginStore @Inject constructor(
// ***** Interface ***** // ***** Interface *****
override val activeBgSource: BgSourceInterface override val activeBgSource: BgSource
get() = activeBgSourceStore ?: checkNotNull(activeBgSourceStore) { "No bg source selected" } get() = activeBgSourceStore ?: checkNotNull(activeBgSourceStore) { "No bg source selected" }
override val activeProfileInterface: ProfileInterface override val activeProfileSource: ProfileSource
get() = activeProfile ?: checkNotNull(activeProfile) { "No profile selected" } get() = activeProfile ?: checkNotNull(activeProfile) { "No profile selected" }
override val activeInsulin: InsulinInterface override val activeInsulin: Insulin
get() = activeInsulinStore ?: checkNotNull(activeInsulinStore) { "No insulin selected" } get() = activeInsulinStore ?: checkNotNull(activeInsulinStore) { "No insulin selected" }
override val activeAPS: APSInterface override val activeAPS: APS
get() = activeAPSStore ?: checkNotNull(activeAPSStore) { "No APS selected" } get() = activeAPSStore ?: checkNotNull(activeAPSStore) { "No APS selected" }
override val activePump: PumpInterface override val activePump: Pump
get() = activePumpStore ?: checkNotNull(activePumpStore) { "No pump selected" } get() = activePumpStore ?: checkNotNull(activePumpStore) { "No pump selected" }
override val activeSensitivity: SensitivityInterface override val activeSensitivity: Sensitivity
get() = activeSensitivityStore get() = activeSensitivityStore
?: checkNotNull(activeSensitivityStore) { "No sensitivity selected" } ?: checkNotNull(activeSensitivityStore) { "No sensitivity selected" }
@ -226,8 +179,8 @@ class PluginStore @Inject constructor(
get() = activeTreatmentsStore get() = activeTreatmentsStore
?: checkNotNull(activeTreatmentsStore) { "No treatments selected" } ?: checkNotNull(activeTreatmentsStore) { "No treatments selected" }
override val activeOverview: OverviewInterface override val activeOverview: Overview
get() = getSpecificPluginsListByInterface(OverviewInterface::class.java).first() as OverviewInterface get() = getSpecificPluginsListByInterface(Overview::class.java).first() as Overview
override fun getPluginsList(): ArrayList<PluginBase> = ArrayList(plugins) override fun getPluginsList(): ArrayList<PluginBase> = ArrayList(plugins)

View file

@ -24,7 +24,7 @@ class DstHelperPlugin @Inject constructor(
private var rxBus: RxBusWrapper, private var rxBus: RxBusWrapper,
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private var sp: SP, private var sp: SP,
private var activePlugin: ActivePluginProvider, private var activePlugin: ActivePlugin,
private var loopPlugin: LoopPlugin private var loopPlugin: LoopPlugin
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.CONSTRAINTS) .mainType(PluginType.CONSTRAINTS)
@ -33,7 +33,7 @@ class DstHelperPlugin @Inject constructor(
.showInList(false) .showInList(false)
.pluginName(R.string.dst_plugin_name), .pluginName(R.string.dst_plugin_name),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConstraintsInterface { ), Constraints {
companion object { companion object {
private const val DISABLE_TIME_FRAME_HOURS = -3 private const val DISABLE_TIME_FRAME_HOURS = -3

View file

@ -17,7 +17,9 @@ import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.databinding.ObjectivesFragmentBinding import info.nightscout.androidaps.databinding.ObjectivesFragmentBinding
import info.nightscout.androidaps.databinding.ObjectivesItemBinding import info.nightscout.androidaps.databinding.ObjectivesItemBinding
import info.nightscout.androidaps.dialogs.NtpProgressDialog import info.nightscout.androidaps.dialogs.NtpProgressDialog
@ -235,7 +237,7 @@ class ObjectivesFragment : DaggerFragment() {
holder.binding.verify.setOnClickListener { holder.binding.verify.setOnClickListener {
receiverStatusStore.updateNetworkStatus() receiverStatusStore.updateNetworkStatus()
if (binding.fake.isChecked) { if (binding.fake.isChecked) {
objective.accomplishedOn = DateUtil.now() objective.accomplishedOn = dateUtil.now()
scrollToCurrentObjective() scrollToCurrentObjective()
startUpdateTimer() startUpdateTimer()
rxBus.send(EventObjectivesUpdateGui()) rxBus.send(EventObjectivesUpdateGui())
@ -247,7 +249,7 @@ class ObjectivesFragment : DaggerFragment() {
rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.timedetection), 0)) rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.timedetection), 0))
sntpClient.ntpTime(object : SntpClient.Callback() { sntpClient.ntpTime(object : SntpClient.Callback() {
override fun run() { override fun run() {
aapsLogger.debug("NTP time: $time System time: ${DateUtil.now()}") aapsLogger.debug("NTP time: $time System time: ${dateUtil.now()}")
SystemClock.sleep(300) SystemClock.sleep(300)
if (!networkConnected) { if (!networkConnected) {
rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.notconnected), 99)) rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.notconnected), 99))
@ -274,7 +276,7 @@ class ObjectivesFragment : DaggerFragment() {
holder.binding.start.setOnClickListener { holder.binding.start.setOnClickListener {
receiverStatusStore.updateNetworkStatus() receiverStatusStore.updateNetworkStatus()
if (binding.fake.isChecked) { if (binding.fake.isChecked) {
objective.startedOn = DateUtil.now() objective.startedOn = dateUtil.now()
scrollToCurrentObjective() scrollToCurrentObjective()
startUpdateTimer() startUpdateTimer()
rxBus.send(EventObjectivesUpdateGui()) rxBus.send(EventObjectivesUpdateGui())
@ -286,7 +288,7 @@ class ObjectivesFragment : DaggerFragment() {
rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.timedetection), 0)) rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.timedetection), 0))
sntpClient.ntpTime(object : SntpClient.Callback() { sntpClient.ntpTime(object : SntpClient.Callback() {
override fun run() { override fun run() {
aapsLogger.debug("NTP time: $time System time: ${DateUtil.now()}") aapsLogger.debug("NTP time: $time System time: ${dateUtil.now()}")
SystemClock.sleep(300) SystemClock.sleep(300)
if (!networkConnected) { if (!networkConnected) {
rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.notconnected), 99)) rxBus.send(EventNtpStatus(resourceHelper.gs(R.string.notconnected), 99))
@ -308,7 +310,8 @@ class ObjectivesFragment : DaggerFragment() {
holder.binding.unstart.setOnClickListener { holder.binding.unstart.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.doyouwantresetstart), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.doyouwantresetstart), Runnable {
uel.log(Action.OBJECTIVE_UNSTARTED, ValueWithUnit(position + 1, Units.None)) uel.log(Action.OBJECTIVE_UNSTARTED, Sources.Objectives,
ValueWithUnit.SimpleInt(position + 1))
objective.startedOn = 0 objective.startedOn = 0
scrollToCurrentObjective() scrollToCurrentObjective()
rxBus.send(EventObjectivesUpdateGui()) rxBus.send(EventObjectivesUpdateGui())

View file

@ -5,15 +5,16 @@ import com.google.common.base.Charsets
import com.google.common.hash.Hashing import com.google.common.hash.Hashing
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.* import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.* import java.util.*
@ -25,9 +26,10 @@ class ObjectivesPlugin @Inject constructor(
injector: HasAndroidInjector, injector: HasAndroidInjector,
aapsLogger: AAPSLogger, aapsLogger: AAPSLogger,
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePlugin,
private val sp: SP, private val sp: SP,
config: Config, config: ConfigImpl,
private val dateUtil: DateUtil,
private val uel: UserEntryLogger private val uel: UserEntryLogger
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.CONSTRAINTS) .mainType(PluginType.CONSTRAINTS)
@ -39,7 +41,7 @@ class ObjectivesPlugin @Inject constructor(
.shortName(R.string.objectives_shortname) .shortName(R.string.objectives_shortname)
.description(R.string.description_objectives), .description(R.string.description_objectives),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConstraintsInterface { ), Constraints {
var objectives: MutableList<Objective> = ArrayList() var objectives: MutableList<Objective> = ArrayList()
@ -125,25 +127,25 @@ class ObjectivesPlugin @Inject constructor(
if (!url.endsWith("/")) url = "$url/" if (!url.endsWith("/")) url = "$url/"
@Suppress("DEPRECATION") val hashNS = Hashing.sha1().hashString(url + BuildConfig.APPLICATION_ID + "/" + requestCode, Charsets.UTF_8).toString() @Suppress("DEPRECATION") val hashNS = Hashing.sha1().hashString(url + BuildConfig.APPLICATION_ID + "/" + requestCode, Charsets.UTF_8).toString()
if (request.equals(hashNS.substring(0, 10), ignoreCase = true)) { if (request.equals(hashNS.substring(0, 10), ignoreCase = true)) {
sp.putLong("Objectives_" + "openloop" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "openloop" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "openloop" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "openloop" + "_accomplished", dateUtil.now())
sp.putLong("Objectives_" + "maxbasal" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "maxbasal" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "maxbasal" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "maxbasal" + "_accomplished", dateUtil.now())
sp.putLong("Objectives_" + "maxiobzero" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "maxiobzero" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "maxiobzero" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "maxiobzero" + "_accomplished", dateUtil.now())
sp.putLong("Objectives_" + "maxiob" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "maxiob" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "maxiob" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "maxiob" + "_accomplished", dateUtil.now())
sp.putLong("Objectives_" + "autosens" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "autosens" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "autosens" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "autosens" + "_accomplished", dateUtil.now())
sp.putLong("Objectives_" + "ama" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "ama" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "ama" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "ama" + "_accomplished", dateUtil.now())
sp.putLong("Objectives_" + "smb" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "smb" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "smb" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "smb" + "_accomplished", dateUtil.now())
sp.putLong("Objectives_" + "auto" + "_started", DateUtil.now()) sp.putLong("Objectives_" + "auto" + "_started", dateUtil.now())
sp.putLong("Objectives_" + "auto" + "_accomplished", DateUtil.now()) sp.putLong("Objectives_" + "auto" + "_accomplished", dateUtil.now())
setupObjectives() setupObjectives()
OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeaccepted)) OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeaccepted))
uel.log(Action.OBJECTIVES_SKIPPED) uel.log(Action.OBJECTIVES_SKIPPED, Sources.Objectives)
} else { } else {
OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeinvalid)) OKDialog.show(activity, resourceHelper.gs(R.string.objectives), resourceHelper.gs(R.string.codeinvalid))
} }

View file

@ -108,7 +108,7 @@ class ObjectivesExamDialog : DaggerDialogFragment() {
} }
task.answered = result task.answered = result
if (!result) { if (!result) {
task.disabledTo = DateUtil.now() + T.hours(1).msecs() task.disabledTo = dateUtil.now() + T.hours(1).msecs()
ToastUtils.showToastInUiThread(context, R.string.wronganswer) ToastUtils.showToastInUiThread(context, R.string.wronganswer)
} else task.disabledTo = 0 } else task.disabledTo = 0
updateGui() updateGui()

View file

@ -21,6 +21,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var dateUtil: DateUtil
private val spName: String private val spName: String
@StringRes val objective: Int @StringRes val objective: Int
@ -55,7 +56,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
this.gate = gate this.gate = gate
startedOn = sp.getLong("Objectives_" + spName + "_started", 0L) startedOn = sp.getLong("Objectives_" + spName + "_started", 0L)
accomplishedOn = sp.getLong("Objectives_" + spName + "_accomplished", 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 if (accomplishedOn - dateUtil.now() > T.hours(3).msecs() || startedOn - dateUtil.now() > T.hours(3).msecs()) { // more than 3 hours in the future
startedOn = 0 startedOn = 0
accomplishedOn = 0 accomplishedOn = 0
} }
@ -69,7 +70,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
} }
val isAccomplished: Boolean val isAccomplished: Boolean
get() = accomplishedOn != 0L && accomplishedOn < DateUtil.now() get() = accomplishedOn != 0L && accomplishedOn < dateUtil.now()
val isStarted: Boolean val isStarted: Boolean
get() = startedOn != 0L get() = startedOn != 0L
@ -144,7 +145,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
override fun isCompleted(): Boolean = answered override fun isCompleted(): Boolean = answered
fun isEnabledAnswer(): Boolean = disabledTo < DateUtil.now() fun isEnabledAnswer(): Boolean = disabledTo < dateUtil.now()
fun option(option: Option): ExamTask { fun option(option: Option): ExamTask {
options.add(option) options.add(option)

View file

@ -2,25 +2,24 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import javax.inject.Inject import javax.inject.Inject
class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R.string.objectives_0_objective, R.string.objectives_0_gate) { class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R.string.objectives_0_objective, R.string.objectives_0_gate) {
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin @Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var loopPlugin: LoopPlugin @Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var nsClientPlugin: NSClientPlugin @Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var iobCobCalculator: IobCobCalculator
init { init {
tasks.add(object : Task(this, R.string.objectives_bgavailableinns) { tasks.add(object : Task(this, R.string.objectives_bgavailableinns) {
@ -49,7 +48,7 @@ class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R
}) })
tasks.add(object : Task(this, R.string.hasbgdata) { tasks.add(object : Task(this, R.string.hasbgdata) {
override fun isCompleted(): Boolean { override fun isCompleted(): Boolean {
return iobCobCalculatorPlugin.lastBg() != null return iobCobCalculator.ads.lastBg() != null
} }
}) })
tasks.add(object : Task(this, R.string.loopenabled) { tasks.add(object : Task(this, R.string.loopenabled) {
@ -65,7 +64,7 @@ class Objective0(injector: HasAndroidInjector) : Objective(injector, "config", R
}) })
tasks.add(object : Task(this, R.string.activate_profile) { tasks.add(object : Task(this, R.string.activate_profile) {
override fun isCompleted(): Boolean { override fun isCompleted(): Boolean {
return treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now()) != null return treatmentsPlugin.getProfileSwitchFromHistory(dateUtil.now()) != null
} }
}) })
} }

View file

@ -5,7 +5,7 @@ import android.os.Build
import com.scottyab.rootbeer.RootBeer import com.scottyab.rootbeer.RootBeer
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ConstraintsInterface import info.nightscout.androidaps.interfaces.Constraints
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
@ -27,7 +27,7 @@ class PhoneCheckerPlugin @Inject constructor(
.showInList(false) .showInList(false)
.pluginName(R.string.phonechecker), .pluginName(R.string.phonechecker),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConstraintsInterface { ), Constraints {
var phoneRooted: Boolean = false var phoneRooted: Boolean = false
var devMode: Boolean = false var devMode: Boolean = false

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.plugins.constraints.safety package info.nightscout.androidaps.plugins.constraints.safety
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
@ -13,6 +13,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.Round
@ -34,11 +35,12 @@ class SafetyPlugin @Inject constructor(
private val openAPSAMAPlugin: OpenAPSAMAPlugin, private val openAPSAMAPlugin: OpenAPSAMAPlugin,
private val openAPSSMBPlugin: OpenAPSSMBPlugin, private val openAPSSMBPlugin: OpenAPSSMBPlugin,
private val sensitivityOref1Plugin: SensitivityOref1Plugin, private val sensitivityOref1Plugin: SensitivityOref1Plugin,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePlugin,
private val hardLimits: HardLimits, private val hardLimits: HardLimits,
private val buildHelper: BuildHelper, private val buildHelper: BuildHelper,
private val treatmentsPlugin: TreatmentsInterface, private val iobCobCalculator: IobCobCalculator,
private val config: Config private val config: Config,
private val dateUtil: DateUtil
) : PluginBase(PluginDescription() ) : PluginBase(PluginDescription()
.mainType(PluginType.CONSTRAINTS) .mainType(PluginType.CONSTRAINTS)
.neverVisible(true) .neverVisible(true)
@ -47,7 +49,7 @@ class SafetyPlugin @Inject constructor(
.pluginName(R.string.safety) .pluginName(R.string.safety)
.preferencesId(R.xml.pref_safety), .preferencesId(R.xml.pref_safety),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConstraintsInterface { ), Constraints {
/** /**
* Constraints interface * Constraints interface
@ -68,7 +70,7 @@ class SafetyPlugin @Inject constructor(
value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_on_dev_branch)] = this value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_on_dev_branch)] = this
} }
val pump = activePlugin.activePump val pump = activePlugin.activePump
if (!pump.isFakingTempsByExtendedBoluses && treatmentsPlugin.isInHistoryExtendedBolusInProgress) { if (!pump.isFakingTempsByExtendedBoluses && iobCobCalculator.getExtendedBolus(dateUtil.now()) != null) {
value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_with_eb)] = this value[aapsLogger, false, resourceHelper.gs(R.string.closed_loop_disabled_with_eb)] = this
} }
return value return value
@ -124,7 +126,7 @@ class SafetyPlugin @Inject constructor(
val pump = activePlugin.activePump val pump = activePlugin.activePump
// check for pump max // check for pump max
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
absoluteRate.setIfSmaller(aapsLogger, pumpLimit, String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this) absoluteRate.setIfSmaller(aapsLogger, pumpLimit, String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this)
} }
@ -147,7 +149,7 @@ class SafetyPlugin @Inject constructor(
percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt()
percentRate[aapsLogger, percentRateAfterConst, String.format(resourceHelper.gs(R.string.limitingpercentrate), percentRateAfterConst, resourceHelper.gs(R.string.pumplimit))] = this percentRate[aapsLogger, percentRateAfterConst, String.format(resourceHelper.gs(R.string.limitingpercentrate), percentRateAfterConst, resourceHelper.gs(R.string.pumplimit))] = this
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) { if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) {
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this) percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), String.format(resourceHelper.gs(R.string.limitingbasalratio), pumpLimit, resourceHelper.gs(R.string.pumplimit)), this)
} }
return percentRate return percentRate

View file

@ -5,7 +5,7 @@ import android.content.pm.PackageManager
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ConstraintsInterface import info.nightscout.androidaps.interfaces.Constraints
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
@ -46,7 +46,7 @@ class SignatureVerifierPlugin @Inject constructor(
.showInList(false) .showInList(false)
.pluginName(R.string.signature_verifier), .pluginName(R.string.signature_verifier),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConstraintsInterface { ), Constraints {
private val REVOKED_CERTS_URL = "https://raw.githubusercontent.com/nightscout/AndroidAPS/master/app/src/main/assets/revoked_certs.txt" private val REVOKED_CERTS_URL = "https://raw.githubusercontent.com/nightscout/AndroidAPS/master/app/src/main/assets/revoked_certs.txt"
private val UPDATE_INTERVAL = TimeUnit.DAYS.toMillis(1) private val UPDATE_INTERVAL = TimeUnit.DAYS.toMillis(1)

View file

@ -6,7 +6,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ConstraintsInterface import info.nightscout.androidaps.interfaces.Constraints
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
@ -33,7 +33,7 @@ open class StorageConstraintPlugin @Inject constructor(
.showInList(false) .showInList(false)
.pluginName(R.string.storage), .pluginName(R.string.storage),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConstraintsInterface { ), Constraints {
override fun isClosedLoopAllowed(value: Constraint<Boolean>): Constraint<Boolean> { override fun isClosedLoopAllowed(value: Constraint<Boolean>): Constraint<Boolean> {
val diskFree = availableInternalMemorySize() val diskFree = availableInternalMemorySize()

View file

@ -4,7 +4,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.ConstraintsInterface import info.nightscout.androidaps.interfaces.Constraints
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
@ -35,7 +35,7 @@ class VersionCheckerPlugin @Inject constructor(
.showInList(false) .showInList(false)
.pluginName(R.string.versionChecker), .pluginName(R.string.versionChecker),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), ConstraintsInterface { ), Constraints {
enum class GracePeriod(val warning: Long, val old: Long, val veryOld: Long) { enum class GracePeriod(val warning: Long, val old: Long, val veryOld: Long) {
RELEASE(30, 60, 90), RELEASE(30, 60, 90),

View file

@ -11,17 +11,24 @@ import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.activities.TDDStatsActivity import info.nightscout.androidaps.activities.TDDStatsActivity
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.dialogs.* import info.nightscout.androidaps.dialogs.*
import info.nightscout.androidaps.events.* import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.extensions.toStringMedium
import info.nightscout.androidaps.extensions.toStringShort
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -31,10 +38,10 @@ import info.nightscout.androidaps.plugins.general.overview.StatusLightHandler
import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.skins.SkinProvider import info.nightscout.androidaps.skins.SkinProvider
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -52,18 +59,21 @@ class ActionsFragment : DaggerFragment() {
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var ctx: Context @Inject lateinit var ctx: Context
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var statusLightHandler: StatusLightHandler @Inject lateinit var statusLightHandler: StatusLightHandler
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var protectionCheck: ProtectionCheck @Inject lateinit var protectionCheck: ProtectionCheck
@Inject lateinit var skinProvider: SkinProvider @Inject lateinit var skinProvider: SkinProvider
@Inject lateinit var config: Config @Inject lateinit var config: Config
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var repository: AppRepository
private var disposable: CompositeDisposable = CompositeDisposable() private var disposable: CompositeDisposable = CompositeDisposable()
@ -154,8 +164,8 @@ class ActionsFragment : DaggerFragment() {
} }
} }
extendedBolusCancel?.setOnClickListener { extendedBolusCancel?.setOnClickListener {
if (activePlugin.activeTreatments.isInHistoryExtendedBolusInProgress) { if (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null) {
uel.log(Action.CANCEL_EXTENDED_BOLUS) uel.log(Action.CANCEL_EXTENDED_BOLUS, Sources.Actions)
commandQueue.cancelExtended(object : Callback() { commandQueue.cancelExtended(object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
@ -169,8 +179,8 @@ class ActionsFragment : DaggerFragment() {
TempBasalDialog().show(childFragmentManager, "Actions") TempBasalDialog().show(childFragmentManager, "Actions")
} }
cancelTempBasal?.setOnClickListener { cancelTempBasal?.setOnClickListener {
if (activePlugin.activeTreatments.isTempBasalInProgress) { if (iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) != null) {
uel.log(Action.CANCEL_TEMP_BASAL) uel.log(Action.CANCEL_TEMP_BASAL, Sources.Actions)
commandQueue.cancelTempBasal(true, object : Callback() { commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() { override fun run() {
if (!result.success) { if (!result.success) {
@ -255,7 +265,7 @@ class ActionsFragment : DaggerFragment() {
val pump = activePlugin.activePump val pump = activePlugin.activePump
profileSwitch?.visibility = ( profileSwitch?.visibility = (
activePlugin.activeProfileInterface.profile != null && activePlugin.activeProfileSource.profile != null &&
pump.pumpDescription.isSetBasalProfileCapable && pump.pumpDescription.isSetBasalProfileCapable &&
pump.isInitialized() && pump.isInitialized() &&
!pump.isSuspended()).toVisibility() !pump.isSuspended()).toVisibility()
@ -264,12 +274,12 @@ class ActionsFragment : DaggerFragment() {
extendedBolus?.visibility = View.GONE extendedBolus?.visibility = View.GONE
extendedBolusCancel?.visibility = View.GONE extendedBolusCancel?.visibility = View.GONE
} else { } else {
val activeExtendedBolus = activePlugin.activeTreatments.getExtendedBolusFromHistory(System.currentTimeMillis()) val activeExtendedBolus = repository.getExtendedBolusActiveAt(dateUtil.now()).blockingGet()
if (activeExtendedBolus != null) { if (activeExtendedBolus is ValueWrapper.Existing) {
extendedBolus?.visibility = View.GONE extendedBolus?.visibility = View.GONE
extendedBolusCancel?.visibility = View.VISIBLE extendedBolusCancel?.visibility = View.VISIBLE
@Suppress("SetTextI18n") @Suppress("SetTextI18n")
extendedBolusCancel?.text = resourceHelper.gs(R.string.cancel) + " " + activeExtendedBolus.toStringMedium() extendedBolusCancel?.text = resourceHelper.gs(R.string.cancel) + " " + activeExtendedBolus.value.toStringMedium(dateUtil)
} else { } else {
extendedBolus?.visibility = View.VISIBLE extendedBolus?.visibility = View.VISIBLE
extendedBolusCancel?.visibility = View.GONE extendedBolusCancel?.visibility = View.GONE
@ -280,7 +290,7 @@ class ActionsFragment : DaggerFragment() {
setTempBasal?.visibility = View.GONE setTempBasal?.visibility = View.GONE
cancelTempBasal?.visibility = View.GONE cancelTempBasal?.visibility = View.GONE
} else { } else {
val activeTemp = activePlugin.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis())
if (activeTemp != null) { if (activeTemp != null) {
setTempBasal?.visibility = View.GONE setTempBasal?.visibility = View.GONE
cancelTempBasal?.visibility = View.VISIBLE cancelTempBasal?.visibility = View.VISIBLE

View file

@ -1,7 +1,7 @@
package info.nightscout.androidaps.plugins.general.actions package info.nightscout.androidaps.plugins.general.actions
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription

View file

@ -5,15 +5,10 @@ import android.content.Intent
import android.content.pm.ResolveInfo import android.content.pm.ResolveInfo
import android.os.Bundle import android.os.Bundle
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.events.* import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.*
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.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
@ -22,11 +17,13 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.receivers.ReceiverStatusStore import info.nightscout.androidaps.receivers.ReceiverStatusStore
import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.services.Intents
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.extensions.durationInMinutes
import info.nightscout.androidaps.extensions.toStringFull
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -40,14 +37,15 @@ class DataBroadcastPlugin @Inject constructor(
resourceHelper: ResourceHelper, resourceHelper: ResourceHelper,
private val aapsSchedulers: AapsSchedulers, private val aapsSchedulers: AapsSchedulers,
private val context: Context, private val context: Context,
private val dateUtil: DateUtil,
private val fabricPrivacy: FabricPrivacy, private val fabricPrivacy: FabricPrivacy,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val iobCobCalculator: IobCobCalculator,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val defaultValueHelper: DefaultValueHelper, private val defaultValueHelper: DefaultValueHelper,
private val nsDeviceStatus: NSDeviceStatus, private val nsDeviceStatus: NSDeviceStatus,
private val loopPlugin: LoopPlugin, private val loopPlugin: LoopPlugin,
private val activePlugin: ActivePluginProvider, private val activePlugin: ActivePlugin,
private var receiverStatusStore: ReceiverStatusStore, private var receiverStatusStore: ReceiverStatusStore,
private val config: Config, private val config: Config,
private val glucoseStatusProvider: GlucoseStatusProvider private val glucoseStatusProvider: GlucoseStatusProvider
@ -121,7 +119,7 @@ class DataBroadcastPlugin @Inject constructor(
} }
private fun bgStatus(bundle: Bundle) { private fun bgStatus(bundle: Bundle) {
val lastBG = iobCobCalculatorPlugin.lastBg() ?: return val lastBG = iobCobCalculator.ads.lastBg() ?: return
val glucoseStatus = glucoseStatusProvider.glucoseStatusData ?: return val glucoseStatus = glucoseStatusProvider.glucoseStatusData ?: return
bundle.putDouble("glucoseMgdl", lastBG.value) // last BG in mgdl bundle.putDouble("glucoseMgdl", lastBG.value) // last BG in mgdl
@ -136,15 +134,13 @@ class DataBroadcastPlugin @Inject constructor(
private fun iobCob(bundle: Bundle) { private fun iobCob(bundle: Bundle) {
profileFunction.getProfile() ?: return profileFunction.getProfile() ?: return
activePlugin.activeTreatments.updateTotalIOBTreatments() val bolusIob = iobCobCalculator.calculateIobFromBolus().round()
val bolusIob: IobTotal = activePlugin.activeTreatments.lastCalculationTreatments.round() val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
activePlugin.activeTreatments.updateTotalIOBTempBasals()
val basalIob: IobTotal = activePlugin.activeTreatments.lastCalculationTempBasals.round()
bundle.putDouble("bolusIob", bolusIob.iob) bundle.putDouble("bolusIob", bolusIob.iob)
bundle.putDouble("basalIob", basalIob.basaliob) bundle.putDouble("basalIob", basalIob.basaliob)
bundle.putDouble("iob", bolusIob.iob + basalIob.basaliob) // total IOB bundle.putDouble("iob", bolusIob.iob + basalIob.basaliob) // total IOB
val cob = iobCobCalculatorPlugin.getCobInfo(false, "broadcast") val cob = iobCobCalculator.getCobInfo(false, "broadcast")
bundle.putDouble("cob", cob.displayCob ?: -1.0) // COB [g] or -1 if N/A bundle.putDouble("cob", cob.displayCob ?: -1.0) // COB [g] or -1 if N/A
bundle.putDouble("futureCarbs", cob.futureCarbs) // future scheduled carbs bundle.putDouble("futureCarbs", cob.futureCarbs) // future scheduled carbs
} }
@ -181,12 +177,12 @@ class DataBroadcastPlugin @Inject constructor(
bundle.putLong("basalTimeStamp", now) bundle.putLong("basalTimeStamp", now)
bundle.putDouble("baseBasal", profile.basal) bundle.putDouble("baseBasal", profile.basal)
bundle.putString("profile", profileFunction.getProfileName()) bundle.putString("profile", profileFunction.getProfileName())
activePlugin.activeTreatments.getTempBasalFromHistory(now)?.let { iobCobCalculator.getTempBasalIncludingConvertedExtended(now)?.let {
bundle.putLong("tempBasalStart", it.date) bundle.putLong("tempBasalStart", it.timestamp)
bundle.putInt("tempBasalDurationInMinutes", it.durationInMinutes) bundle.putLong("tempBasalDurationInMinutes", it.durationInMinutes)
if (it.isAbsolute) bundle.putDouble("tempBasalAbsolute", it.absoluteRate) // U/h for absolute TBR if (it.isAbsolute) bundle.putDouble("tempBasalAbsolute", it.rate) // U/h for absolute TBR
else bundle.putInt("tempBasalPercent", it.percentRate) // % for percent type TBR else bundle.putInt("tempBasalPercent", it.rate.toInt()) // % for percent type TBR
bundle.putString("tempBasalString", it.toStringFull()) // user friendly string bundle.putString("tempBasalString", it.toStringFull(profile, dateUtil)) // user friendly string
} }
} }

View file

@ -17,6 +17,8 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Food import info.nightscout.androidaps.database.entities.Food
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.InvalidateFoodTransaction import info.nightscout.androidaps.database.transactions.InvalidateFoodTransaction
import info.nightscout.androidaps.databinding.FoodFragmentBinding import info.nightscout.androidaps.databinding.FoodFragmentBinding
import info.nightscout.androidaps.databinding.FoodItemBinding import info.nightscout.androidaps.databinding.FoodItemBinding
@ -25,11 +27,10 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.Completable import io.reactivex.Completable
@ -48,13 +49,12 @@ class FoodFragment : DaggerFragment() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var nsUpload: NSUpload
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
private lateinit var unfiltered: List<Food> private var unfiltered: List<Food> = arrayListOf()
private lateinit var filtered: MutableList<Food> private var filtered: MutableList<Food> = arrayListOf()
private var _binding: FoodFragmentBinding? = null private var _binding: FoodFragmentBinding? = null
@ -76,7 +76,8 @@ class FoodFragment : DaggerFragment() {
binding.refreshFromNightscout.setOnClickListener { binding.refreshFromNightscout.setOnClickListener {
context?.let { context -> context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", { OKDialog.showConfirmation(context, resourceHelper.gs(R.string.refresheventsfromnightscout) + " ?", {
uel.log(Action.FOOD_FROM_NS) uel.log(Action.FOOD, Sources.Food, resourceHelper.gs(R.string.refresheventsfromnightscout),
ValueWithUnit.SimpleString(resourceHelper.gsNotLocalised(R.string.refresheventsfromnightscout)))
disposable += Completable.fromAction { repository.deleteAllFoods() } disposable += Completable.fromAction { repository.deleteAllFoods() }
.subscribeOn(aapsSchedulers.io) .subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
@ -200,8 +201,10 @@ class FoodFragment : DaggerFragment() {
private fun filterData() { private fun filterData() {
val textFilter = binding.filter.text.toString() val textFilter = binding.filter.text.toString()
val categoryFilter = binding.category.selectedItem?.toString() ?: resourceHelper.gs(R.string.none) val categoryFilter = binding.category.selectedItem?.toString()
val subcategoryFilter = binding.subcategory.selectedItem?.toString() ?: resourceHelper.gs(R.string.none) ?: resourceHelper.gs(R.string.none)
val subcategoryFilter = binding.subcategory.selectedItem?.toString()
?: resourceHelper.gs(R.string.none)
val newFiltered = ArrayList<Food>() val newFiltered = ArrayList<Food>()
for (f in unfiltered) { for (f in unfiltered) {
if (f.category == null || f.subCategory == null) continue if (f.category == null || f.subCategory == null) continue
@ -250,16 +253,12 @@ class FoodFragment : DaggerFragment() {
val food = v.tag as Food val food = v.tag as Food
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord) + "\n" + food.name, { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord) + "\n" + food.name, {
uel.log(Action.FOOD_REMOVED, food.name) uel.log(Action.FOOD_REMOVED, Sources.Food, food.name)
disposable += repository.runTransactionForResult(InvalidateFoodTransaction(food.id)) disposable += repository.runTransactionForResult(InvalidateFoodTransaction(food.id))
.subscribe({ .subscribe(
val id = food.interfaceIDs.nightscoutId { aapsLogger.error(LTag.DATABASE, "Invalidated food $it") },
if (NSUpload.isIdValid(id)) nsUpload.removeFoodFromNS(id) { aapsLogger.error(LTag.DATABASE, "Error while invalidating food", it) }
// no create at the moment )
// else uploadQueue.removeID("dbAdd", food.timestamp.toString())
}, {
aapsLogger.error(LTag.BGSOURCE, "Error while invalidating food", it)
})
}, null) }, null)
} }
} }

View file

@ -3,11 +3,13 @@ package info.nightscout.androidaps.plugins.general.food
import android.content.Context import android.content.Context
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.Food import info.nightscout.androidaps.database.entities.Food
import info.nightscout.androidaps.database.transactions.SyncFoodTransaction import info.nightscout.androidaps.database.transactions.SyncNsFoodTransaction
import info.nightscout.androidaps.extensions.foodFromJson
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
@ -15,10 +17,8 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.extensions.foodFromJson
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -56,8 +56,8 @@ class FoodPlugin @Inject constructor(
override fun doWork(): Result { override fun doWork(): Result {
val foods = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1)) val foods = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure(workDataOf("Error" to "missing input data"))
aapsLogger.debug(LTag.DATAFOOD, "Received Food Data: $foods") aapsLogger.debug(LTag.DATABASE, "Received Food Data: $foods")
var ret = Result.success() var ret = Result.success()
@ -75,34 +75,34 @@ class FoodPlugin @Inject constructor(
isValid = false isValid = false
).also { it.interfaceIDs.nightscoutId = JsonHelper.safeGetString(jsonFood, "_id") } ).also { it.interfaceIDs.nightscoutId = JsonHelper.safeGetString(jsonFood, "_id") }
repository.runTransactionForResult(SyncFoodTransaction(delFood)) repository.runTransactionForResult(SyncNsFoodTransaction(delFood, true))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATAFOOD, "Error while removing food", it) aapsLogger.error(LTag.DATABASE, "Error while removing food", it)
ret = Result.failure() ret = Result.failure(workDataOf("Error" to it))
} }
.blockingGet() .blockingGet()
.also { .also {
it.invalidated.forEach { f -> aapsLogger.debug(LTag.DATAFOOD, "Invalidated food ${f.interfaceIDs.nightscoutId}") } it.invalidated.forEach { f -> aapsLogger.debug(LTag.DATABASE, "Invalidated food ${f.interfaceIDs.nightscoutId}") }
} }
} }
else -> { else -> {
val food = foodFromJson(jsonFood) val food = foodFromJson(jsonFood)
if (food != null) { if (food != null) {
repository.runTransactionForResult(SyncFoodTransaction(food)) repository.runTransactionForResult(SyncNsFoodTransaction(food, false))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATAFOOD, "Error while adding/updating food", it) aapsLogger.error(LTag.DATABASE, "Error while adding/updating food", it)
ret = Result.failure() ret = Result.failure(workDataOf("Error" to it))
} }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATAFOOD, "Inserted food $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted food $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATAFOOD, "Updated food $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated food $it") }
result.invalidated.forEach { aapsLogger.debug(LTag.DATAFOOD, "Invalidated food $it") } result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated food $it") }
} }
} else { } else {
aapsLogger.error(LTag.DATAFOOD, "Error parsing food", jsonFood.toString()) aapsLogger.error(LTag.DATABASE, "Error parsing food", jsonFood.toString())
ret = Result.failure() ret = Result.failure(workDataOf("Error" to "Error parsing food"))
} }
} }
} }

View file

@ -16,10 +16,11 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
import info.nightscout.androidaps.activities.PreferencesActivity import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.events.EventAppExit import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.interfaces.ImportExportPrefs
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
@ -40,7 +41,6 @@ import io.reactivex.Single
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.IOException import java.io.IOException
import java.util.*
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.system.exitProcess import kotlin.system.exitProcess
@ -50,20 +50,21 @@ import kotlin.system.exitProcess
*/ */
@Singleton @Singleton
class ImportExportPrefs @Inject constructor( class ImportExportPrefsImpl @Inject constructor(
private var log: AAPSLogger, private var log: AAPSLogger,
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val sp: SP, private val sp: SP,
private val buildHelper: BuildHelper, private val buildHelper: BuildHelper,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val passwordCheck: PasswordCheck, private val passwordCheck: PasswordCheck,
private val config: ConfigInterface, private val config: Config,
private val androidPermission: AndroidPermission, private val androidPermission: AndroidPermission,
private val classicPrefsFormat: ClassicPrefsFormat, private val classicPrefsFormat: ClassicPrefsFormat,
private val encryptedPrefsFormat: EncryptedPrefsFormat, private val encryptedPrefsFormat: EncryptedPrefsFormat,
private val prefFileList: PrefFileListProvider, private val prefFileList: PrefFileListProvider,
private val uel: UserEntryLogger private val uel: UserEntryLogger,
) : ImportExportPrefsInterface { private val dateUtil: DateUtil
) : ImportExportPrefs {
override fun prefsFileExists(): Boolean { override fun prefsFileExists(): Boolean {
return prefFileList.listPreferenceFiles().size > 0 return prefFileList.listPreferenceFiles().size > 0
@ -94,7 +95,7 @@ class ImportExportPrefs @Inject constructor(
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf() val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf()
metadata[PrefsMetadataKey.DEVICE_NAME] = PrefMetadata(detectUserName(context), PrefsStatus.OK) metadata[PrefsMetadataKey.DEVICE_NAME] = PrefMetadata(detectUserName(context), PrefsStatus.OK)
metadata[PrefsMetadataKey.CREATED_AT] = PrefMetadata(DateUtil.toISOString(Date()), PrefsStatus.OK) metadata[PrefsMetadataKey.CREATED_AT] = PrefMetadata(dateUtil.toISOString(dateUtil.now()), PrefsStatus.OK)
metadata[PrefsMetadataKey.AAPS_VERSION] = PrefMetadata(BuildConfig.VERSION_NAME, PrefsStatus.OK) metadata[PrefsMetadataKey.AAPS_VERSION] = PrefMetadata(BuildConfig.VERSION_NAME, PrefsStatus.OK)
metadata[PrefsMetadataKey.AAPS_FLAVOUR] = PrefMetadata(BuildConfig.FLAVOR, PrefsStatus.OK) metadata[PrefsMetadataKey.AAPS_FLAVOUR] = PrefMetadata(BuildConfig.FLAVOR, PrefsStatus.OK)
metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatus.OK) metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatus.OK)
@ -348,7 +349,7 @@ class ImportExportPrefs @Inject constructor(
private fun restartAppAfterImport(context: Context) { private fun restartAppAfterImport(context: Context) {
sp.putBoolean(R.string.key_setupwizard_processed, true) sp.putBoolean(R.string.key_setupwizard_processed, true)
OKDialog.show(context, resourceHelper.gs(R.string.setting_imported), resourceHelper.gs(R.string.restartingapp)) { OKDialog.show(context, resourceHelper.gs(R.string.setting_imported), resourceHelper.gs(R.string.restartingapp)) {
uel.log(Action.IMPORT_SETTINGS) uel.log(Action.IMPORT_SETTINGS, Sources.Maintenance)
log.debug(LTag.CORE, "Exiting") log.debug(LTag.CORE, "Exiting")
rxBus.send(EventAppExit()) rxBus.send(EventAppExit())
if (context is AppCompatActivity) { if (context is AppCompatActivity) {

View file

@ -8,16 +8,19 @@ import android.view.ViewGroup
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding
import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.events.EventNewBG
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface import info.nightscout.androidaps.interfaces.ImportExportPrefs
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -32,12 +35,13 @@ class MaintenanceFragment : DaggerFragment() {
@Inject lateinit var maintenancePlugin: MaintenancePlugin @Inject lateinit var maintenancePlugin: MaintenancePlugin
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var importExportPrefs: ImportExportPrefs
@Inject lateinit var importExportPrefs: ImportExportPrefsInterface
@Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var uel: UserEntryLogger @Inject lateinit var uel: UserEntryLogger
@Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var pumpSync: PumpSync
private val compositeDisposable = CompositeDisposable() private val compositeDisposable = CompositeDisposable()
@ -56,40 +60,42 @@ class MaintenanceFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.logSend.setOnClickListener { maintenancePlugin.sendLogs() } binding.logSend.setOnClickListener { maintenancePlugin.sendLogs() }
binding.logDelete.setOnClickListener { binding.logDelete.setOnClickListener {
uel.log(Action.DELETE_LOGS) uel.log(Action.DELETE_LOGS, Sources.Maintenance)
maintenancePlugin.deleteLogs() maintenancePlugin.deleteLogs()
} }
binding.navResetdb.setOnClickListener { binding.navResetdb.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.maintenance), resourceHelper.gs(R.string.reset_db_confirm), Runnable { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.maintenance), resourceHelper.gs(R.string.reset_db_confirm), Runnable {
uel.log(Action.RESET_DATABASES)
compositeDisposable.add( compositeDisposable.add(
fromAction { fromAction {
databaseHelper.resetDatabases() databaseHelper.resetDatabases()
// should be handled by Plugin-Interface and
// additional service interface and plugin registry
treatmentsPlugin.service.resetTreatments()
repository.clearDatabases() repository.clearDatabases()
dataSyncSelector.resetToNextFullSync()
pumpSync.connectNewPump()
} }
.subscribeOn(aapsSchedulers.io) .subscribeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.main) .observeOn(aapsSchedulers.main)
.subscribeBy( .subscribeBy(
onError = { aapsLogger.error("Error clearing databases", it) }, onError = { aapsLogger.error("Error clearing databases", it) },
onComplete = { rxBus.send(EventNewBG(null)) } onComplete = {
rxBus.send(EventNewBG(null))
rxBus.send(EventNewHistoryData(0, true))
}
) )
) )
uel.log(Action.RESET_DATABASES, Sources.Maintenance)
}) })
} }
} }
binding.navExport.setOnClickListener { binding.navExport.setOnClickListener {
uel.log(Action.EXPORT_SETTINGS) uel.log(Action.EXPORT_SETTINGS, Sources.Maintenance)
// start activity for checking permissions... // start activity for checking permissions...
importExportPrefs.verifyStoragePermissions(this) { importExportPrefs.verifyStoragePermissions(this) {
importExportPrefs.exportSharedPreferences(this) importExportPrefs.exportSharedPreferences(this)
} }
} }
binding.navImport.setOnClickListener { binding.navImport.setOnClickListener {
uel.log(Action.IMPORT_SETTINGS) uel.log(Action.IMPORT_SETTINGS, Sources.Maintenance)
// start activity for checking permissions... // start activity for checking permissions...
importExportPrefs.verifyStoragePermissions(this) { importExportPrefs.verifyStoragePermissions(this) {
importExportPrefs.importSharedPreferences(this) importExportPrefs.importSharedPreferences(this)
@ -99,7 +105,7 @@ class MaintenanceFragment : DaggerFragment() {
binding.exportCsv.setOnClickListener { binding.exportCsv.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.ue_export_to_csv) + "?") { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.ue_export_to_csv) + "?") {
uel.log(Action.EXPORT_CSV) uel.log(Action.EXPORT_CSV, Sources.Maintenance)
importExportPrefs.exportUserEntriesCsv(activity, repository.getAllUserEntries()) importExportPrefs.exportUserEntriesCsv(activity, repository.getAllUserEntries())
} }
} }

View file

@ -8,7 +8,7 @@ import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription

View file

@ -0,0 +1,411 @@
package info.nightscout.androidaps.plugins.general.nsclient
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.DeviceStatus
import info.nightscout.androidaps.database.entities.*
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.extensions.toJson
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject
class DataSyncSelectorImplementation @Inject constructor(
private val sp: SP,
private val aapsLogger: AAPSLogger,
private val dateUtil: DateUtil,
private val profileFunction: ProfileFunction,
private val nsClientPlugin: NSClientPlugin,
private val activePlugin: ActivePlugin,
private val appRepository: AppRepository
) : DataSyncSelector {
override fun resetToNextFullSync() {
sp.remove(R.string.key_ns_temporary_target_last_synced_id)
sp.remove(R.string.key_ns_glucose_value_last_synced_id)
sp.remove(R.string.key_ns_food_last_synced_id)
sp.remove(R.string.key_ns_bolus_last_synced_id)
sp.remove(R.string.key_ns_carbs_last_synced_id)
sp.remove(R.string.key_ns_bolus_calculator_result_last_synced_id)
sp.remove(R.string.key_ns_device_status_last_synced_id)
sp.remove(R.string.key_ns_temporary_basal_last_synced_id)
sp.remove(R.string.key_ns_extended_bolus_last_synced_id)
sp.remove(R.string.key_ns_therapy_event_last_synced_id)
}
override fun confirmLastBolusIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting Bolus data sync from $lastSynced")
sp.putLong(R.string.key_ns_bolus_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedBoluses(): List<Bolus> {
val startId = sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)
return appRepository.getModifiedBolusesDataFromId(startId)
.blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.also {
aapsLogger.debug(LTag.NSCLIENT, "Loading Bolus data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedBolusesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)
appRepository.getNextSyncElementBolus(startId).blockingGet()?.let { bolus ->
aapsLogger.info(LTag.DATABASE, "Loading Bolus data Start: $startId ID: ${bolus.first.id} HistoryID: ${bolus.second} ")
when {
// removed and not uploaded yet = ignore
!bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", bolus.first.interfaceIDs.nightscoutId, DataSyncSelector.PairBolus(bolus.first, bolus.second))
// existing without nsId = create new
bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", bolus.first.toJson(dateUtil), DataSyncSelector.PairBolus(bolus.first, bolus.second))
// existing with nsId = update
bolus.first.isValid && bolus.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolus.first.interfaceIDs.nightscoutId, bolus.first.toJson(dateUtil), DataSyncSelector.PairBolus(bolus.first, bolus.second))
}
return true
}
return false
}
override fun confirmLastCarbsIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting Carbs data sync from $lastSynced")
sp.putLong(R.string.key_ns_carbs_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedCarbs(): List<Carbs> {
val startId = sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)
return appRepository.getModifiedCarbsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading Carbs data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedCarbsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)
appRepository.getNextSyncElementCarbs(startId).blockingGet()?.let { carb ->
aapsLogger.info(LTag.DATABASE, "Loading Carbs data Start: $startId ID: ${carb.first.id} HistoryID: ${carb.second} ")
when {
// removed and not uploaded yet = ignore
!carb.first.isValid && carb.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!carb.first.isValid && carb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", carb.first.interfaceIDs.nightscoutId, DataSyncSelector.PairCarbs(carb.first, carb.second))
// existing without nsId = create new
carb.first.isValid && carb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", carb.first.toJson(dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second))
// existing with nsId = update
carb.first.isValid && carb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", carb.first.interfaceIDs.nightscoutId, carb.first.toJson(dateUtil), DataSyncSelector.PairCarbs(carb.first, carb.second))
}
return true
}
return false
}
override fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting BolusCalculatorResult data sync from $lastSynced")
sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedBolusCalculatorResults(): List<BolusCalculatorResult> {
val startId = sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)
return appRepository.getModifiedBolusCalculatorResultsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading BolusCalculatorResult data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedBolusCalculatorResultsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)
appRepository.getNextSyncElementBolusCalculatorResult(startId).blockingGet()?.let { bolusCalculatorResult ->
aapsLogger.info(LTag.DATABASE, "Loading BolusCalculatorResult data Start: $startId ID: ${bolusCalculatorResult.first.id} HistoryID: ${bolusCalculatorResult.second} ")
when {
// removed and not uploaded yet = ignore
!bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second))
// existing without nsId = create new
bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", bolusCalculatorResult.first.toJson(dateUtil), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second))
// existing with nsId = update
bolusCalculatorResult.first.isValid && bolusCalculatorResult.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(dateUtil), DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second))
}
return true
}
return false
}
override fun confirmLastTempTargetsIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryTarget data sync from $lastSynced")
sp.putLong(R.string.key_ns_temporary_target_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedTempTargets(): List<TemporaryTarget> {
val startId = sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)
return appRepository.getModifiedTemporaryTargetsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading TemporaryTarget data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedTempTargetsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)
appRepository.getNextSyncElementTemporaryTarget(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading TemporaryTarget data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
when {
// removed and not uploaded yet = ignore
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", tt.first.interfaceIDs.nightscoutId, DataSyncSelector.PairTemporaryTarget(tt.first, tt.second))
// existing without nsId = create new
tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tt.first.toJson(profileFunction.getUnits(), dateUtil), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second))
// existing with nsId = update
tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(profileFunction.getUnits(), dateUtil), DataSyncSelector.PairTemporaryTarget(tt.first, tt.second))
}
return true
}
return false
}
override fun confirmLastFoodIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_food_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting Food data sync from $lastSynced")
sp.putLong(R.string.key_ns_food_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedFoods(): List<Food> {
val startId = sp.getLong(R.string.key_ns_food_last_synced_id, 0)
return appRepository.getModifiedFoodDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading Food data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedFoodsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_food_last_synced_id, 0)
appRepository.getNextSyncElementFood(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading Food data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
when {
// removed and not uploaded yet = ignore
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("food", tt.first.interfaceIDs.nightscoutId, DataSyncSelector.PairFood(tt.first, tt.second))
// existing without nsId = create new
tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("food", tt.first.toJson(), DataSyncSelector.PairFood(tt.first, tt.second))
// existing with nsId = update
tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("food", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(), DataSyncSelector.PairFood(tt.first, tt.second))
}
return true
}
return false
}
override fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting GlucoseValue data sync from $lastSynced")
sp.putLong(R.string.key_ns_glucose_value_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedGlucoseValues(): List<GlucoseValue> {
val startId = sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)
return appRepository.getModifiedBgReadingsDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading GlucoseValue data for sync from $startId . Records ${it.size}")
}
}
override fun processChangedGlucoseValuesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)
appRepository.getNextSyncElementGlucoseValue(startId).blockingGet()?.let { gv ->
aapsLogger.info(LTag.DATABASE, "Loading GlucoseValue data Start: $startId ID: ${gv.first.id} HistoryID: ${gv.second} ")
if (activePlugin.activeBgSource.shouldUploadToNs(gv.first)) {
when {
// removed and not uploaded yet = ignore
!gv.first.isValid && gv.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!gv.first.isValid && gv.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("entries", gv.first.interfaceIDs.nightscoutId, DataSyncSelector.PairGlucoseValue(gv.first, gv.second))
// existing without nsId = create new
gv.first.isValid && gv.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("entries", gv.first.toJson(dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second))
// existing with nsId = update
gv.first.isValid && gv.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("entries", gv.first.interfaceIDs.nightscoutId, gv.first.toJson(dateUtil), DataSyncSelector.PairGlucoseValue(gv.first, gv.second))
}
return true
}
}
return false
}
override fun confirmLastTherapyEventIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting TherapyEvents data sync from $lastSynced")
sp.putLong(R.string.key_ns_therapy_event_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedTherapyEvents(): List<TherapyEvent> {
val startId = sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)
return appRepository.getModifiedTherapyEventDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading TherapyEvents data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedTherapyEventsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)
appRepository.getNextSyncElementTherapyEvent(startId).blockingGet()?.let { tt ->
aapsLogger.info(LTag.DATABASE, "Loading TherapyEvents data Start: $startId ID: ${tt.first.id} HistoryID: ${tt.second} ")
when {
// removed and not uploaded yet = ignore
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", tt.first.interfaceIDs.nightscoutId, DataSyncSelector.PairTherapyEvent(tt.first, tt.second))
// existing without nsId = create new
tt.first.isValid && tt.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tt.first.toJson(), DataSyncSelector.PairTherapyEvent(tt.first, tt.second))
// existing with nsId = update
tt.first.isValid && tt.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tt.first.interfaceIDs.nightscoutId, tt.first.toJson(), DataSyncSelector.PairTherapyEvent(tt.first, tt.second))
}
return true
}
return false
}
override fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting DeviceStatus data sync from $lastSynced")
sp.putLong(R.string.key_ns_device_status_last_synced_id, lastSynced)
}
}
override fun changedDeviceStatuses(): List<DeviceStatus> {
val startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)
return appRepository.getModifiedDeviceStatusDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading DeviceStatus data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedDeviceStatusesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)
appRepository.getNextSyncElementDeviceStatus(startId).blockingGet()?.let { deviceStatus ->
aapsLogger.info(LTag.DATABASE, "Loading DeviceStatus data Start: $startId ID: ${deviceStatus.id}")
when {
// without nsId = create new
deviceStatus.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("devicestatus", deviceStatus.toJson(dateUtil), deviceStatus)
// with nsId = ignore
deviceStatus.interfaceIDs.nightscoutId != null -> Any()
}
return true
}
return false
}
override fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryBasal data sync from $lastSynced")
sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedTemporaryBasals(): List<TemporaryBasal> {
val startId = sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)
return appRepository.getModifiedTemporaryBasalDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading TemporaryBasal data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedTemporaryBasalsCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)
appRepository.getNextSyncElementTemporaryBasal(startId).blockingGet()?.let { tb ->
aapsLogger.info(LTag.DATABASE, "Loading TemporaryBasal data Start: $startId ID: ${tb.first.id} HistoryID: ${tb.second} ")
profileFunction.getProfile(tb.first.timestamp)?.let { profile ->
when {
// removed and not uploaded yet = ignore
!tb.first.isValid && tb.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!tb.first.isValid && tb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", tb.first.interfaceIDs.nightscoutId, DataSyncSelector.PairTemporaryBasal(tb.first, tb.second))
// existing without nsId = create new
tb.first.isValid && tb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", tb.first.toJson(profile, dateUtil), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second))
// existing with nsId = update
tb.first.isValid && tb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", tb.first.interfaceIDs.nightscoutId, tb.first.toJson(profile, dateUtil), DataSyncSelector.PairTemporaryBasal(tb.first, tb.second))
}
return true
}
}
return false
}
override fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) {
if (lastSynced > sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)) {
aapsLogger.debug(LTag.NSCLIENT, "Setting ExtendedBolus data sync from $lastSynced")
sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, lastSynced)
}
}
// Prepared for v3 (returns all modified after)
override fun changedExtendedBoluses(): List<ExtendedBolus> {
val startId = sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)
return appRepository.getModifiedExtendedBolusDataFromId(startId).blockingGet().also {
aapsLogger.debug(LTag.NSCLIENT, "Loading ExtendedBolus data for sync from $startId. Records ${it.size}")
}
}
override fun processChangedExtendedBolusesCompat(): Boolean {
val startId = sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)
appRepository.getNextSyncElementExtendedBolus(startId).blockingGet()?.let { eb ->
aapsLogger.info(LTag.DATABASE, "Loading ExtendedBolus data Start: $startId ID: ${eb.first.id} HistoryID: ${eb.second} ")
profileFunction.getProfile(eb.first.timestamp)?.let { profile ->
when {
// removed and not uploaded yet = ignore
!eb.first.isValid && eb.first.interfaceIDs.nightscoutId == null -> Any()
// removed and already uploaded = send for removal
!eb.first.isValid && eb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbRemove("treatments", eb.first.interfaceIDs.nightscoutId, DataSyncSelector.PairExtendedBolus(eb.first, eb.second))
// existing without nsId = create new
eb.first.isValid && eb.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd("treatments", eb.first.toJson(profile, dateUtil), DataSyncSelector.PairExtendedBolus(eb.first, eb.second))
// existing with nsId = update
eb.first.isValid && eb.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate("treatments", eb.first.interfaceIDs.nightscoutId, eb.first.toJson(profile, dateUtil), DataSyncSelector.PairExtendedBolus(eb.first, eb.second))
}
return true
}
}
return false
}
}

View file

@ -0,0 +1,237 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.DeviceStatus
import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.DataSyncSelector.*
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.acks.NSAddAck
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import javax.inject.Inject
class NSClientAddAckWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var repository: AppRepository
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var aapsSchedulers: AapsSchedulers
override fun doWork(): Result {
var ret = Result.success()
val ack = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as NSAddAck?
?: return Result.failure(workDataOf("Error" to "missing input data"))
when (ack.originalObject) {
is PairTemporaryTarget -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdTemporaryTargetTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of TemporaryTarget failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of TemporaryTarget " + pair.value)
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked TemporaryTarget " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedTempTargetsCompat()
}
is PairGlucoseValue -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdGlucoseValueTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of GlucoseValue failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of GlucoseValue " + pair.value)
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked GlucoseValue " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedGlucoseValuesCompat()
}
is PairFood -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdFoodTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of Food failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of Food " + pair.value)
dataSyncSelector.confirmLastFoodIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked Food " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedFoodsCompat()
}
is PairTherapyEvent -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdTherapyEventTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of TherapyEvent failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of TherapyEvent " + pair.value)
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked TherapyEvent " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedTherapyEventsCompat()
}
is PairBolus -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdBolusTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of Bolus failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of Bolus " + pair.value)
dataSyncSelector.confirmLastBolusIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked Bolus " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedBolusesCompat()
}
is PairCarbs -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdCarbsTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of Carbs failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of Carbs " + pair.value)
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked Carbs" + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedCarbsCompat()
}
is PairBolusCalculatorResult -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdBolusCalculatorResultTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of BolusCalculatorResult failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of BolusCalculatorResult " + pair.value)
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked BolusCalculatorResult" + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedBolusCalculatorResultsCompat()
}
is PairTemporaryBasal -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdTemporaryBasalTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of TemporaryBasal failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of TemporaryBasal " + pair.value)
dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked TemporaryBasal" + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedTemporaryBasalsCompat()
}
is PairExtendedBolus -> {
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdExtendedBolusTransaction(pair.value))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of ExtendedBolus failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of ExtendedBolus " + pair.value)
dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.updateRecordId)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked ExtendedBolus" + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedTemporaryBasalsCompat()
}
is DeviceStatus -> {
val deviceStatus = ack.originalObject
deviceStatus.interfaceIDs.nightscoutId = ack.id
repository.runTransactionForResult(UpdateNsIdDeviceStatusTransaction(deviceStatus))
.doOnError { error ->
aapsLogger.error(LTag.DATABASE, "Updated ns id of DeviceStatus failed", error)
ret = Result.failure((workDataOf("Error" to error)))
}
.doOnSuccess {
ret = Result.success(workDataOf("ProcessedData" to deviceStatus))
aapsLogger.debug(LTag.DATABASE, "Updated ns id of DeviceStatus $deviceStatus")
dataSyncSelector.confirmLastDeviceStatusIdIfGreater(deviceStatus.id)
}
.blockingGet()
rxBus.send(EventNSClientNewLog("DBADD", "Acked DeviceStatus" + deviceStatus.interfaceIDs.nightscoutId))
// Send new if waiting
dataSyncSelector.processChangedBolusCalculatorResultsCompat()
}
}
return ret
}
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
}

View file

@ -3,16 +3,18 @@ package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context import android.content.Context
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.SyncTemporaryTargetTransaction import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.events.EventNsTreatment import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -25,9 +27,8 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetLong import info.nightscout.androidaps.utils.JsonHelper.safeGetLong
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.temporaryTargetFromJson
import info.nightscout.androidaps.utils.extensions.therapyEventFromJson
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
class NSClientAddUpdateWorker( class NSClientAddUpdateWorker(
@ -40,8 +41,8 @@ class NSClientAddUpdateWorker(
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var dateutil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var config: ConfigInterface @Inject lateinit var config: Config
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@ -49,65 +50,135 @@ class NSClientAddUpdateWorker(
override fun doWork(): Result { override fun doWork(): Result {
val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT
if (!acceptNSData) return Result.failure() if (!acceptNSData) return Result.success()
val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1)) val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure(workDataOf("Error" to "missing input data"))
var ret = Result.success() var ret = Result.success()
var latestDateInReceivedData = 0L var latestDateInReceivedData = 0L
for (i in 0 until treatments.length()) { for (i in 0 until treatments.length()) {
val json = treatments.getJSONObject(i) var json = treatments.getJSONObject(i)
// new DB model // new DB model
val insulin = JsonHelper.safeGetDouble(json, "insulin") val insulin = JsonHelper.safeGetDouble(json, "insulin")
val carbs = JsonHelper.safeGetDouble(json, "carbs") val carbs = JsonHelper.safeGetDouble(json, "carbs")
val eventType = JsonHelper.safeGetString(json, "eventType") val eventType = JsonHelper.safeGetString(json, "eventType")
if (eventType == null) { if (eventType == null) {
aapsLogger.debug(LTag.DATASERVICE, "Wrong treatment. Ignoring : $json") aapsLogger.debug(LTag.NSCLIENT, "Wrong treatment. Ignoring : $json")
continue continue
} }
//Find latest date in treatment //Find latest date in treatment
val mills = safeGetLong(json, "mills") val mills = safeGetLong(json, "mills")
if (mills != 0L && mills < dateutil._now()) if (mills != 0L && mills < dateUtil.now())
if (mills > latestDateInReceivedData) latestDateInReceivedData = mills if (mills > latestDateInReceivedData) latestDateInReceivedData = mills
if (insulin > 0) {
bolusFromJson(json)?.let { bolus ->
repository.runTransactionForResult(SyncNsBolusTransaction(bolus, invalidateByNsOnly = false))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(Action.BOLUS, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Insulin(it.amount)
)
aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it")
}
result.invalidated.forEach {
uel.log(Action.BOLUS_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Insulin(it.amount)
)
aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId bolus $it")
}
}
} ?: aapsLogger.error("Error parsing bolus json $json")
}
if (carbs > 0) {
carbsFromJson(json)?.let { carb ->
repository.runTransactionForResult(SyncNsCarbsTransaction(carb, invalidateByNsOnly = false))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(Action.CARBS, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Gram(it.amount.toInt())
)
aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it")
}
result.invalidated.forEach {
uel.log(Action.CARBS_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Gram(it.amount.toInt())
)
aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId carbs $it")
}
}
} ?: aapsLogger.error("Error parsing bolus json $json")
}
// Convert back emulated TBR -> EB
if (eventType == TherapyEvent.Type.TEMPORARY_BASAL.text && json.has("extendedEmulated")) {
val ebJson = json.getJSONObject("extendedEmulated")
ebJson.put("_id", json.getString("_id"))
ebJson.put("isValid", json.getBoolean("isValid"))
json = ebJson
}
when { when {
insulin > 0 || carbs > 0 -> insulin > 0 || carbs > 0 -> Any()
rxBus.send(EventNsTreatment(EventNsTreatment.ADD, json))
eventType == TherapyEvent.Type.TEMPORARY_TARGET.text -> eventType == TherapyEvent.Type.TEMPORARY_TARGET.text ->
temporaryTargetFromJson(json)?.let { temporaryTarget -> temporaryTargetFromJson(json)?.let { temporaryTarget ->
repository.runTransactionForResult(SyncTemporaryTargetTransaction(temporaryTarget)) repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTarget, invalidateByNsOnly = false))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
ret = Result.failure() ret = Result.failure(workDataOf("Error" to it))
} }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { result.inserted.forEach { tt ->
uel.log(UserEntry.Action.TT_FROM_NS, uel.log(Action.TT, Sources.NSClient,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent), ValueWithUnit.TherapyEventTTReason(tt.reason),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true), ValueWithUnit.fromGlucoseUnit(tt.lowTarget, Constants.MGDL),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget), ValueWithUnit.fromGlucoseUnit(tt.highTarget, Constants.MGDL).takeIf { tt.lowTarget != tt.highTarget },
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true) ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt())
) )
aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryTarget $tt")
} }
result.invalidated.forEach { result.invalidated.forEach { tt ->
uel.log(UserEntry.Action.TT_DELETED_FROM_NS, uel.log(Action.TT_REMOVED, Sources.NSClient,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent), ValueWithUnit.TherapyEventTTReason(tt.reason),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true), ValueWithUnit.Mgdl(tt.lowTarget),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget), ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget },
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true) ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt())
) )
aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryTarget $tt")
} }
result.ended.forEach { result.ended.forEach { tt ->
uel.log(UserEntry.Action.TT_CANCELED_FROM_NS, uel.log(Action.CANCEL_TT, Sources.NSClient,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent), ValueWithUnit.TherapyEventTTReason(tt.reason),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true), ValueWithUnit.Mgdl(tt.lowTarget),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget), ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget },
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, true) ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt())
) )
aapsLogger.debug(LTag.DATABASE, "Updated TemporaryTarget $tt")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryTarget $it")
} }
} }
} ?: aapsLogger.error("Error parsing TT json $json") } ?: aapsLogger.error("Error parsing TT json $json")
@ -115,7 +186,6 @@ class NSClientAddUpdateWorker(
eventType == TherapyEvent.Type.INSULIN_CHANGE.text || eventType == TherapyEvent.Type.INSULIN_CHANGE.text ||
eventType == TherapyEvent.Type.SENSOR_CHANGE.text || eventType == TherapyEvent.Type.SENSOR_CHANGE.text ||
eventType == TherapyEvent.Type.FINGER_STICK_BG_VALUE.text || eventType == TherapyEvent.Type.FINGER_STICK_BG_VALUE.text ||
eventType == TherapyEvent.Type.NOTE.text ||
eventType == TherapyEvent.Type.NONE.text || eventType == TherapyEvent.Type.NONE.text ||
eventType == TherapyEvent.Type.ANNOUNCEMENT.text || eventType == TherapyEvent.Type.ANNOUNCEMENT.text ||
eventType == TherapyEvent.Type.QUESTION.text || eventType == TherapyEvent.Type.QUESTION.text ||
@ -123,33 +193,118 @@ class NSClientAddUpdateWorker(
eventType == TherapyEvent.Type.APS_OFFLINE.text || eventType == TherapyEvent.Type.APS_OFFLINE.text ||
eventType == TherapyEvent.Type.PUMP_BATTERY_CHANGE.text -> eventType == TherapyEvent.Type.PUMP_BATTERY_CHANGE.text ->
therapyEventFromJson(json)?.let { therapyEvent -> therapyEventFromJson(json)?.let { therapyEvent ->
repository.runTransactionForResult(SyncTherapyEventTransaction(therapyEvent)) repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEvent, invalidateByNsOnly = false))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it)
ret = Result.failure() ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
val action = when (eventType) {
TherapyEvent.Type.CANNULA_CHANGE.text -> Action.SITE_CHANGE
TherapyEvent.Type.INSULIN_CHANGE.text -> Action.RESERVOIR_CHANGE
else -> Action.CAREPORTAL
}
result.inserted.forEach {
uel.log(action, Sources.NSClient,
it.note ?: "",
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.TherapyEventType(it.type)
)
aapsLogger.debug(LTag.DATABASE, "Inserted TherapyEvent $it")
}
result.invalidated.forEach {
uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient,
it.note ?: "",
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.TherapyEventType(it.type)
)
aapsLogger.debug(LTag.DATABASE, "Invalidated TherapyEvent $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TherapyEvent $it")
}
}
} ?: aapsLogger.error("Error parsing TherapyEvent json $json")
eventType == TherapyEvent.Type.COMBO_BOLUS.text ->
extendedBolusFromJson(json)?.let { extendedBolus ->
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus, invalidateByNsOnly = false))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving extended bolus", it)
ret = Result.failure(workDataOf("Error" to it))
} }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { result.inserted.forEach {
uel.log(UserEntry.Action.CAREPORTAL_FROM_NS, uel.log(Action.EXTENDED_BOLUS, Sources.NSClient,
it.note ?: "", ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit.Insulin(it.amount),
ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent) ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
) )
aapsLogger.debug(LTag.DATABASE, "Inserted ExtendedBolus $it")
} }
result.invalidated.forEach { result.invalidated.forEach {
uel.log(UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.NSClient,
it.note ?: "", ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit.Insulin(it.amount),
ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent) ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
) )
aapsLogger.debug(LTag.DATABASE, "Invalidated ExtendedBolus $it")
}
result.ended.forEach {
uel.log(Action.CANCEL_EXTENDED_BOLUS, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Insulin(it.amount),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Updated ExtendedBolus $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId ExtendedBolus $it")
} }
} }
} ?: aapsLogger.error("Error parsing TherapyEvent json $json") } ?: aapsLogger.error("Error parsing ExtendedBolus json $json")
eventType == TherapyEvent.Type.TEMPORARY_BASAL.text -> eventType == TherapyEvent.Type.TEMPORARY_BASAL.text ->
databaseHelper.createTempBasalFromJsonIfNotExists(json) temporaryBasalFromJson(json)?.let { temporaryBasal ->
eventType == TherapyEvent.Type.COMBO_BOLUS.text -> repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal, invalidateByNsOnly = false))
databaseHelper.createExtendedBolusFromJsonIfNotExists(json) .doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.inserted.forEach {
uel.log(Action.TEMP_BASAL, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it")
}
result.invalidated.forEach {
uel.log(Action.TEMP_BASAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryBasal $it")
}
result.ended.forEach {
uel.log(Action.CANCEL_TEMP_BASAL, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt())
)
aapsLogger.debug(LTag.DATABASE, "Ended TemporaryBasal $it")
}
result.updatedNsId.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryBasal $it")
}
}
} ?: aapsLogger.error("Error parsing TemporaryBasal json $json")
eventType == TherapyEvent.Type.PROFILE_SWITCH.text -> eventType == TherapyEvent.Type.PROFILE_SWITCH.text ->
databaseHelper.createProfileSwitchFromJsonIfNotExists(json) databaseHelper.createProfileSwitchFromJsonIfNotExists(json)
} }

View file

@ -1,171 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient;
import android.graphics.Paint;
import android.os.Bundle;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ScrollView;
import android.widget.TextView;
import javax.inject.Inject;
import dagger.android.support.DaggerFragment;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface;
import info.nightscout.androidaps.database.entities.UserEntry;
import info.nightscout.androidaps.database.entities.UserEntry.*;
import info.nightscout.androidaps.logging.UserEntryLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.HtmlHelper;
import info.nightscout.androidaps.utils.alertDialogs.OKDialog;
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;
public class NSClientFragment extends DaggerFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
@Inject NSClientPlugin nsClientPlugin;
@Inject SP sp;
@Inject ResourceHelper resourceHelper;
@Inject RxBusWrapper rxBus;
@Inject UploadQueueAdminInterface uploadQueue;
@Inject FabricPrivacy fabricPrivacy;
@Inject AapsSchedulers aapsSchedulers;
@Inject UserEntryLogger uel;
private final CompositeDisposable disposable = new CompositeDisposable();
private TextView logTextView;
private TextView queueTextView;
private TextView urlTextView;
private TextView statusTextView;
private TextView clearlog;
private TextView restart;
private TextView delivernow;
private TextView clearqueue;
private TextView showqueue;
private ScrollView logScrollview;
private CheckBox autoscrollCheckbox;
private CheckBox pausedCheckbox;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.nsclientinternal_fragment, container, false);
logScrollview = view.findViewById(R.id.nsclientinternal_logscrollview);
autoscrollCheckbox = view.findViewById(R.id.nsclientinternal_autoscroll);
autoscrollCheckbox.setChecked(nsClientPlugin.autoscroll);
autoscrollCheckbox.setOnCheckedChangeListener(this);
pausedCheckbox = view.findViewById(R.id.nsclientinternal_paused);
pausedCheckbox.setChecked(nsClientPlugin.paused);
pausedCheckbox.setOnCheckedChangeListener(this);
logTextView = view.findViewById(R.id.nsclientinternal_log);
queueTextView = view.findViewById(R.id.nsclientinternal_queue);
urlTextView = view.findViewById(R.id.nsclientinternal_url);
statusTextView = view.findViewById(R.id.nsclientinternal_status);
clearlog = view.findViewById(R.id.nsclientinternal_clearlog);
clearlog.setOnClickListener(this);
clearlog.setPaintFlags(clearlog.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
restart = view.findViewById(R.id.nsclientinternal_restart);
restart.setOnClickListener(this);
restart.setPaintFlags(restart.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
delivernow = view.findViewById(R.id.nsclientinternal_delivernow);
delivernow.setOnClickListener(this);
delivernow.setPaintFlags(delivernow.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
clearqueue = view.findViewById(R.id.nsclientinternal_clearqueue);
clearqueue.setOnClickListener(this);
clearqueue.setPaintFlags(clearqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
showqueue = view.findViewById(R.id.nsclientinternal_showqueue);
showqueue.setOnClickListener(this);
showqueue.setPaintFlags(showqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
return view;
}
@Override
public synchronized void onResume() {
super.onResume();
disposable.add(rxBus
.toObservable(EventNSClientUpdateGUI.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> updateGui(), fabricPrivacy::logException)
);
updateGui();
}
@Override
public synchronized void onPause() {
super.onPause();
disposable.clear();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.nsclientinternal_restart:
rxBus.send(new EventNSClientRestart());
fabricPrivacy.logCustom("NSClientRestart");
break;
case R.id.nsclientinternal_delivernow:
nsClientPlugin.resend("GUI");
fabricPrivacy.logCustom("NSClientDeliverNow");
break;
case R.id.nsclientinternal_clearlog:
nsClientPlugin.clearLog();
break;
case R.id.nsclientinternal_clearqueue:
OKDialog.showConfirmation(getContext(), resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.clearqueueconfirm), () -> {
uel.log(Action.NS_QUEUE_CLEARED);
uploadQueue.clearQueue();
updateGui();
fabricPrivacy.logCustom("NSClientClearQueue");
});
break;
case R.id.nsclientinternal_showqueue:
rxBus.send(new EventNSClientNewLog("QUEUE", uploadQueue.textList()));
break;
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
switch (buttonView.getId()) {
case R.id.nsclientinternal_paused:
uel.log(isChecked ? Action.NS_PAUSED : Action.NS_RESUME);
nsClientPlugin.pause(isChecked);
updateGui();
fabricPrivacy.logCustom("NSClientPause");
break;
case R.id.nsclientinternal_autoscroll:
sp.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked);
nsClientPlugin.autoscroll = isChecked;
updateGui();
break;
}
}
protected void updateGui() {
nsClientPlugin.updateLog();
pausedCheckbox.setChecked(sp.getBoolean(R.string.key_nsclientinternal_paused, false));
logTextView.setText(nsClientPlugin.textLog);
if (nsClientPlugin.autoscroll) {
logScrollview.fullScroll(ScrollView.FOCUS_DOWN);
}
urlTextView.setText(nsClientPlugin.url());
Spanned queuetext = HtmlHelper.INSTANCE.fromHtml(resourceHelper.gs(R.string.queue) + " <b>" + uploadQueue.size() + "</b>");
queueTextView.setText(queuetext);
statusTextView.setText(nsClientPlugin.status);
}
}

View file

@ -0,0 +1,122 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.graphics.Paint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ScrollView
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.databinding.NsClientFragmentBinding
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper.fromHtml
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
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 javax.inject.Inject
class NSClientFragment : DaggerFragment() {
@Inject lateinit var nsClientPlugin: NSClientPlugin
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var uploadQueue: UploadQueueAdminInterface
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var uel: UserEntryLogger
private val disposable = CompositeDisposable()
private var _binding: NsClientFragmentBinding? = 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 =
NsClientFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.autoscroll.isChecked = nsClientPlugin.autoscroll
binding.autoscroll.setOnCheckedChangeListener { _, isChecked ->
sp.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked)
nsClientPlugin.autoscroll = isChecked
updateGui()
}
binding.paused.isChecked = nsClientPlugin.paused
binding.paused.setOnCheckedChangeListener { _, isChecked ->
uel.log(if (isChecked) Action.NS_PAUSED else Action.NS_RESUME, Sources.NSClient)
nsClientPlugin.pause(isChecked)
updateGui()
}
binding.clearLog.setOnClickListener { nsClientPlugin.clearLog() }
binding.clearLog.paintFlags = binding.clearLog.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.restart.setOnClickListener { rxBus.send(EventNSClientRestart()) }
binding.restart.paintFlags = binding.restart.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.deliverNow.setOnClickListener { nsClientPlugin.resend("GUI") }
binding.deliverNow.paintFlags = binding.deliverNow.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.clearQueue.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.clearqueueconfirm), Runnable {
uel.log(Action.NS_QUEUE_CLEARED, Sources.NSClient)
uploadQueue.clearQueue()
updateGui()
})
}
}
binding.clearQueue.paintFlags = binding.clearQueue.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.showQueue.setOnClickListener { rxBus.send(EventNSClientNewLog("QUEUE", uploadQueue.textList())) }
binding.showQueue.paintFlags = binding.showQueue.paintFlags or Paint.UNDERLINE_TEXT_FLAG
binding.fullSync.setOnClickListener {
context?.let { context ->
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.full_sync), Runnable {
dataSyncSelector.resetToNextFullSync()
})
}
}
binding.fullSync.paintFlags = binding.fullSync.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
@Synchronized override fun onResume() {
super.onResume()
disposable.add(rxBus
.toObservable(EventNSClientUpdateGUI::class.java)
.observeOn(aapsSchedulers.main)
.subscribe({ updateGui() }, fabricPrivacy::logException)
)
updateGui()
}
@Synchronized override fun onPause() {
super.onPause()
disposable.clear()
}
private fun updateGui() {
if (_binding == null) return
nsClientPlugin.updateLog()
binding.paused.isChecked = sp.getBoolean(R.string.key_nsclientinternal_paused, false)
binding.log.text = nsClientPlugin.textLog
if (nsClientPlugin.autoscroll) binding.logScrollview.fullScroll(ScrollView.FOCUS_DOWN)
binding.url.text = nsClientPlugin.url()
binding.queue.text = fromHtml(resourceHelper.gs(R.string.queue) + " <b>" + uploadQueue.size() + "</b>")
binding.status.text = nsClientPlugin.status
}
}

View file

@ -3,17 +3,18 @@ package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context import android.content.Context
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction import info.nightscout.androidaps.database.transactions.SyncNsTherapyEventTransaction
import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg
import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.therapyEventFromNsMbg import info.nightscout.androidaps.extensions.therapyEventFromNsMbg
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
@ -27,7 +28,7 @@ class NSClientMbgWorker(
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var config: ConfigInterface @Inject lateinit var config: Config
override fun doWork(): Result { override fun doWork(): Result {
var ret = Result.success() var ret = Result.success()
@ -36,14 +37,14 @@ class NSClientMbgWorker(
if (!acceptNSData) return ret if (!acceptNSData) return ret
val mbgArray = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1)) val mbgArray = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure(workDataOf("Error" to "missing input data"))
for (i in 0 until mbgArray.length()) { for (i in 0 until mbgArray.length()) {
val nsMbg = NSMbg(mbgArray.getJSONObject(i)) val nsMbg = NSMbg(mbgArray.getJSONObject(i))
if (!nsMbg.isValid()) continue if (!nsMbg.isValid()) continue
repository.runTransactionForResult(SyncTherapyEventTransaction(therapyEventFromNsMbg(nsMbg))) repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEventFromNsMbg(nsMbg), false))
.doOnError { .doOnError {
aapsLogger.error("Error while saving therapy event", it) aapsLogger.error("Error while saving therapy event", it)
ret = Result.failure() ret = Result.failure(workDataOf("Error" to it))
} }
.blockingGet() .blockingGet()
.also { .also {

View file

@ -4,20 +4,16 @@ import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.text.Spanned; import android.text.Spanned;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -25,30 +21,18 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.android.HasAndroidInjector; import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.interfaces.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.database.entities.TemporaryTarget;
import info.nightscout.androidaps.database.entities.TherapyEvent;
import info.nightscout.androidaps.database.entities.UserEntry.Action;
import info.nightscout.androidaps.database.entities.UserEntry.Units;
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit;
import info.nightscout.androidaps.database.transactions.SyncTemporaryTargetTransaction;
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction;
import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventChargingState; import info.nightscout.androidaps.events.EventChargingState;
import info.nightscout.androidaps.events.EventNetworkChange; import info.nightscout.androidaps.events.EventNetworkChange;
import info.nightscout.androidaps.events.EventNsTreatment;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.logging.UserEntryLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck; import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm; import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
@ -57,12 +41,8 @@ import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientR
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus; import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI; import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService; import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.HtmlHelper; import info.nightscout.androidaps.utils.HtmlHelper;
import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.ToastUtils; import info.nightscout.androidaps.utils.ToastUtils;
import info.nightscout.androidaps.utils.buildHelper.BuildHelper; import info.nightscout.androidaps.utils.buildHelper.BuildHelper;
import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.resources.ResourceHelper;
@ -70,11 +50,6 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.androidaps.utils.sharedPreferences.SP; import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensionKt.temporaryTargetFromJson;
import static info.nightscout.androidaps.utils.extensions.TemporaryTargetExtensionKt.temporaryTargetFromNsIdForInvalidating;
import static info.nightscout.androidaps.utils.extensions.TherapyEventExtensionKt.therapyEventFromJson;
import static info.nightscout.androidaps.utils.extensions.TherapyEventExtensionKt.therapyEventFromNsIdForInvalidating;
@Singleton @Singleton
public class NSClientPlugin extends PluginBase { public class NSClientPlugin extends PluginBase {
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
@ -86,13 +61,9 @@ public class NSClientPlugin extends PluginBase {
private final AapsSchedulers aapsSchedulers; private final AapsSchedulers aapsSchedulers;
private final FabricPrivacy fabricPrivacy; private final FabricPrivacy fabricPrivacy;
private final SP sp; private final SP sp;
private final NsClientReceiverDelegate nsClientReceiverDelegate;
private final Config config; private final Config config;
private final BuildHelper buildHelper; private final BuildHelper buildHelper;
private final ActivePluginProvider activePlugin;
private final NSUpload nsUpload;
private final AppRepository repository;
private final DatabaseHelperInterface databaseHelper;
private final UserEntryLogger uel;
public Handler handler; public Handler handler;
@ -104,9 +75,8 @@ public class NSClientPlugin extends PluginBase {
public String status = ""; public String status = "";
public NSClientService nsClientService = null; public @Nullable NSClientService nsClientService = null;
private final NsClientReceiverDelegate nsClientReceiverDelegate;
@Inject @Inject
public NSClientPlugin( public NSClientPlugin(
@ -120,12 +90,7 @@ public class NSClientPlugin extends PluginBase {
SP sp, SP sp,
NsClientReceiverDelegate nsClientReceiverDelegate, NsClientReceiverDelegate nsClientReceiverDelegate,
Config config, Config config,
BuildHelper buildHelper, BuildHelper buildHelper
ActivePluginProvider activePlugin,
NSUpload nsUpload,
DatabaseHelperInterface databaseHelper,
AppRepository repository,
UserEntryLogger uel
) { ) {
super(new PluginDescription() super(new PluginDescription()
.mainType(PluginType.GENERAL) .mainType(PluginType.GENERAL)
@ -148,11 +113,6 @@ public class NSClientPlugin extends PluginBase {
this.nsClientReceiverDelegate = nsClientReceiverDelegate; this.nsClientReceiverDelegate = nsClientReceiverDelegate;
this.config = config; this.config = config;
this.buildHelper = buildHelper; this.buildHelper = buildHelper;
this.activePlugin = activePlugin;
this.nsUpload = nsUpload;
this.databaseHelper = databaseHelper;
this.repository = repository;
this.uel = uel;
if (config.getNSCLIENT()) { if (config.getNSCLIENT()) {
getPluginDescription().alwaysEnabled(true).visibleByDefault(true); getPluginDescription().alwaysEnabled(true).visibleByDefault(true);
@ -354,7 +314,7 @@ public class NSClientPlugin extends PluginBase {
} }
public void updateLatestDateReceivedIfNewer(long latestReceived) { public void updateLatestDateReceivedIfNewer(long latestReceived) {
if (latestReceived > nsClientService.latestDateInReceivedData) if (nsClientService != null && latestReceived > nsClientService.latestDateInReceivedData)
nsClientService.latestDateInReceivedData = latestReceived; nsClientService.latestDateInReceivedData = latestReceived;
} }
} }

View file

@ -3,16 +3,16 @@ package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context import android.content.Context
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.ValueWithUnit import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.SyncTemporaryTargetTransaction import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.database.transactions.SyncTherapyEventTransaction import info.nightscout.androidaps.database.transactions.*
import info.nightscout.androidaps.events.EventNsTreatment import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.events.EventNsTreatment.Companion.REMOVE import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -21,9 +21,8 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.temporaryTargetFromNsIdForInvalidating
import info.nightscout.androidaps.utils.extensions.therapyEventFromNsIdForInvalidating
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
// This will not be needed fpr NS v3 // This will not be needed fpr NS v3
@ -38,7 +37,7 @@ class NSClientRemoveWorker(
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var buildHelper: BuildHelper @Inject lateinit var buildHelper: BuildHelper
@Inject lateinit var sp: SP @Inject lateinit var sp: SP
@Inject lateinit var config: ConfigInterface @Inject lateinit var config: Config
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@ -46,12 +45,12 @@ class NSClientRemoveWorker(
override fun doWork(): Result { override fun doWork(): Result {
val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT
if (!acceptNSData) return Result.failure() if (!acceptNSData) return Result.success()
var ret = Result.success() var ret = Result.success()
val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1)) val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1))
?: return Result.failure() ?: return Result.failure(workDataOf("Error" to "missing input data"))
for (i in 0 until treatments.length()) { for (i in 0 until treatments.length()) {
val json = treatments.getJSONObject(i) val json = treatments.getJSONObject(i)
@ -59,46 +58,107 @@ class NSClientRemoveWorker(
// room Temporary target // room Temporary target
val temporaryTarget = temporaryTargetFromNsIdForInvalidating(nsId) val temporaryTarget = temporaryTargetFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncTemporaryTargetTransaction(temporaryTarget)) repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTarget, invalidateByNsOnly = true))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATABASE, "Error while removing temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it)
ret = Result.failure() ret = Result.failure(workDataOf("Error" to it))
} }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.invalidated.forEach { result.invalidated.forEach { tt ->
uel.log( uel.log(
UserEntry.Action.TT_DELETED_FROM_NS, Action.TT_REMOVED, Sources.NSClient,
ValueWithUnit(it.reason.text, UserEntry.Units.TherapyEvent), ValueWithUnit.TherapyEventTTReason(tt.reason),
ValueWithUnit(it.lowTarget, UserEntry.Units.Mg_Dl, true), ValueWithUnit.Mgdl(tt.lowTarget),
ValueWithUnit(it.highTarget, UserEntry.Units.Mg_Dl, it.lowTarget != it.highTarget), ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget },
ValueWithUnit(it.duration.toInt() / 60000, UserEntry.Units.M, it.duration != 0L) ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()).takeIf { tt.duration != 0L }
) )
} }
} }
// room Therapy Event // room Therapy Event
val therapyEvent = therapyEventFromNsIdForInvalidating(nsId) val therapyEvent = therapyEventFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncTherapyEventTransaction(therapyEvent)) repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEvent, invalidateByNsOnly = true))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATABASE, "Error while removing therapy event", it) aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it)
ret = Result.failure() ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient,
(it.note ?: ""),
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.TherapyEventType(it.type))
}
}
// room Bolus
val bolus = bolusFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsBolusTransaction(bolus, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Insulin(it.amount))
}
}
// room Carbs
val carbs = carbsFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsCarbsTransaction(carbs, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.Gram(it.amount.toInt()))
}
}
// room TemporaryBasal
val temporaryBasal = temporaryBasalFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it)
ret = Result.failure(workDataOf("Error" to it))
} }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.invalidated.forEach { result.invalidated.forEach {
uel.log( uel.log(
UserEntry.Action.CAREPORTAL_DELETED_FROM_NS, (it.note ?: ""), Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit(it.timestamp, UserEntry.Units.Timestamp, true), ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit(it.type.text, UserEntry.Units.TherapyEvent)) ValueWithUnit.UnitPerHour(it.rate))
}
}
// room ExtendedBolus
val extendedBolus = extendedBolusFromNsIdForInvalidating(nsId)
repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus, invalidateByNsOnly = true))
.doOnError {
aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it)
ret = Result.failure(workDataOf("Error" to it))
}
.blockingGet()
.also { result ->
result.invalidated.forEach {
uel.log(
Action.CAREPORTAL_REMOVED, Sources.NSClient,
ValueWithUnit.Timestamp(it.timestamp),
ValueWithUnit.UnitPerHour(it.rate))
} }
} }
// Insulin, carbs
rxBus.send(EventNsTreatment(REMOVE, json))
// old DB model // old DB model
databaseHelper.deleteTempBasalById(nsId)
databaseHelper.deleteExtendedBolusById(nsId)
databaseHelper.deleteProfileSwitchById(nsId) databaseHelper.deleteProfileSwitchById(nsId)
} }

View file

@ -0,0 +1,126 @@
package info.nightscout.androidaps.plugins.general.nsclient
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.DataSyncSelector.*
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import javax.inject.Inject
class NSClientUpdateRemoveAckWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
@Inject lateinit var dataWorker: DataWorker
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var repository: AppRepository
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var aapsSchedulers: AapsSchedulers
override fun doWork(): Result {
var ret = Result.success()
val ack = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as NSUpdateAck?
?: return Result.failure(workDataOf("Error" to "missing input data"))
// new room way
when (ack.originalObject) {
is PairTemporaryTarget -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked TemporaryTarget" + ack._id))
// Send new if waiting
dataSyncSelector.processChangedTempTargetsCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairGlucoseValue -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked GlucoseValue " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedGlucoseValuesCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairFood -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastFoodIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked Food " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedFoodsCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairTherapyEvent -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked TherapyEvent " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedTherapyEventsCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairBolus -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastBolusIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked Bolus " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedBolusesCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairCarbs -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked Carbs " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedCarbsCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairBolusCalculatorResult -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked BolusCalculatorResult " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedBolusCalculatorResultsCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairTemporaryBasal -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked TemporaryBasal " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedTemporaryBasalsCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
is PairExtendedBolus -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.updateRecordId)
rxBus.send(EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked ExtendedBolus " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedExtendedBolusesCompat()
ret = Result.success(workDataOf("ProcessedData" to pair.toString()))
}
}
return ret
}
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
}
}

View file

@ -1,62 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.acks;
import org.json.JSONArray;
import org.json.JSONObject;
import info.nightscout.androidaps.events.Event;
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.events.EventNSClientRestart;
import io.socket.client.Ack;
/**
* Created by mike on 29.12.2015.
*/
public class NSAddAck extends Event implements Ack {
private final AAPSLogger aapsLogger;
private final RxBusWrapper rxBus;
public String _id = null;
public String nsClientID = null;
public JSONObject json = null;
public NSAddAck(AAPSLogger aapsLogger, RxBusWrapper rxBus) {
this.aapsLogger = aapsLogger;
this.rxBus = rxBus;
}
public void call(Object... args) {
// Regular response
try {
JSONArray responsearray = (JSONArray) (args[0]);
JSONObject response;
if (responsearray.length() > 0) {
response = responsearray.getJSONObject(0);
_id = response.getString("_id");
json = response;
if (response.has("NSCLIENT_ID")) {
nsClientID = response.getString("NSCLIENT_ID");
}
}
rxBus.send(this);
return;
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
// Check for not authorized
try {
JSONObject response = (JSONObject) (args[0]);
if (response.has("result")) {
_id = null;
if (response.getString("result").contains("Not")) {
rxBus.send(new EventNSClientRestart());
return;
}
aapsLogger.debug(LTag.NSCLIENT, "DBACCESS " + response.getString("result"));
}
} catch (Exception e) {
aapsLogger.error("Unhandled exception", e);
}
}
}

View file

@ -0,0 +1,54 @@
package info.nightscout.androidaps.plugins.general.nsclient.acks
import info.nightscout.androidaps.events.Event
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.events.EventNSClientRestart
import io.socket.client.Ack
import org.json.JSONArray
import org.json.JSONObject
class NSAddAck(
private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
val originalObject: Any? = null
) : Event(), Ack {
var id: String? = null
@JvmField var nsClientID: String? = null
@JvmField var json: JSONObject? = null
override fun call(vararg args: Any) {
// Regular response
try {
val responseArray = args[0] as JSONArray
val response: JSONObject
if (responseArray.length() > 0) {
response = responseArray.getJSONObject(0)
id = response.getString("_id")
json = response
if (response.has("NSCLIENT_ID")) {
nsClientID = response.getString("NSCLIENT_ID")
}
}
rxBus.send(this)
return
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
// Check for not authorized
try {
val response = args[0] as JSONObject
if (response.has("result")) {
id = null
if (response.getString("result").contains("Not")) {
rxBus.send(EventNSClientRestart())
return
}
aapsLogger.debug(LTag.NSCLIENT, "DBACCESS " + response.getString("result"))
}
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
}
}

View file

@ -1,46 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.acks;
import org.json.JSONException;
import org.json.JSONObject;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import io.socket.client.Ack;
/**
* Created by mike on 21.02.2016.
*/
public class NSUpdateAck extends Event implements Ack {
private final AAPSLogger aapsLogger;
private final RxBusWrapper rxBus;
public boolean result = false;
public String _id;
public String action;
public void call(Object... args) {
JSONObject response = (JSONObject) args[0];
if (response.has("result"))
try {
if (response.getString("result").equals("success"))
result = true;
else if (response.getString("result").equals("Missing _id")) {
result = true;
aapsLogger.debug(LTag.NSCLIENT, "Internal error: Missing _id returned on dbUpdate ack");
}
rxBus.send(this);
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public NSUpdateAck(String action, String _id, AAPSLogger aapsLogger, RxBusWrapper rxBus) {
super();
this.action = action;
this._id = _id;
this.aapsLogger = aapsLogger;
this.rxBus = rxBus;
}
}

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps.plugins.general.nsclient.acks
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import io.socket.client.Ack
import org.json.JSONException
import org.json.JSONObject
/**
* Created by mike on 21.02.2016.
*/
class NSUpdateAck(
val action : String,
var _id: String,
private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
val originalObject: Any? = null
) : Event(), Ack {
var result = false
override fun call(vararg args: Any) {
val response = args[0] as JSONObject
if (response.has("result")) try {
if (response.getString("result") == "success") {
result = true
} else if (response.getString("result") == "Missing _id") {
result = true
aapsLogger.debug(LTag.NSCLIENT, "Internal error: Missing _id returned on dbUpdate ack")
}
rxBus.send(this)
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
}
}

View file

@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.data
import android.text.Spanned import android.text.Spanned
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.ConfigInterface import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.loop.APSResult import info.nightscout.androidaps.plugins.aps.loop.APSResult
@ -78,7 +78,7 @@ class NSDeviceStatus @Inject constructor(
private val sp: SP, private val sp: SP,
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val nsSettingsStatus: NSSettingsStatus, private val nsSettingsStatus: NSSettingsStatus,
private val config: ConfigInterface, private val config: Config,
private val dateUtil: DateUtil, private val dateUtil: DateUtil,
private val runningConfiguration: RunningConfiguration private val runningConfiguration: RunningConfiguration
) { ) {
@ -164,12 +164,12 @@ class NSDeviceStatus @Inject constructor(
// test warning level // test warning level
val level = when { val level = when {
pumpData.clock + nsSettingsStatus.extendedPumpSettings("urgentClock") * 60 * 1000L < dateUtil._now() -> Levels.URGENT pumpData.clock + nsSettingsStatus.extendedPumpSettings("urgentClock") * 60 * 1000L < dateUtil.now() -> Levels.URGENT
pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("urgentRes") -> Levels.URGENT pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("urgentRes") -> Levels.URGENT
pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("urgentBattP") -> Levels.URGENT pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("urgentBattP") -> Levels.URGENT
!pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("urgentBattV") -> Levels.URGENT !pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("urgentBattV") -> Levels.URGENT
pumpData.clock + nsSettingsStatus.extendedPumpSettings("warnClock") * 60 * 1000L < dateUtil._now() -> Levels.WARN pumpData.clock + nsSettingsStatus.extendedPumpSettings("warnClock") * 60 * 1000L < dateUtil.now() -> Levels.WARN
pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("warnRes") -> Levels.WARN pumpData.reservoir < nsSettingsStatus.extendedPumpSettings("warnRes") -> Levels.WARN
pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("warnBattP") -> Levels.WARN pumpData.isPercent && pumpData.percent < nsSettingsStatus.extendedPumpSettings("warnBattP") -> Levels.WARN
!pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("warnBattV") -> Levels.WARN !pumpData.isPercent && pumpData.voltage < nsSettingsStatus.extendedPumpSettings("warnBattV") -> Levels.WARN
else -> Levels.INFO else -> Levels.INFO
@ -179,7 +179,7 @@ class NSDeviceStatus @Inject constructor(
if (fields.contains("reservoir")) string.append(pumpData.reservoir.toInt()).append("U ") if (fields.contains("reservoir")) string.append(pumpData.reservoir.toInt()).append("U ")
if (fields.contains("battery") && pumpData.isPercent) string.append(pumpData.percent).append("% ") if (fields.contains("battery") && pumpData.isPercent) string.append(pumpData.percent).append("% ")
if (fields.contains("battery") && !pumpData.isPercent) string.append(Round.roundTo(pumpData.voltage, 0.001)).append(" ") if (fields.contains("battery") && !pumpData.isPercent) string.append(Round.roundTo(pumpData.voltage, 0.001)).append(" ")
if (fields.contains("clock")) string.append(DateUtil.minAgo(resourceHelper, pumpData.clock)).append(" ") if (fields.contains("clock")) string.append(dateUtil.minAgo(resourceHelper, pumpData.clock)).append(" ")
if (fields.contains("status")) string.append(pumpData.status).append(" ") if (fields.contains("status")) string.append(pumpData.status).append(" ")
if (fields.contains("device")) string.append(device).append(" ") if (fields.contains("device")) string.append(device).append(" ")
string.append("</span>") // color string.append("</span>") // color
@ -201,7 +201,7 @@ class NSDeviceStatus @Inject constructor(
try { try {
val data = this.data ?: return val data = this.data ?: return
val pump = if (data.has("pump")) data.getJSONObject("pump") else JSONObject() val pump = if (data.has("pump")) data.getJSONObject("pump") else JSONObject()
val clock = if (pump.has("clock")) DateUtil.fromISODateString(pump.getString("clock")).time else 0L val clock = if (pump.has("clock")) dateUtil.fromISODateString(pump.getString("clock")) else 0L
// check if this is new data // check if this is new data
if (clock == 0L || deviceStatusPumpData != null && clock < deviceStatusPumpData!!.clock) return if (clock == 0L || deviceStatusPumpData != null && clock < deviceStatusPumpData!!.clock) return
@ -247,13 +247,13 @@ class NSDeviceStatus @Inject constructor(
val openAps = if (jsonObject.has("openaps")) jsonObject.getJSONObject("openaps") else JSONObject() val openAps = if (jsonObject.has("openaps")) jsonObject.getJSONObject("openaps") else JSONObject()
val suggested = if (openAps.has("suggested")) openAps.getJSONObject("suggested") else JSONObject() val suggested = if (openAps.has("suggested")) openAps.getJSONObject("suggested") else JSONObject()
val enacted = if (openAps.has("enacted")) openAps.getJSONObject("enacted") else JSONObject() val enacted = if (openAps.has("enacted")) openAps.getJSONObject("enacted") else JSONObject()
var clock = if (suggested.has("timestamp")) DateUtil.fromISODateString(suggested.getString("timestamp")).time else 0L var clock = if (suggested.has("timestamp")) dateUtil.fromISODateString(suggested.getString("timestamp")) else 0L
// check if this is new data // check if this is new data
if (clock != 0L && clock > deviceStatusOpenAPSData.clockSuggested) { if (clock != 0L && clock > deviceStatusOpenAPSData.clockSuggested) {
deviceStatusOpenAPSData.suggested = suggested deviceStatusOpenAPSData.suggested = suggested
deviceStatusOpenAPSData.clockSuggested = clock deviceStatusOpenAPSData.clockSuggested = clock
} }
clock = if (enacted.has("timestamp")) DateUtil.fromISODateString(enacted.getString("timestamp")).time else 0L clock = if (enacted.has("timestamp")) dateUtil.fromISODateString(enacted.getString("timestamp")) else 0L
// check if this is new data // check if this is new data
if (clock != 0L && clock > deviceStatusOpenAPSData.clockEnacted) { if (clock != 0L && clock > deviceStatusOpenAPSData.clockEnacted) {
deviceStatusOpenAPSData.enacted = enacted deviceStatusOpenAPSData.enacted = enacted
@ -273,12 +273,12 @@ class NSDeviceStatus @Inject constructor(
// test warning level // test warning level
val level = when { val level = when {
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_urgent_staledatavalue, 31)).msecs() < dateUtil._now() -> Levels.URGENT deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_urgent_staledatavalue, 31)).msecs() < dateUtil.now() -> Levels.URGENT
deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_staledatavalue, 16)).msecs() < dateUtil._now() -> Levels.WARN deviceStatusOpenAPSData.clockSuggested + T.mins(sp.getLong(R.string.key_nsalarm_staledatavalue, 16)).msecs() < dateUtil.now() -> Levels.WARN
else -> Levels.INFO else -> Levels.INFO
} }
string.append("<span style=\"color:${level.toColor()}\">") string.append("<span style=\"color:${level.toColor()}\">")
if (deviceStatusOpenAPSData.clockSuggested != 0L) string.append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append(" ") if (deviceStatusOpenAPSData.clockSuggested != 0L) string.append(dateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append(" ")
string.append("</span>") // color string.append("</span>") // color
return fromHtml(string.toString()) return fromHtml(string.toString())
} }
@ -287,8 +287,8 @@ class NSDeviceStatus @Inject constructor(
get() { get() {
val string = StringBuilder() val string = StringBuilder()
try { try {
if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested) string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockEnacted)).append("</b> ").append(deviceStatusOpenAPSData.enacted!!.getString("reason")).append("<br>") if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested) string.append("<b>").append(dateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockEnacted)).append("</b> ").append(deviceStatusOpenAPSData.enacted!!.getString("reason")).append("<br>")
if (deviceStatusOpenAPSData.suggested != null) string.append("<b>").append(DateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append("</b> ").append(deviceStatusOpenAPSData.suggested!!.getString("reason")).append("<br>") if (deviceStatusOpenAPSData.suggested != null) string.append("<b>").append(dateUtil.minAgo(resourceHelper, deviceStatusOpenAPSData.clockSuggested)).append("</b> ").append(deviceStatusOpenAPSData.suggested!!.getString("reason")).append("<br>")
return fromHtml(string.toString()) return fromHtml(string.toString())
} catch (e: JSONException) { } catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e) aapsLogger.error("Unhandled exception", e)
@ -307,7 +307,7 @@ class NSDeviceStatus @Inject constructor(
val clock = val clock =
when { when {
jsonObject.has("mills") -> jsonObject.getLong("mills") jsonObject.has("mills") -> jsonObject.getLong("mills")
jsonObject.has("created_at") -> DateUtil.fromISODateString(jsonObject.getString("created_at")).time jsonObject.has("created_at") -> dateUtil.fromISODateString(jsonObject.getString("created_at"))
else -> 0L else -> 0L
} }
val device = device val device = device

View file

@ -1,8 +1,9 @@
package info.nightscout.androidaps.plugins.general.nsclient.data package info.nightscout.androidaps.plugins.general.nsclient.data
import android.content.Context import android.content.Context
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
@ -246,7 +247,7 @@ class NSSettingsStatus @Inject constructor(
getExtendedWarnValue("sage", "urgent")?.let { sp.putDouble(R.string.key_statuslights_sage_critical, it) } getExtendedWarnValue("sage", "urgent")?.let { sp.putDouble(R.string.key_statuslights_sage_critical, it) }
getExtendedWarnValue("bage", "warn")?.let { sp.putDouble(R.string.key_statuslights_bage_warning, it) } getExtendedWarnValue("bage", "warn")?.let { sp.putDouble(R.string.key_statuslights_bage_warning, it) }
getExtendedWarnValue("bage", "urgent")?.let { sp.putDouble(R.string.key_statuslights_bage_critical, it) } getExtendedWarnValue("bage", "urgent")?.let { sp.putDouble(R.string.key_statuslights_bage_critical, it) }
uel.log(Action.NS_SETTINGS_COPIED) uel.log(Action.NS_SETTINGS_COPIED, UserEntry.Sources.NSClient)
} }
if (context != null) OKDialog.showConfirmation(context, resourceHelper.gs(R.string.statuslights), resourceHelper.gs(R.string.copyexistingvalues), action) if (context != null) OKDialog.showConfirmation(context, resourceHelper.gs(R.string.statuslights), resourceHelper.gs(R.string.copyexistingvalues), action)

View file

@ -10,7 +10,6 @@ import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.work.OneTimeWorkRequest; import androidx.work.OneTimeWorkRequest;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
@ -30,12 +29,14 @@ import javax.inject.Inject;
import dagger.android.DaggerService; import dagger.android.DaggerService;
import dagger.android.HasAndroidInjector; import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.interfaces.Config;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.database.AppRepository;
import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.DataSyncSelector;
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.UploadQueueInterface; import info.nightscout.androidaps.interfaces.UploadQueueInterface;
@ -43,10 +44,12 @@ import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.food.FoodPlugin; import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddAckWorker;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker; import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker; import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker; import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientUpdateRemoveAckWorker;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck; import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck; import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck;
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck; import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck;
@ -96,6 +99,8 @@ public class NSClientService extends DaggerService {
@Inject DateUtil dateUtil; @Inject DateUtil dateUtil;
@Inject UploadQueueInterface uploadQueue; @Inject UploadQueueInterface uploadQueue;
@Inject DataWorker dataWorker; @Inject DataWorker dataWorker;
@Inject DataSyncSelector dataSyncSelector;
@Inject AppRepository repository;
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
@ -118,6 +123,7 @@ public class NSClientService extends DaggerService {
private final Integer nsHours = 48; private final Integer nsHours = 48;
public long lastResendTime = 0; public long lastResendTime = 0;
public long lastAckTime = 0;
public long latestDateInReceivedData = 0; public long latestDateInReceivedData = 0;
@ -126,7 +132,7 @@ public class NSClientService extends DaggerService {
private final ArrayList<Long> reconnections = new ArrayList<>(); private final ArrayList<Long> reconnections = new ArrayList<>();
private final int WATCHDOG_INTERVAL_MINUTES = 2; private final int WATCHDOG_INTERVAL_MINUTES = 2;
private final int WATCHDOG_RECONNECT_IN = 15; private final int WATCHDOG_RECONNECT_IN = 15;
private final int WATCHDOG_MAXCONNECTIONS = 5; private final int WATCHDOG_MAX_CONNECTIONS = 5;
public NSClientService() { public NSClientService() {
super(); super();
@ -213,6 +219,14 @@ public class NSClientService extends DaggerService {
} }
public void processAddAck(NSAddAck ack) { public void processAddAck(NSAddAck ack) {
lastAckTime = dateUtil.now();
// new room way
dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSClientAddAckWorker.class)
.setInputData(dataWorker.storeInputData(ack, null))
.build());
// old way
if (ack.nsClientID != null) { if (ack.nsClientID != null) {
uploadQueue.removeByNsClientIdIfExists(ack.json); uploadQueue.removeByNsClientIdIfExists(ack.json);
rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID)); rxBus.send(new EventNSClientNewLog("DBADD", "Acked " + ack.nsClientID));
@ -222,9 +236,17 @@ public class NSClientService extends DaggerService {
} }
public void processUpdateAck(NSUpdateAck ack) { public void processUpdateAck(NSUpdateAck ack) {
if (ack.result) { lastAckTime = dateUtil.now();
uploadQueue.removeByMongoId(ack.action, ack._id); // new room way
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack._id)); dataWorker.enqueue(
new OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker.class)
.setInputData(dataWorker.storeInputData(ack, null))
.build());
// old way
if (ack.getResult()) {
uploadQueue.removeByMongoId(ack.getAction(), ack.get_id());
rxBus.send(new EventNSClientNewLog("DBUPDATE/DBREMOVE", "Acked " + ack.get_id()));
} else { } else {
rxBus.send(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response")); rxBus.send(new EventNSClientNewLog("ERROR", "DBUPDATE/DBREMOVE Unknown response"));
} }
@ -258,6 +280,7 @@ public class NSClientService extends DaggerService {
public NSClientService getServiceInstance() { public NSClientService getServiceInstance() {
return NSClientService.this; return NSClientService.this;
} }
} }
@Override @Override
@ -337,7 +360,7 @@ public class NSClientService extends DaggerService {
void watchdog() { void watchdog() {
synchronized (reconnections) { synchronized (reconnections) {
long now = DateUtil.now(); long now = dateUtil.now();
reconnections.add(now); reconnections.add(now);
for (int i = 0; i < reconnections.size(); i++) { for (int i = 0; i < reconnections.size(); i++) {
Long r = reconnections.get(i); Long r = reconnections.get(i);
@ -345,8 +368,8 @@ public class NSClientService extends DaggerService {
reconnections.remove(r); reconnections.remove(r);
} }
} }
rxBus.send(new EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " mins: " + reconnections.size() + "/" + WATCHDOG_MAXCONNECTIONS)); rxBus.send(new EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " mins: " + reconnections.size() + "/" + WATCHDOG_MAX_CONNECTIONS));
if (reconnections.size() >= WATCHDOG_MAXCONNECTIONS) { if (reconnections.size() >= WATCHDOG_MAX_CONNECTIONS) {
Notification n = new Notification(Notification.NS_MALFUNCTION, resourceHelper.gs(R.string.nsmalfunction), Notification.URGENT); Notification n = new Notification(Notification.NS_MALFUNCTION, resourceHelper.gs(R.string.nsmalfunction), Notification.URGENT);
rxBus.send(new EventNewNotification(n)); rxBus.send(new EventNewNotification(n));
rxBus.send(new EventNSClientNewLog("WATCHDOG", "pausing for " + WATCHDOG_RECONNECT_IN + " mins")); rxBus.send(new EventNSClientNewLog("WATCHDOG", "pausing for " + WATCHDOG_RECONNECT_IN + " mins"));
@ -579,7 +602,7 @@ public class NSClientService extends DaggerService {
if (action == null) addedOrUpdatedTreatments.put(jsonTreatment); if (action == null) addedOrUpdatedTreatments.put(jsonTreatment);
else if (action.equals("update")) else if (action.equals("update"))
addedOrUpdatedTreatments.put(jsonTreatment); addedOrUpdatedTreatments.put(jsonTreatment);
else if (action.equals("remove") && mills > dateUtil._now() - T.days(1).msecs()) // handle 1 day old deletions only else if (action.equals("remove") && mills > dateUtil.now() - T.days(1).msecs()) // handle 1 day old deletions only
removedTreatments.put(jsonTreatment); removedTreatments.put(jsonTreatment);
} }
if (removedTreatments.length() > 0) { if (removedTreatments.length() > 0) {
@ -698,15 +721,15 @@ public class NSClientService extends DaggerService {
} }
} }
public void dbUpdateUnset(DbRequest dbr, NSUpdateAck ack) { public void dbUpdate(String collection, String _id, JSONObject data, Object originalObject) {
try { try {
if (!isConnected || !hasWriteAuth) return; if (!isConnected || !hasWriteAuth) return;
JSONObject message = new JSONObject(); JSONObject message = new JSONObject();
message.put("collection", dbr.collection); message.put("collection", collection);
message.put("_id", dbr._id); message.put("_id", _id);
message.put("data", new JSONObject(dbr.data)); message.put("data", data);
mSocket.emit("dbUpdateUnset", message, ack); mSocket.emit("dbUpdate", message, new NSUpdateAck("dbUpdate", _id, aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBUPDATEUNSET " + dbr.collection, "Sent " + dbr._id)); rxBus.send(new EventNSClientNewLog("DBUPDATE " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + _id));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
} }
@ -725,6 +748,19 @@ public class NSClientService extends DaggerService {
} }
} }
public void dbRemove(String collection, String _id, Object originalObject) {
try {
if (!isConnected || !hasWriteAuth) return;
JSONObject message = new JSONObject();
message.put("collection", collection);
message.put("_id", _id);
mSocket.emit("dbRemove", message, new NSUpdateAck("dbRemove", _id, aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBREMOVE " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + _id));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void dbAdd(DbRequest dbr, NSAddAck ack) { public void dbAdd(DbRequest dbr, NSAddAck ack) {
try { try {
if (!isConnected || !hasWriteAuth) return; if (!isConnected || !hasWriteAuth) return;
@ -738,6 +774,19 @@ public class NSClientService extends DaggerService {
} }
} }
public void dbAdd(String collection, JSONObject data, Object originalObject) {
try {
if (!isConnected || !hasWriteAuth) return;
JSONObject message = new JSONObject();
message.put("collection", collection);
message.put("data", data);
mSocket.emit("dbAdd", message, new NSAddAck(aapsLogger, rxBus, originalObject));
rxBus.send(new EventNSClientNewLog("DBADD " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + data));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
}
public void sendAlarmAck(AlarmAck alarmAck) { public void sendAlarmAck(AlarmAck alarmAck) {
if (!isConnected || !hasWriteAuth) return; if (!isConnected || !hasWriteAuth) return;
mSocket.emit("ack", alarmAck.level, alarmAck.group, alarmAck.silenceTime); mSocket.emit("ack", alarmAck.level, alarmAck.group, alarmAck.silenceTime);
@ -745,22 +794,38 @@ public class NSClientService extends DaggerService {
} }
public void resend(final String reason) { public void resend(final String reason) {
if (uploadQueue.size() == 0)
return;
if (!isConnected || !hasWriteAuth) return; if (!isConnected || !hasWriteAuth) return;
handler.post(() -> { handler.post(() -> {
if (mSocket == null || !mSocket.connected()) return; if (mSocket == null || !mSocket.connected()) return;
rxBus.send(new EventNSClientNewLog("QUEUE", "Resend started: " + reason));
if (lastAckTime > System.currentTimeMillis() - 10 * 1000L) {
aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastAckTime: " + ((System.currentTimeMillis() - lastAckTime) / 1000L) + " sec");
return;
}
dataSyncSelector.processChangedBolusesCompat();
dataSyncSelector.processChangedCarbsCompat();
dataSyncSelector.processChangedBolusCalculatorResultsCompat();
dataSyncSelector.processChangedTemporaryBasalsCompat();
dataSyncSelector.processChangedExtendedBolusesCompat();
dataSyncSelector.processChangedGlucoseValuesCompat();
dataSyncSelector.processChangedTempTargetsCompat();
dataSyncSelector.processChangedFoodsCompat();
dataSyncSelector.processChangedTherapyEventsCompat();
dataSyncSelector.processChangedDeviceStatusesCompat();
if (uploadQueue.size() == 0)
return;
if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) { if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) {
aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec"); aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec");
return; return;
} }
lastResendTime = System.currentTimeMillis(); lastResendTime = System.currentTimeMillis();
rxBus.send(new EventNSClientNewLog("QUEUE", "Resend started: " + reason));
CloseableIterator<DbRequest> iterator; CloseableIterator<DbRequest> iterator;
int maxcount = 30; int maxcount = 30;
try { try {
@ -769,17 +834,14 @@ public class NSClientService extends DaggerService {
while (iterator.hasNext() && maxcount > 0) { while (iterator.hasNext() && maxcount > 0) {
DbRequest dbr = iterator.next(); DbRequest dbr = iterator.next();
if (dbr.action.equals("dbAdd")) { if (dbr.action.equals("dbAdd")) {
NSAddAck addAck = new NSAddAck(aapsLogger, rxBus); NSAddAck addAck = new NSAddAck(aapsLogger, rxBus, null);
dbAdd(dbr, addAck); dbAdd(dbr, addAck);
} else if (dbr.action.equals("dbRemove")) { } else if (dbr.action.equals("dbRemove")) {
NSUpdateAck removeAck = new NSUpdateAck(dbr.action, dbr._id, aapsLogger, rxBus); NSUpdateAck removeAck = new NSUpdateAck("dbRemove", dbr._id, aapsLogger, rxBus, null);
dbRemove(dbr, removeAck); dbRemove(dbr, removeAck);
} else if (dbr.action.equals("dbUpdate")) { } else if (dbr.action.equals("dbUpdate")) {
NSUpdateAck updateAck = new NSUpdateAck(dbr.action, dbr._id, aapsLogger, rxBus); NSUpdateAck updateAck = new NSUpdateAck("dbUpdate", dbr._id, aapsLogger, rxBus, null);
dbUpdate(dbr, updateAck); dbUpdate(dbr, updateAck);
} else if (dbr.action.equals("dbUpdateUnset")) {
NSUpdateAck updateUnsetAck = new NSUpdateAck(dbr.action, dbr._id, aapsLogger, rxBus);
dbUpdateUnset(dbr, updateUnsetAck);
} }
maxcount--; maxcount--;
} }
@ -838,32 +900,6 @@ public class NSClientService extends DaggerService {
} }
} }
public void handleNewTreatment(JSONArray treatments, boolean isDelta) {
List<JSONArray> splitted = splitArray(treatments);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("treatments", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
splitted = splitArray(treatments);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("treatments", part.toString());
bundle.putBoolean("delta", isDelta);
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.getApplicationContext().sendBroadcast(intent);
}
}
}
public List<JSONArray> splitArray(JSONArray array) { public List<JSONArray> splitArray(JSONArray array) {
List<JSONArray> ret = new ArrayList<>(); List<JSONArray> ret = new ArrayList<>();
try { try {

View file

@ -28,8 +28,7 @@ import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.extensions.toConstant
import info.nightscout.androidaps.utils.extensions.toConstant
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -61,7 +60,6 @@ class OpenHumansUploader @Inject constructor(
private val sp: SP, private val sp: SP,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val context: Context, private val context: Context,
private val treatmentsPlugin: TreatmentsPlugin,
private val databaseHelper: DatabaseHelperInterface, private val databaseHelper: DatabaseHelperInterface,
val repository: AppRepository val repository: AppRepository
) : PluginBase( ) : PluginBase(
@ -356,29 +354,29 @@ class OpenHumansUploader @Inject constructor(
if (currentProgress % 1000L == 0L) showOngoingNotification(maxProgress, currentProgress) if (currentProgress % 1000L == 0L) showOngoingNotification(maxProgress, currentProgress)
} }
copyDisposable = Completable.fromCallable { databaseHelper.clearOpenHumansQueue() } copyDisposable = Completable.fromCallable { databaseHelper.clearOpenHumansQueue() }
.andThen(Single.defer { Single.just(databaseHelper.getCountOfAllRows() + treatmentsPlugin.service.count()) }) // .andThen(Single.defer { Single.just(databaseHelper.getCountOfAllRows() + treatmentsPlugin.service.count()) })
.doOnSuccess { maxProgress = it } // .doOnSuccess { maxProgress = it }
.flatMapObservable { Observable.defer { Observable.fromIterable(treatmentsPlugin.service.getTreatmentData()) } } // .flatMapObservable { Observable.defer { Observable.fromIterable(treatmentsPlugin.service.getTreatmentData()) } }
.map { enqueueTreatment(it); increaseCounter() } // .map { enqueueTreatment(it); increaseCounter() }
.ignoreElements() // .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(repository.compatGetBgReadingsDataFromTime(0, true).blockingGet()) }) .andThen(Observable.defer { Observable.fromIterable(repository.compatGetBgReadingsDataFromTime(0, true).blockingGet()) })
.map { enqueueBGReading(it); increaseCounter() } .map { enqueueBGReading(it); increaseCounter() }
.ignoreElements() .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(repository.compatGetTherapyEventDataFromTime(0, true).blockingGet()) }) .andThen(Observable.defer { Observable.fromIterable(repository.compatGetTherapyEventDataFromTime(0, true).blockingGet()) })
.map { enqueueTherapyEvent(it); increaseCounter() } .map { enqueueTherapyEvent(it); increaseCounter() }
.ignoreElements() .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllExtendedBoluses()) }) // .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllExtendedBoluses()) })
.map { enqueueExtendedBolus(it); increaseCounter() } // .map { enqueueExtendedBolus(it); increaseCounter() }
.ignoreElements() // .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllProfileSwitches()) }) .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllProfileSwitches()) })
.map { enqueueProfileSwitch(it); increaseCounter() } .map { enqueueProfileSwitch(it); increaseCounter() }
.ignoreElements() .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTDDs()) }) .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTDDs()) })
.map { enqueueTotalDailyDose(it); increaseCounter() } .map { enqueueTotalDailyDose(it); increaseCounter() }
.ignoreElements() .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTemporaryBasals()) }) // .andThen(Observable.defer { Observable.fromIterable(databaseHelper.getAllTemporaryBasals()) })
.map { enqueueTemporaryBasal(it); increaseCounter() } // .map { enqueueTemporaryBasal(it); increaseCounter() }
.ignoreElements() // .ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(repository.compatGetTemporaryTargetData().blockingGet()) }) .andThen(Observable.defer { Observable.fromIterable(repository.compatGetTemporaryTargetData().blockingGet()) })
.map { enqueueTempTarget(it); increaseCounter() } .map { enqueueTempTarget(it); increaseCounter() }
.ignoreElements() .ignoreElements()

View file

@ -24,33 +24,34 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.jjoe64.graphview.GraphView import com.jjoe64.graphview.GraphView
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TemporaryTarget
import info.nightscout.androidaps.database.entities.UserEntry.* import info.nightscout.androidaps.database.entities.UserEntry.Action
import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.interfaces.end import info.nightscout.androidaps.database.interfaces.end
import info.nightscout.androidaps.databinding.OverviewFragmentBinding import info.nightscout.androidaps.databinding.OverviewFragmentBinding
import info.nightscout.androidaps.dialogs.* import info.nightscout.androidaps.dialogs.*
import info.nightscout.androidaps.events.* import info.nightscout.androidaps.events.*
import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.source.DexcomPlugin import info.nightscout.androidaps.plugins.source.DexcomPlugin
@ -61,10 +62,7 @@ import info.nightscout.androidaps.skins.SkinProvider
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.directionToIcon import info.nightscout.androidaps.utils.extensions.*
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.extensions.valueToUnits
import info.nightscout.androidaps.utils.extensions.valueToUnitsString
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -97,10 +95,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
@Inject lateinit var statusLightHandler: StatusLightHandler @Inject lateinit var statusLightHandler: StatusLightHandler
@Inject lateinit var nsDeviceStatus: NSDeviceStatus @Inject lateinit var nsDeviceStatus: NSDeviceStatus
@Inject lateinit var loopPlugin: LoopPlugin @Inject lateinit var loopPlugin: LoopPlugin
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var dexcomPlugin: DexcomPlugin @Inject lateinit var dexcomPlugin: DexcomPlugin
@Inject lateinit var dexcomMediator: DexcomPlugin.DexcomMediator @Inject lateinit var dexcomMediator: DexcomPlugin.DexcomMediator
@Inject lateinit var xdripPlugin: XdripPlugin @Inject lateinit var xdripPlugin: XdripPlugin
@ -310,7 +307,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
R.id.active_profile -> { R.id.active_profile -> {
ProfileViewerDialog().also { pvd -> ProfileViewerDialog().also { pvd ->
pvd.arguments = Bundle().also { pvd.arguments = Bundle().also {
it.putLong("time", DateUtil.now()) it.putLong("time", dateUtil.now())
it.putInt("mode", ProfileViewerDialog.Mode.RUNNING_PROFILE.ordinal) it.putInt("mode", ProfileViewerDialog.Mode.RUNNING_PROFILE.ordinal)
} }
}.show(childFragmentManager, "ProfileViewDialog") }.show(childFragmentManager, "ProfileViewDialog")
@ -351,7 +348,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned() OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
?: "".toSpanned(), { ?: "".toSpanned(), {
uel.log(Action.ACCEPTS_TEMP_BASAL) uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
binding.buttonsLayout.acceptTempButton.visibility = View.GONE binding.buttonsLayout.acceptTempButton.visibility = View.GONE
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID) (context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID)
rxBus.send(EventWearInitiateAction("cancelChangeRequest")) rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
@ -412,7 +409,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
private fun onClickQuickWizard() { private fun onClickQuickWizard() {
val actualBg = iobCobCalculatorPlugin.actualBg() val actualBg = iobCobCalculator.ads.actualBg()
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()
val profileName = profileFunction.getProfileName() val profileName = profileFunction.getProfileName()
val pump = activePlugin.activePump val pump = activePlugin.activePump
@ -447,11 +444,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun processButtonsVisibility() { private fun processButtonsVisibility() {
val lastBG = iobCobCalculatorPlugin.lastBg() val lastBG = iobCobCalculator.ads.lastBg()
val pump = activePlugin.activePump val pump = activePlugin.activePump
val profile = profileFunction.getProfile() val profile = profileFunction.getProfile()
val profileName = profileFunction.getProfileName() val profileName = profileFunction.getProfileName()
val actualBG = iobCobCalculatorPlugin.actualBg() val actualBG = iobCobCalculator.ads.actualBg()
// QuickWizard button // QuickWizard button
val quickWizardEntry = quickWizard.getActive() val quickWizardEntry = quickWizard.getActive()
@ -550,7 +547,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (_binding == null) return if (_binding == null) return
aapsLogger.debug("UpdateGUI from $from") aapsLogger.debug("UpdateGUI from $from")
binding.infoLayout.time.text = dateUtil.timeString(Date()) binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now())
if (!profileFunction.isProfileValid("Overview")) { if (!profileFunction.isProfileValid("Overview")) {
binding.loopPumpStatusLayout.pumpStatus.setText(R.string.noprofileset) binding.loopPumpStatusLayout.pumpStatus.setText(R.string.noprofileset)
@ -563,8 +560,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.loopPumpStatusLayout.loopLayout.visibility = View.VISIBLE binding.loopPumpStatusLayout.loopLayout.visibility = View.VISIBLE
val profile = profileFunction.getProfile() ?: return val profile = profileFunction.getProfile() ?: return
val actualBG = iobCobCalculatorPlugin.actualBg() val actualBG = iobCobCalculator.ads.actualBg()
val lastBG = iobCobCalculatorPlugin.lastBg() val lastBG = iobCobCalculator.ads.lastBg()
val pump = activePlugin.activePump val pump = activePlugin.activePump
val units = profileFunction.getUnits() val units = profileFunction.getUnits()
val lowLine = defaultValueHelper.determineLowLine() val lowLine = defaultValueHelper.determineLowLine()
@ -613,8 +610,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} else flag and Paint.STRIKE_THRU_TEXT_FLAG.inv() } else flag and Paint.STRIKE_THRU_TEXT_FLAG.inv()
overview_bg.paintFlags = flag overview_bg.paintFlags = flag
} }
binding.infoLayout.timeAgo.text = DateUtil.minAgo(resourceHelper, lastBG.timestamp) binding.infoLayout.timeAgo.text = dateUtil.minAgo(resourceHelper, lastBG.timestamp)
binding.infoLayout.timeAgoShort.text = "(" + DateUtil.minAgoShort(lastBG.timestamp) + ")" binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(lastBG.timestamp) + ")"
} }
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed() val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
@ -626,24 +623,24 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
when { when {
loopPlugin.isEnabled() && loopPlugin.isSuperBolus -> { loopPlugin.isEnabled() && loopPlugin.isSuperBolus -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus) binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus)
binding.infoLayout.apsModeText.text = DateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper) binding.infoLayout.apsModeText.text = dateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper)
binding.infoLayout.apsModeText.visibility = View.VISIBLE binding.infoLayout.apsModeText.visibility = View.VISIBLE
} }
loopPlugin.isDisconnected -> { loopPlugin.isDisconnected -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected) binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected)
binding.infoLayout.apsModeText.text = DateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper) binding.infoLayout.apsModeText.text = dateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper)
binding.infoLayout.apsModeText.visibility = View.VISIBLE binding.infoLayout.apsModeText.visibility = View.VISIBLE
} }
loopPlugin.isEnabled() && loopPlugin.isSuspended -> { loopPlugin.isEnabled() && loopPlugin.isSuspended -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused) binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused)
binding.infoLayout.apsModeText.text = DateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper) binding.infoLayout.apsModeText.text = dateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper)
binding.infoLayout.apsModeText.visibility = View.VISIBLE binding.infoLayout.apsModeText.visibility = View.VISIBLE
} }
pump.isSuspended() -> { pump.isSuspended() -> {
binding.infoLayout.apsMode.setImageResource(if (pump.model() == PumpType.Omnipod_Eros || pump.model() == PumpType.Omnipod_Dash) { binding.infoLayout.apsMode.setImageResource(if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
// For Omnipod, indicate the pump as disconnected when it's suspended. // For Omnipod, indicate the pump as disconnected when it's suspended.
// The only way to 'reconnect' it, is through the Omnipod tab // The only way to 'reconnect' it, is through the Omnipod tab
R.drawable.ic_loop_disconnected R.drawable.ic_loop_disconnected
@ -681,11 +678,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
// temp target // temp target
val tempTarget: ValueWrapper<TemporaryTarget> = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() val tempTarget: ValueWrapper<TemporaryTarget> = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (tempTarget is ValueWrapper.Existing) { if (tempTarget is ValueWrapper.Existing) {
binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) binding.loopPumpStatusLayout.tempTarget.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) binding.loopPumpStatusLayout.tempTarget.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.highTarget, Constants.MGDL, units) + " " + DateUtil.untilString(tempTarget.value.end, resourceHelper) binding.loopPumpStatusLayout.tempTarget.text = Profile.toTargetRangeString(tempTarget.value.lowTarget, tempTarget.value.highTarget, Constants.MGDL, units) + " " + dateUtil.untilString(tempTarget.value.end, resourceHelper)
} else { } else {
// If the target is not the same as set in the profile then oref has overridden it // If the target is not the same as set in the profile then oref has overridden it
val targetUsed = lastRun?.constraintsProcessed?.targetBG ?: 0.0 val targetUsed = lastRun?.constraintsProcessed?.targetBG ?: 0.0
@ -703,13 +700,13 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
// Basal, TBR // Basal, TBR
val activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis())
binding.infoLayout.baseBasal.text = activeTemp?.let { "T:" + activeTemp.toStringVeryShort() } binding.infoLayout.baseBasal.text = activeTemp?.let { "T:" + activeTemp.toStringShort() }
?: resourceHelper.gs(R.string.pump_basebasalrate, profile.basal) ?: resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)
binding.infoLayout.basalLayout.setOnClickListener { binding.infoLayout.basalLayout.setOnClickListener {
var fullText = "${resourceHelper.gs(R.string.basebasalrate_label)}: ${resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)}" var fullText = "${resourceHelper.gs(R.string.basebasalrate_label)}: ${resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)}"
if (activeTemp != null) if (activeTemp != null)
fullText += "\n" + resourceHelper.gs(R.string.tempbasal_label) + ": " + activeTemp.toStringFull() fullText += "\n" + resourceHelper.gs(R.string.tempbasal_label) + ": " + activeTemp.toStringFull(profile, dateUtil)
activity?.let { activity?.let {
OKDialog.show(it, resourceHelper.gs(R.string.basal), fullText) OKDialog.show(it, resourceHelper.gs(R.string.basal), fullText)
} }
@ -718,23 +715,23 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
?: resourceHelper.gc(R.color.defaulttextcolor)) ?: resourceHelper.gc(R.color.defaulttextcolor))
binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_no_tbr) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_no_tbr)
val percentRate = activeTemp?.tempBasalConvertedToPercent(System.currentTimeMillis(), profile) val percentRate = activeTemp?.convertedToPercent(System.currentTimeMillis(), profile)
?: 100 ?: 100
if (percentRate > 100) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_tbr_high) if (percentRate > 100) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_tbr_high)
if (percentRate < 100) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_tbr_low) if (percentRate < 100) binding.infoLayout.baseBasalIcon.setImageResource(R.drawable.ic_cp_basal_tbr_low)
// Extended bolus // Extended bolus
val extendedBolus = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis()) val extendedBolus = repository.getExtendedBolusActiveAt(dateUtil.now()).blockingGet()
binding.infoLayout.extendedBolus.text = binding.infoLayout.extendedBolus.text =
if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses) if (extendedBolus is ValueWrapper.Existing && !pump.isFakingTempsByExtendedBoluses)
resourceHelper.gs(R.string.pump_basebasalrate, extendedBolus.absoluteRate()) resourceHelper.gs(R.string.pump_basebasalrate, extendedBolus.value.rate)
else "" else ""
binding.infoLayout.extendedBolus.setOnClickListener { binding.infoLayout.extendedBolus.setOnClickListener {
if (extendedBolus != null) activity?.let { if (extendedBolus is ValueWrapper.Existing) activity?.let {
OKDialog.show(it, resourceHelper.gs(R.string.extended_bolus), extendedBolus.toString()) OKDialog.show(it, resourceHelper.gs(R.string.extended_bolus), extendedBolus.value.toStringFull(dateUtil))
} }
} }
binding.infoLayout.extendedLayout.visibility = (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses).toVisibility() binding.infoLayout.extendedLayout.visibility = (extendedBolus is ValueWrapper.Existing && !pump.isFakingTempsByExtendedBoluses).toVisibility()
// Active profile // Active profile
binding.loopPumpStatusLayout.activeProfile.text = profileFunction.getProfileNameWithDuration() binding.loopPumpStatusLayout.activeProfile.text = profileFunction.getProfileNameWithDuration()
@ -749,10 +746,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
processButtonsVisibility() processButtonsVisibility()
// iob // iob
treatmentsPlugin.updateTotalIOBTreatments() val bolusIob = iobCobCalculator.calculateIobFromBolus().round()
treatmentsPlugin.updateTotalIOBTempBasals() val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
val bolusIob = treatmentsPlugin.lastCalculationTreatments.round()
val basalIob = treatmentsPlugin.lastCalculationTempBasals.round()
binding.infoLayout.iob.text = resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) binding.infoLayout.iob.text = resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob)
binding.infoLayout.iobLayout.setOnClickListener { binding.infoLayout.iobLayout.setOnClickListener {
@ -771,7 +766,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// cob // cob
var cobText: String = resourceHelper.gs(R.string.value_unavailable_short) var cobText: String = resourceHelper.gs(R.string.value_unavailable_short)
val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Overview COB") val cobInfo = iobCobCalculator.getCobInfo(false, "Overview COB")
if (cobInfo.displayCob != null) { if (cobInfo.displayCob != null) {
cobText = resourceHelper.gs(R.string.format_carbs, cobInfo.displayCob!!.toInt()) cobText = resourceHelper.gs(R.string.format_carbs, cobInfo.displayCob!!.toInt())
if (cobInfo.futureCarbs > 0) cobText += "(" + DecimalFormatter.to0Decimal(cobInfo.futureCarbs) + ")" if (cobInfo.futureCarbs > 0) cobText += "(" + DecimalFormatter.to0Decimal(cobInfo.futureCarbs) + ")"
@ -780,7 +775,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (config.APS && lastRun?.constraintsProcessed != null) { if (config.APS && lastRun?.constraintsProcessed != null) {
if (lastRun.constraintsProcessed!!.carbsReq > 0) { if (lastRun.constraintsProcessed!!.carbsReq > 0) {
//only display carbsreq when carbs have not been entered recently //only display carbsreq when carbs have not been entered recently
if (treatmentsPlugin.lastCarbTime < lastRun.lastAPSRun) { val lastCarb = repository.getLastCarbsRecordWrapped().blockingGet()
val lastCarbsTime = if (lastCarb is ValueWrapper.Existing) lastCarb.value.timestamp else 0L
if (lastCarbsTime < lastRun.lastAPSRun) {
cobText = cobText + " | " + lastRun.constraintsProcessed!!.carbsReq + " " + resourceHelper.gs(R.string.required) cobText = cobText + " | " + lastRun.constraintsProcessed!!.carbsReq + " " + resourceHelper.gs(R.string.required)
} }
binding.infoLayout.cob.text = cobText binding.infoLayout.cob.text = cobText
@ -813,17 +810,17 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
binding.infoLayout.sensitivity.text = binding.infoLayout.sensitivity.text =
iobCobCalculatorPlugin.getLastAutosensData("Overview")?.let { autosensData -> iobCobCalculator.ads.getLastAutosensData("Overview", aapsLogger, dateUtil)?.let { autosensData ->
String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100) String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
} ?: "" } ?: ""
} }
private fun updateGraph(lastRun: LoopInterface.LastRun?, predictionsAvailable: Boolean, lowLine: Double, highLine: Double, pump: PumpInterface, profile: Profile) { private fun updateGraph(lastRun: LoopInterface.LastRun?, predictionsAvailable: Boolean, lowLine: Double, highLine: Double, pump: Pump, profile: Profile) {
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
if (_binding == null) return@launch if (_binding == null) return@launch
val menuChartSettings = overviewMenus.setting val menuChartSettings = overviewMenus.setting
prepareGraphsIfNeeded(menuChartSettings.size) prepareGraphsIfNeeded(menuChartSettings.size)
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, iobCobCalculatorPlugin, treatmentsPlugin) val graphData = GraphData(injector, binding.graphsLayout.bgGraph, iobCobCalculator, treatmentsPlugin)
val secondaryGraphsData: ArrayList<GraphData> = ArrayList() val secondaryGraphsData: ArrayList<GraphData> = ArrayList()
// do preparation in different thread // do preparation in different thread
@ -863,8 +860,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// **** BG **** // **** BG ****
if (predictionsAvailable && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) if (predictionsAvailable && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, apsResult?.predictions) graphData.addBgReadings(fromTime, toTime, highLine, apsResult?.predictions?.map { bg-> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper) }?.toMutableList())
else graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null) else graphData.addBgReadings(fromTime, toTime, highLine, null)
if (buildHelper.isDev()) graphData.addBucketedData(fromTime, toTime)
// Treatments // Treatments
graphData.addTreatments(fromTime, endTime) graphData.addTreatments(fromTime, endTime)
@ -890,7 +888,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// ------------------ 2nd graph // ------------------ 2nd graph
synchronized(graphLock) { synchronized(graphLock) {
for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) { for (g in 0 until min(secondaryGraphs.size, menuChartSettings.size + 1)) {
val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPlugin, treatmentsPlugin) val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculator, treatmentsPlugin)
var useABSForScale = false var useABSForScale = false
var useIobForScale = false var useIobForScale = false
var useCobForScale = false var useCobForScale = false

View file

@ -9,7 +9,7 @@ import androidx.annotation.ColorRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import com.google.gson.Gson import com.google.gson.Gson
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger

View file

@ -3,10 +3,11 @@ package info.nightscout.androidaps.plugins.general.overview
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference import androidx.preference.SwitchPreference
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventRefreshOverview
import info.nightscout.androidaps.interfaces.OverviewInterface import info.nightscout.androidaps.extensions.*
import info.nightscout.androidaps.interfaces.Overview
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
@ -16,7 +17,6 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNo
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.extensions.*
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -48,7 +48,7 @@ class OverviewPlugin @Inject constructor(
.preferencesId(R.xml.pref_overview) .preferencesId(R.xml.pref_overview)
.description(R.string.description_overview), .description(R.string.description_overview),
aapsLogger, resourceHelper, injector aapsLogger, resourceHelper, injector
), OverviewInterface { ), Overview {
private var disposable: CompositeDisposable = CompositeDisposable() private var disposable: CompositeDisposable = CompositeDisposable()

View file

@ -3,18 +3,19 @@ package info.nightscout.androidaps.plugins.general.overview
import android.graphics.Color import android.graphics.Color
import android.widget.TextView import android.widget.TextView
import androidx.annotation.StringRes import androidx.annotation.StringRes
import info.nightscout.androidaps.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.WarnColors import info.nightscout.androidaps.utils.WarnColors
import info.nightscout.androidaps.utils.extensions.age import info.nightscout.androidaps.extensions.age
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
@ -24,7 +25,8 @@ import javax.inject.Singleton
class StatusLightHandler @Inject constructor( class StatusLightHandler @Inject constructor(
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val sp: SP, private val sp: SP,
private val activePlugin: ActivePluginProvider, private val dateUtil: DateUtil,
private val activePlugin: ActivePlugin,
private val warnColors: WarnColors, private val warnColors: WarnColors,
private val config: Config, private val config: Config,
private val repository: AppRepository private val repository: AppRepository
@ -43,7 +45,7 @@ class StatusLightHandler @Inject constructor(
handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0) handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0)
} }
if (!config.NSCLIENT) { if (!config.NSCLIENT) {
if (pump.model() == PumpType.Omnipod_Eros || pump.model() == PumpType.Omnipod_Dash) { if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) {
handleOmnipodReservoirLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") handleOmnipodReservoirLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U")
} else { } else {
handleLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U") handleLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, "U")
@ -55,15 +57,15 @@ class StatusLightHandler @Inject constructor(
} }
if (!config.NSCLIENT) { if (!config.NSCLIENT) {
if (pump.model() == PumpType.Omnipod_Dash) { if (pump.model() == PumpType.OMNIPOD_DASH) {
// Omnipod Dash does not report its battery level // Omnipod Dash does not report its battery level
careportal_battery_level?.text = resourceHelper.gs(R.string.notavailable) careportal_battery_level?.text = resourceHelper.gs(R.string.notavailable)
careportal_battery_level?.setTextColor(Color.WHITE) careportal_battery_level?.setTextColor(Color.WHITE)
} else if (pump.model() == PumpType.Omnipod_Eros && pump is OmnipodErosPumpPlugin) { // instance of check is needed because at startup, pump can still be VirtualPumpPlugin and that will cause a crash because of the class cast below } else if (pump.model() == PumpType.OMNIPOD_EROS && pump is OmnipodErosPumpPlugin) { // instance of check is needed because at startup, pump can still be VirtualPumpPlugin and that will cause a crash because of the class cast below
// The Omnipod Eros does not report its battery level. However, some RileyLink alternatives do. // The Omnipod Eros does not report its battery level. However, some RileyLink alternatives do.
// Depending on the user's configuration, we will either show the battery level reported by the RileyLink or "n/a" // Depending on the user's configuration, we will either show the battery level reported by the RileyLink or "n/a"
handleOmnipodErosBatteryLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%", pump.isUseRileyLinkBatteryLevel) handleOmnipodErosBatteryLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%", pump.isUseRileyLinkBatteryLevel)
} else if (pump.model() != PumpType.AccuChekCombo) { } else if (pump.model() != PumpType.ACCU_CHEK_COMBO) {
handleLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%") handleLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%")
} }
} }
@ -75,7 +77,7 @@ class StatusLightHandler @Inject constructor(
val therapyEvent = repository.getLastTherapyRecord(type).blockingGet() val therapyEvent = repository.getLastTherapyRecord(type).blockingGet()
if (therapyEvent is ValueWrapper.Existing) { if (therapyEvent is ValueWrapper.Existing) {
warnColors.setColorByAge(view, therapyEvent.value, warn, urgent) warnColors.setColorByAge(view, therapyEvent.value, warn, urgent)
view?.text = therapyEvent.value.age(resourceHelper.shortTextMode(), resourceHelper) view?.text = therapyEvent.value.age(resourceHelper.shortTextMode(), resourceHelper, dateUtil)
} else { } else {
view?.text = if (resourceHelper.shortTextMode()) "-" else resourceHelper.gs(R.string.notavailable) view?.text = if (resourceHelper.shortTextMode()) "-" else resourceHelper.gs(R.string.notavailable)
} }

View file

@ -83,7 +83,7 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
// create an OnTimeSetListener // create an OnTimeSetListener
val fromTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute -> val fromTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
fromSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt() fromSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt()
binding.from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) binding.from.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(fromSeconds))
} }
binding.from.setOnClickListener { binding.from.setOnClickListener {
@ -96,11 +96,11 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
} }
} }
fromSeconds = entry.validFrom() fromSeconds = entry.validFrom()
binding.from.text = dateUtil.timeString(DateUtil.toDate(fromSeconds)) binding.from.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(fromSeconds))
val toTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute -> val toTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
toSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt() toSeconds = (T.hours(hour.toLong()).secs() + T.mins(minute.toLong()).secs()).toInt()
binding.from.text = dateUtil.timeString(DateUtil.toDate(toSeconds)) binding.from.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds))
} }
binding.to.setOnClickListener { binding.to.setOnClickListener {
@ -113,7 +113,7 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
} }
} }
toSeconds = entry.validFrom() toSeconds = entry.validFrom()
binding.to.text = dateUtil.timeString(DateUtil.toDate(toSeconds)) binding.to.text = dateUtil.timeString(dateUtil.secondsOfTheDayToMilliseconds(toSeconds))
binding.buttonEdit.setText(entry.buttonText()) binding.buttonEdit.setText(entry.buttonText())
binding.carbsEdit.setText(entry.carbs().toString()) binding.carbsEdit.setText(entry.carbs().toString())

View file

@ -11,28 +11,20 @@ import com.jjoe64.graphview.series.Series
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.GlucoseValueDataPoint
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.TherapyEventDataPoint
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
import info.nightscout.androidaps.interfaces.LoopInterface
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.TreatmentsInterface
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.* import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.extensions.target
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -43,7 +35,7 @@ import kotlin.math.min
class GraphData( class GraphData(
private val injector: HasAndroidInjector, private val injector: HasAndroidInjector,
private val graph: GraphView, private val graph: GraphView,
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val iobCobCalculator: IobCobCalculator,
private val treatmentsPlugin: TreatmentsInterface private val treatmentsPlugin: TreatmentsInterface
) { ) {
@ -51,10 +43,12 @@ class GraphData(
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider @Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var databaseHelper: DatabaseHelperInterface @Inject lateinit var databaseHelper: DatabaseHelperInterface
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var translator: Translator
var maxY = Double.MIN_VALUE var maxY = Double.MIN_VALUE
private var minY = Double.MAX_VALUE private var minY = Double.MAX_VALUE
@ -67,10 +61,23 @@ class GraphData(
units = profileFunction.getUnits() units = profileFunction.getUnits()
} }
@Suppress("UNUSED_PARAMETER") fun addBucketedData(fromTime: Long, toTime: Long) {
fun addBgReadings(fromTime: Long, toTime: Long, lowLine: Double, highLine: Double, predictions: MutableList<GlucoseValueDataPoint>?) { val bucketedData = iobCobCalculator.ads.getBucketedDataTableCopy() ?: return
if (bucketedData.isEmpty()) {
aapsLogger.debug("No bucketed data.")
return
}
val bucketedListArray: MutableList<DataPointWithLabelInterface> = ArrayList()
for (inMemoryGlucoseValue in bucketedData) {
if (inMemoryGlucoseValue.timestamp < fromTime || inMemoryGlucoseValue.timestamp > toTime) continue
bucketedListArray.add(InMemoryGlucoseValueDataPoint(inMemoryGlucoseValue, profileFunction, resourceHelper))
}
addSeries(PointsWithLabelGraphSeries(Array(bucketedListArray.size) { i -> bucketedListArray[i] }))
}
fun addBgReadings(fromTime: Long, toTime: Long, highLine: Double, predictions: MutableList<GlucoseValueDataPoint>?) {
var maxBgValue = Double.MIN_VALUE var maxBgValue = Double.MIN_VALUE
bgReadingsArray = iobCobCalculatorPlugin.bgReadings bgReadingsArray = repository.compatGetBgReadingsDataFromTime(fromTime, toTime, false).blockingGet()
if (bgReadingsArray?.isEmpty() != false) { if (bgReadingsArray?.isEmpty() != false) {
aapsLogger.debug("No BG data.") aapsLogger.debug("No BG data.")
maxY = if (units == Constants.MGDL) 180.0 else 10.0 maxY = if (units == Constants.MGDL) 180.0 else 10.0
@ -81,7 +88,7 @@ class GraphData(
for (bg in bgReadingsArray!!) { for (bg in bgReadingsArray!!) {
if (bg.timestamp < fromTime || bg.timestamp > toTime) continue if (bg.timestamp < fromTime || bg.timestamp > toTime) continue
if (bg.value > maxBgValue) maxBgValue = bg.value if (bg.value > maxBgValue) maxBgValue = bg.value
bgListArray.add(GlucoseValueDataPoint(injector, bg)) bgListArray.add(GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper))
} }
if (predictions != null) { if (predictions != null) {
predictions.sortWith(Comparator { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) }) predictions.sortWith(Comparator { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) })
@ -134,7 +141,7 @@ class GraphData(
time += 60 * 1000L time += 60 * 1000L
continue continue
} }
val basalData = iobCobCalculatorPlugin.getBasalData(profile, time) val basalData = iobCobCalculator.getBasalData(profile, time)
val baseBasalValue = basalData.basal val baseBasalValue = basalData.basal
var absoluteLineValue = baseBasalValue var absoluteLineValue = baseBasalValue
var tempBasalValue = 0.0 var tempBasalValue = 0.0
@ -244,9 +251,15 @@ class GraphData(
fun addTreatments(fromTime: Long, endTime: Long) { fun addTreatments(fromTime: Long, endTime: Long) {
val filteredTreatments: MutableList<DataPointWithLabelInterface> = ArrayList() val filteredTreatments: MutableList<DataPointWithLabelInterface> = ArrayList()
treatmentsPlugin.treatmentsFromHistory repository.getBolusesIncludingInvalidFromTimeToTime(fromTime, endTime, true).blockingGet()
.filterTimeframe(fromTime, endTime) .map { BolusDataPoint(it, resourceHelper, activePlugin, defaultValueHelper) }
.filter { !it.isSMB || it.isValid } .filter { it.data.type != Bolus.Type.SMB || it.data.isValid }
.forEach {
it.y = getNearestBg(it.x.toLong())
filteredTreatments.add(it)
}
repository.getCarbsIncludingInvalidFromTimeToTimeExpanded(fromTime, endTime, true).blockingGet()
.map { CarbsDataPoint(it, resourceHelper) }
.forEach { .forEach {
it.y = getNearestBg(it.x.toLong()) it.y = getNearestBg(it.x.toLong())
filteredTreatments.add(it) filteredTreatments.add(it)
@ -259,8 +272,8 @@ class GraphData(
// Extended bolus // Extended bolus
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
treatmentsPlugin.extendedBolusesFromHistory.list repository.getExtendedBolusDataFromTimeToTime(fromTime, endTime, true).blockingGet()
.filterTimeframe(fromTime, endTime) .map { ExtendedBolusDataPoint(it) }
.filter { it.duration != 0L } .filter { it.duration != 0L }
.forEach { .forEach {
it.y = getNearestBg(it.x.toLong()) it.y = getNearestBg(it.x.toLong())
@ -270,8 +283,8 @@ class GraphData(
// Careportal // Careportal
// databaseHelper.getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true) // databaseHelper.getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true)
repository.compatGetTherapyEventDataFromToTime(fromTime - 6 * 60 * 60 * 1000, endTime).blockingGet() repository.compatGetTherapyEventDataFromToTime(fromTime - T.hours(6).msecs(), endTime).blockingGet()
.map { TherapyEventDataPoint(injector, it) } .map { TherapyEventDataPoint(it, resourceHelper, profileFunction, translator) }
.filterTimeframe(fromTime, endTime) .filterTimeframe(fromTime, endTime)
.forEach { .forEach {
if (it.y == 0.0) it.y = getNearestBg(it.x.toLong()) if (it.y == 0.0) it.y = getNearestBg(it.x.toLong())
@ -289,8 +302,7 @@ class GraphData(
private fun getNearestBg(date: Long): Double { private fun getNearestBg(date: Long): Double {
bgReadingsArray?.let { bgReadingsArray -> bgReadingsArray?.let { bgReadingsArray ->
for (r in bgReadingsArray.indices) { for (reading in bgReadingsArray) {
val reading = bgReadingsArray[r]
if (reading.timestamp > date) continue if (reading.timestamp > date) continue
return Profile.fromMgdlToUnits(reading.value, units) return Profile.fromMgdlToUnits(reading.value, units)
} }
@ -312,7 +324,7 @@ class GraphData(
time += 5 * 60 * 1000L time += 5 * 60 * 1000L
continue continue
} }
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile) total = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile)
val act: Double = total.activity val act: Double = total.activity
if (time <= now) actArrayHist.add(ScaledDataPoint(time, act, actScale)) else actArrayPrediction.add(ScaledDataPoint(time, act, actScale)) if (time <= now) actArrayHist.add(ScaledDataPoint(time, act, actScale)) else actArrayPrediction.add(ScaledDataPoint(time, act, actScale))
maxIAValue = max(maxIAValue, abs(act)) maxIAValue = max(maxIAValue, abs(act))
@ -353,10 +365,10 @@ class GraphData(
time += 5 * 60 * 1000L time += 5 * 60 * 1000L
continue continue
} }
val deviation = if (devBgiScale) iobCobCalculatorPlugin.getAutosensData(time)?.deviation val deviation = if (devBgiScale) iobCobCalculator.ads.getAutosensDataAtTime(time)?.deviation
?: 0.0 else 0.0 ?: 0.0 else 0.0
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile) total = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile)
val bgi: Double = total.activity * profile.getIsfMgdl(time) * 5.0 val bgi: Double = total.activity * profile.getIsfMgdl(time) * 5.0
if (time <= now) bgiArrayHist.add(ScaledDataPoint(time, bgi, bgiScale)) else bgiArrayPrediction.add(ScaledDataPoint(time, bgi, bgiScale)) if (time <= now) bgiArrayHist.add(ScaledDataPoint(time, bgi, bgiScale)) else bgiArrayPrediction.add(ScaledDataPoint(time, bgi, bgiScale))
maxBGIValue = max(maxBGIValue, max(abs(bgi), deviation)) maxBGIValue = max(maxBGIValue, max(abs(bgi), deviation))
@ -395,8 +407,8 @@ class GraphData(
var iob = 0.0 var iob = 0.0
var absIob = 0.0 var absIob = 0.0
if (profile != null) { if (profile != null) {
iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile).iob iob = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile).iob
if (absScale) absIob = iobCobCalculatorPlugin.calculateAbsInsulinFromTreatmentsAndTempsSynchronized(time).iob if (absScale) absIob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob
} }
if (abs(lastIob - iob) > 0.02) { if (abs(lastIob - iob) > 0.02) {
if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale)) if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale))
@ -413,25 +425,25 @@ class GraphData(
it.thickness = 3 it.thickness = 3
} }
if (showPrediction) { if (showPrediction) {
val autosensData = iobCobCalculatorPlugin.getLastAutosensDataSynchronized("GraphData") val autosensData = iobCobCalculator.getLastAutosensDataWithWaitForCalculationFinish("GraphData")
val lastAutosensResult = autosensData?.autosensResult ?: AutosensResult() val lastAutosensResult = autosensData?.autosensResult ?: AutosensResult()
val isTempTarget = repository.getTemporaryTargetActiveAt(dateUtil._now()).blockingGet() is ValueWrapper.Existing val isTempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
val iobPrediction: MutableList<DataPointWithLabelInterface> = ArrayList() val iobPrediction: MutableList<DataPointWithLabelInterface> = ArrayList()
val iobPredictionArray = iobCobCalculatorPlugin.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget) val iobPredictionArray = iobCobCalculator.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
for (i in iobPredictionArray) { for (i in iobPredictionArray) {
iobPrediction.add(i.setColor(resourceHelper.gc(R.color.iobPredAS))) iobPrediction.add(i.setColor(resourceHelper.gc(R.color.iobPredAS)))
maxIobValueFound = max(maxIobValueFound, abs(i.iob)) maxIobValueFound = max(maxIobValueFound, abs(i.iob))
} }
addSeries(PointsWithLabelGraphSeries(Array(iobPrediction.size) { i -> iobPrediction[i] })) addSeries(PointsWithLabelGraphSeries(Array(iobPrediction.size) { i -> iobPrediction[i] }))
val iobPrediction2: MutableList<DataPointWithLabelInterface> = ArrayList() val iobPrediction2: MutableList<DataPointWithLabelInterface> = ArrayList()
val iobPredictionArray2 = iobCobCalculatorPlugin.calculateIobArrayForSMB(AutosensResult(), SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget) val iobPredictionArray2 = iobCobCalculator.calculateIobArrayForSMB(AutosensResult(), SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
for (i in iobPredictionArray2) { for (i in iobPredictionArray2) {
iobPrediction2.add(i.setColor(resourceHelper.gc(R.color.iobPred))) iobPrediction2.add(i.setColor(resourceHelper.gc(R.color.iobPred)))
maxIobValueFound = max(maxIobValueFound, abs(i.iob)) maxIobValueFound = max(maxIobValueFound, abs(i.iob))
} }
addSeries(PointsWithLabelGraphSeries(Array(iobPrediction2.size) { i -> iobPrediction2[i] })) addSeries(PointsWithLabelGraphSeries(Array(iobPrediction2.size) { i -> iobPrediction2[i] }))
aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(lastAutosensResult.ratio) + ": " + iobCobCalculatorPlugin.iobArrayToString(iobPredictionArray)) aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(lastAutosensResult.ratio) + ": " + iobCobCalculator.iobArrayToString(iobPredictionArray))
aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(1.0) + ": " + iobCobCalculatorPlugin.iobArrayToString(iobPredictionArray2)) aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(1.0) + ": " + iobCobCalculator.iobArrayToString(iobPredictionArray2))
} }
if (useForScale) { if (useForScale) {
maxY = maxIobValueFound maxY = maxIobValueFound
@ -452,7 +464,7 @@ class GraphData(
while (time <= toTime) { while (time <= toTime) {
val profile = profileFunction.getProfile(time) val profile = profileFunction.getProfile(time)
var iob = 0.0 var iob = 0.0
if (profile != null) iob = iobCobCalculatorPlugin.calculateAbsInsulinFromTreatmentsAndTempsSynchronized(time).iob if (profile != null) iob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob
if (abs(lastIob - iob) > 0.02) { if (abs(lastIob - iob) > 0.02) {
if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale)) if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale))
iobArray.add(ScaledDataPoint(time, iob, iobScale)) iobArray.add(ScaledDataPoint(time, iob, iobScale))
@ -484,7 +496,7 @@ class GraphData(
val cobScale = Scale() val cobScale = Scale()
var time = fromTime var time = fromTime
while (time <= toTime) { while (time <= toTime) {
iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData -> iobCobCalculator.ads.getAutosensDataAtTime(time)?.let { autosensData ->
val cob = autosensData.cob.toInt() val cob = autosensData.cob.toInt()
if (cob != lastCob) { if (cob != lastCob) {
if (autosensData.carbsFromBolus > 0) cobArray.add(ScaledDataPoint(time, lastCob.toDouble(), cobScale)) if (autosensData.carbsFromBolus > 0) cobArray.add(ScaledDataPoint(time, lastCob.toDouble(), cobScale))
@ -529,12 +541,12 @@ class GraphData(
while (time <= toTime) { while (time <= toTime) {
// if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0 // if align Dev Scale with BGI scale, then calculate BGI value, else bgi = 0.0
val bgi: Double = if (devBgiScale) { val bgi: Double = if (devBgiScale) {
val profile = profileFunction.getProfile(time) val profile = profileFunction.getProfile(time) ?: continue
total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile) total = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile)
total.activity * (profile?.getIsfMgdl(time) ?: 0.0) * 5.0 total.activity * profile.getIsfMgdl(time) * 5.0
} else 0.0 } else 0.0
iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData -> iobCobCalculator.ads.getAutosensDataAtTime(time)?.let { autosensData ->
var color = resourceHelper.gc(R.color.deviationblack) // "=" var color = resourceHelper.gc(R.color.deviationblack) // "="
if (autosensData.type == "" || autosensData.type == "non-meal") { if (autosensData.type == "" || autosensData.type == "non-meal") {
if (autosensData.pastSensitivity == "C") color = resourceHelper.gc(R.color.deviationgrey) if (autosensData.pastSensitivity == "C") color = resourceHelper.gc(R.color.deviationgrey)
@ -565,15 +577,15 @@ class GraphData(
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
fun addRatio(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double) { fun addRatio(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double) {
val ratioArray: MutableList<ScaledDataPoint> = ArrayList() val ratioArray: MutableList<ScaledDataPoint> = ArrayList()
var maxRatioValueFound = 5.0 //even if sens data equals 0 for all the period, minimum scale is between 95% and 105% var maxRatioValueFound = Double.MIN_VALUE
var minRatioValueFound = - maxRatioValueFound var minRatioValueFound = Double.MAX_VALUE
val ratioScale = if (useForScale) Scale(100.0) else Scale() val ratioScale = Scale()
var time = fromTime var time = fromTime
while (time <= toTime) { while (time <= toTime) {
iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData -> iobCobCalculator.ads.getAutosensDataAtTime(time)?.let { autosensData ->
ratioArray.add(ScaledDataPoint(time, 100.0 * (autosensData.autosensResult.ratio - 1 ), ratioScale)) ratioArray.add(ScaledDataPoint(time, autosensData.autosensResult.ratio - 1, ratioScale))
maxRatioValueFound = max(maxRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1)) maxRatioValueFound = max(maxRatioValueFound, autosensData.autosensResult.ratio - 1)
minRatioValueFound = min(minRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1)) minRatioValueFound = min(minRatioValueFound, autosensData.autosensResult.ratio - 1)
} }
time += 5 * 60 * 1000L time += 5 * 60 * 1000L
} }
@ -584,11 +596,10 @@ class GraphData(
it.thickness = 3 it.thickness = 3
}) })
if (useForScale) { if (useForScale) {
maxY = 100.0 + max(maxRatioValueFound, abs(minRatioValueFound)) maxY = max(maxRatioValueFound, abs(minRatioValueFound))
minY = 100.0 - max(maxRatioValueFound, abs(minRatioValueFound)) minY = -maxY
ratioScale.setMultiplier(1.0) }
} else ratioScale.setMultiplier(maxY * scale / max(maxRatioValueFound, abs(minRatioValueFound)))
ratioScale.setMultiplier(maxY * scale / max(maxRatioValueFound, abs(minRatioValueFound)))
} }
// scale in % of vertical size (like 0.3) // scale in % of vertical size (like 0.3)
@ -601,7 +612,7 @@ class GraphData(
val dsMinScale = Scale() val dsMinScale = Scale()
var time = fromTime var time = fromTime
while (time <= toTime) { while (time <= toTime) {
iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData -> iobCobCalculator.ads.getAutosensDataAtTime(time)?.let { autosensData ->
dsMaxArray.add(ScaledDataPoint(time, autosensData.slopeFromMaxDeviation, dsMaxScale)) dsMaxArray.add(ScaledDataPoint(time, autosensData.slopeFromMaxDeviation, dsMaxScale))
dsMinArray.add(ScaledDataPoint(time, autosensData.slopeFromMinDeviation, dsMinScale)) dsMinArray.add(ScaledDataPoint(time, autosensData.slopeFromMinDeviation, dsMinScale))
maxFromMaxValueFound = max(maxFromMaxValueFound, abs(autosensData.slopeFromMaxDeviation)) maxFromMaxValueFound = max(maxFromMaxValueFound, abs(autosensData.slopeFromMaxDeviation))

View file

@ -0,0 +1,39 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import android.graphics.Color
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
class BolusDataPoint @Inject constructor(
val data: Bolus,
private val resourceHelper: ResourceHelper,
private val activePlugin: ActivePlugin,
private val defaultValueHelper: DefaultValueHelper
) : DataPointWithLabelInterface {
private var yValue = 0.0
override fun getX(): Double = data.timestamp.toDouble()
override fun getY(): Double = if (data.type == Bolus.Type.SMB) defaultValueHelper.determineLowLine() else yValue
override fun getLabel(): String = DecimalFormatter.toPumpSupportedBolus(data.amount, activePlugin.activePump, resourceHelper)
override fun getDuration(): Long = 0
override fun getSize(): Float = 2f
override fun getShape(): PointsWithLabelGraphSeries.Shape =
if (data.type == Bolus.Type.SMB) PointsWithLabelGraphSeries.Shape.SMB
else PointsWithLabelGraphSeries.Shape.BOLUS
override fun getColor(): Int =
if (data.type == Bolus.Type.SMB) resourceHelper.gc(R.color.tempbasal)
else if (data.isValid) Color.CYAN
else resourceHelper.gc(android.R.color.holo_red_light)
override fun setY(y: Double) {
yValue = y
}
}

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
class CarbsDataPoint @Inject constructor(
val data: Carbs,
private val resourceHelper: ResourceHelper
) : DataPointWithLabelInterface {
private var yValue = 0.0
override fun getX(): Double = data.timestamp.toDouble()
override fun getY(): Double = yValue
override fun getLabel(): String = resourceHelper.gs(R.string.format_carbs, data.amount.toInt())
override fun getDuration(): Long = 0
override fun getSize(): Float = 2f
override fun getShape(): PointsWithLabelGraphSeries.Shape = PointsWithLabelGraphSeries.Shape.CARBS
override fun getColor(): Int =
if (data.isValid) resourceHelper.gc(R.color.carbs)
else resourceHelper.gc(android.R.color.holo_red_light)
override fun setY(y: Double) {
yValue = y
}
}

View file

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

View file

@ -1,29 +1,20 @@
package info.nightscout.androidaps.data package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
class GlucoseValueDataPoint @Inject constructor( class GlucoseValueDataPoint @Inject constructor(
val injector: HasAndroidInjector, val data: GlucoseValue,
val data: GlucoseValue private val defaultValueHelper: DefaultValueHelper,
private val profileFunction: ProfileFunction,
private val resourceHelper: ResourceHelper
) : DataPointWithLabelInterface { ) : DataPointWithLabelInterface {
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper
init {
injector.androidInjector().inject(this)
}
fun valueToUnits(units: String): Double = fun valueToUnits(units: String): Double =
if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL
@ -59,11 +50,11 @@ class GlucoseValueDataPoint @Inject constructor(
val predictionColor: Int val predictionColor: Int
get() { get() {
return when (data.sourceSensor) { return when (data.sourceSensor) {
GlucoseValue.SourceSensor.IOB_PREDICTION -> resourceHelper.gc(R.color.iob) GlucoseValue.SourceSensor.IOB_PREDICTION -> resourceHelper.gc(R.color.iob)
GlucoseValue.SourceSensor.COB_PREDICTION -> resourceHelper.gc(R.color.cob) GlucoseValue.SourceSensor.COB_PREDICTION -> resourceHelper.gc(R.color.cob)
GlucoseValue.SourceSensor.aCOB_PREDICTION -> -0x7f000001 and resourceHelper.gc(R.color.cob) GlucoseValue.SourceSensor.A_COB_PREDICTION -> -0x7f000001 and resourceHelper.gc(R.color.cob)
GlucoseValue.SourceSensor.UAM_PREDICTION -> resourceHelper.gc(R.color.uam) GlucoseValue.SourceSensor.UAM_PREDICTION -> resourceHelper.gc(R.color.uam)
GlucoseValue.SourceSensor.ZT_PREDICTION -> resourceHelper.gc(R.color.zt) GlucoseValue.SourceSensor.ZT_PREDICTION -> resourceHelper.gc(R.color.zt)
else -> R.color.white else -> R.color.white
} }
} }
@ -71,7 +62,7 @@ class GlucoseValueDataPoint @Inject constructor(
private val isPrediction: Boolean private val isPrediction: Boolean
get() = data.sourceSensor == GlucoseValue.SourceSensor.IOB_PREDICTION || get() = data.sourceSensor == GlucoseValue.SourceSensor.IOB_PREDICTION ||
data.sourceSensor == GlucoseValue.SourceSensor.COB_PREDICTION || data.sourceSensor == GlucoseValue.SourceSensor.COB_PREDICTION ||
data.sourceSensor == GlucoseValue.SourceSensor.aCOB_PREDICTION || data.sourceSensor == GlucoseValue.SourceSensor.A_COB_PREDICTION ||
data.sourceSensor == GlucoseValue.SourceSensor.UAM_PREDICTION || data.sourceSensor == GlucoseValue.SourceSensor.UAM_PREDICTION ||
data.sourceSensor == GlucoseValue.SourceSensor.ZT_PREDICTION data.sourceSensor == GlucoseValue.SourceSensor.ZT_PREDICTION

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