Merge branch 'nightscout:dev' into dev

This commit is contained in:
Tim Street 2022-06-13 21:12:14 +01:00 committed by GitHub
commit 0b3223d71f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
205 changed files with 2116 additions and 812 deletions

View file

@ -104,12 +104,14 @@ tasks.matching { it instanceof Test }.all {
}
android {
namespace 'info.nightscout.androidaps'
ndkVersion "21.1.6352462"
defaultConfig {
multiDexEnabled true
versionCode 1500
version "3.0.0.2-dev-l"
version "3.0.0.2-dev-m"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'

View file

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="info.nightscout.androidaps">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BLUETOOTH" />
@ -48,7 +46,7 @@
android:restoreAnyVersion="true"
android:roundIcon="${appIconRound}"
android:supportsRtl="true"
android:theme="@style/AppTheme.Launcher" >
android:theme="@style/AppTheme.Launcher">
<meta-data
android:name="com.google.android.gms.version"
@ -65,7 +63,7 @@
<receiver
android:name=".widget.Widget"
android:exported="true" >
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
@ -83,69 +81,86 @@
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
<activity android:name=".MainActivity"
android:theme="@style/AppTheme"
android:exported="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activities.PreferencesActivity" />
<activity android:name=".plugins.general.overview.activities.QuickWizardListActivity"
android:theme="@style/AppTheme"
android:exported="false">
<activity
android:name=".activities.PreferencesActivity"
android:exported="false" />
<activity
android:name=".plugins.general.overview.activities.QuickWizardListActivity"
android:exported="false"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".plugins.general.maintenance.activities.PrefImportListActivity"
<activity
android:name=".plugins.general.maintenance.activities.PrefImportListActivity"
android:exported="false"
android:theme="@style/AppTheme" />
<activity android:name=".activities.HistoryBrowseActivity"
<activity
android:name=".activities.HistoryBrowseActivity"
android:exported="false"
android:theme="@style/AppTheme" />
<activity android:name=".activities.TreatmentsActivity"
<activity
android:name=".activities.TreatmentsActivity"
android:exported="false"
android:theme="@style/AppTheme" />
<activity android:name=".activities.SurveyActivity"
<activity
android:name=".activities.SurveyActivity"
android:exported="false"
android:theme="@style/AppTheme" />
<activity android:name=".activities.ProfileHelperActivity"
<activity
android:name=".activities.ProfileHelperActivity"
android:exported="false"
android:theme="@style/AppTheme" />
<activity android:name=".activities.StatsActivity"
<activity
android:name=".activities.StatsActivity"
android:exported="false"
android:theme="@style/AppTheme" />
<!-- Receive new BG readings from other local apps -->
<receiver
android:name=".receivers.DataReceiver"
android:enabled="true"
android:exported="true">
android:name=".receivers.DataReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<!-- Receiver from xDrip -->
<action android:name="com.eveningoutpost.dexdrip.BgEstimate"/>
<action android:name="com.eveningoutpost.dexdrip.BgEstimate" />
<!-- Receiver from 640g uploader -->
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR"/>
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR" />
<!-- Receiver from glimp -->
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED"/>
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED" />
<!-- Receiver from Dexcom -->
<action android:name="com.dexcom.cgm.EXTERNAL_BROADCAST"/>
<action android:name="com.dexcom.cgm.EXTERNAL_BROADCAST" />
<!-- Receiver from Poctech -->
<action android:name="com.china.poctech.data"/>
<action android:name="com.china.poctech.data" />
<!-- Receiver from Tomato -->
<action android:name="com.fanqies.tomatofn.BgEstimate"/>
<action android:name="com.fanqies.tomatofn.BgEstimate" />
<!-- Receiver from GlucoRx Aidex -->
<action android:name="com.microtechmd.cgms.aidex.action.BgEstimate"/>
<action android:name="com.microtechmd.cgms.aidex.action.BgEstimate" />
</intent-filter>
</receiver>
<!-- Receive new SMS messages -->
<receiver
android:name=".receivers.SmsReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
android:name=".receivers.SmsReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
@ -212,15 +227,23 @@
<activity
android:name=".setupwizard.SetupWizardActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/AppTheme"
android:label="@string/title_activity_setup_wizard" />
android:exported="false"
android:label="@string/title_activity_setup_wizard"
android:theme="@style/AppTheme" />
<activity
android:name=".activities.SingleFragmentActivity"
android:exported="false"
android:theme="@style/AppTheme" />
<activity android:name=".plugins.general.maintenance.activities.LogSettingActivity" />
<activity android:name=".activities.RequestDexcomPermissionActivity" />
<activity android:name=".plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity">
<activity
android:name=".plugins.general.maintenance.activities.LogSettingActivity"
android:exported="false" />
<activity
android:name=".activities.RequestDexcomPermissionActivity"
android:exported="false" />
<activity
android:name=".plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity"
android:exported="false">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity" />
@ -228,7 +251,9 @@
</intent-filter>
</activity>
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
</application>

View file

@ -324,7 +324,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
rT.reason += ", but Min. Delta " + minDelta.toFixed(2) + " > Exp. Delta " + expectedDelta;
}
if (currenttemp.duration > 15 && (round_basal(basal, profile) === round_basal(currenttemp.rate, profile))) {
rT.reason += ", temp " + currenttemp.rate + " ~ req " + basal + "U/hr";
rT.reason += ", temp " + currenttemp.rate + " ~ req " + round(basal, 2) + "U/hr";
return rT;
} else {
rT.reason += "; setting current basal of " + round(basal, 2) + " as temp";
@ -367,10 +367,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate >= currenttemp.rate * 0.8)) {
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr";
rT.reason += ", temp " + (currenttemp.rate).toFixed(3) + " ~< req " + round(rate, 2) + "U/hr";
return rT;
} else {
rT.reason += ", setting " + rate + "U/hr";
rT.reason += ", setting " + round(rate, 2) + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
}
@ -476,22 +476,22 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > 2 * req " + insulinReq + ". Setting temp basal of " + rate + "U/hr";
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate - basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > 2 * req " + insulinReq + ". Setting temp basal of " + round(rate, 2) + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
rT.reason += "no temp, setting " + rate + "U/hr";
rT.reason += "no temp, setting " + round(rate, 2) + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (currenttemp.duration > 5 && (round_basal(rate, profile) <= round_basal(currenttemp.rate, profile))) { // if required temp <~ existing temp basal
rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr";
rT.reason += "temp " + (currenttemp.rate).toFixed(3) + " >~ req " + round(rate, 2) + "U/hr";
return rT;
}
// required temp > existing temp basal
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr";
rT.reason += "temp " + (currenttemp.rate).toFixed(3) + " < " + round(rate, 2) + "U/hr";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}

View file

@ -955,7 +955,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate >= currenttemp.rate * 0.8)) {
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr. ";
rT.reason += ", temp " + currenttemp.rate + " ~< req " + round(rate, 2) + "U/hr. ";
return rT;
} else {
// calculate a long enough zero temp to eventually correct back up to target
@ -976,7 +976,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
return tempBasalFunctions.setTempBasal(rate, durationReq, profile, rT, currenttemp);
}
} else {
rT.reason += ", setting " + rate + "U/hr. ";
rT.reason += ", setting " + round(rate, 2) + "U/hr. ";
}
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
@ -1143,22 +1143,22 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate).toFixed(2) + " > 2 * insulinReq. Setting temp basal of " + rate + "U/hr. ";
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate).toFixed(2) + " > 2 * insulinReq. Setting temp basal of " + round(rate, 2) + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (typeof currenttemp.duration === 'undefined' || currenttemp.duration === 0) { // no temp is set
rT.reason += "no temp, setting " + rate + "U/hr. ";
rT.reason += "no temp, setting " + round(rate, 2) + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (currenttemp.duration > 5 && (round_basal(rate, profile) <= round_basal(currenttemp.rate, profile))) { // if required temp <~ existing temp basal
rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr. ";
rT.reason += "temp " + (currenttemp.rate).toFixed(2) + " >~ req " + round(rate, 2) + "U/hr. ";
return rT;
}
// required temp > existing temp basal
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr. ";
rT.reason += "temp " + (currenttemp.rate).toFixed(2) + " < " + round(rate, 2) + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}

View file

@ -1317,22 +1317,22 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate).toFixed(2) + " > 2 * insulinReq. Setting temp basal of " + rate + "U/hr. ";
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate).toFixed(2) + " > 2 * insulinReq. Setting temp basal of " + round(rate, 2) + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (typeof currenttemp.duration === 'undefined' || currenttemp.duration === 0) { // no temp is set
rT.reason += "no temp, setting " + rate + "U/hr. ";
rT.reason += "no temp, setting " + round(rate, 2) + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}
if (currenttemp.duration > 5 && (round_basal(rate, profile) <= round_basal(currenttemp.rate, profile))) { // if required temp <~ existing temp basal
rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr. ";
rT.reason += "temp " + (currenttemp.rate).toFixed(2) + " >~ req " + round(rate, 2) + "U/hr. ";
return rT;
}
// required temp > existing temp basal
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr. ";
rT.reason += "temp " + (currenttemp.rate).toFixed(2) + " < " + round(rate, 2) + "U/hr. ";
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
}

View file

@ -39,7 +39,6 @@ import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.events.EventRebuildTabs
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
@ -49,7 +48,7 @@ import info.nightscout.androidaps.setupwizard.SetupWizardActivity
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.utils.protection.PasswordCheck

View file

@ -43,7 +43,7 @@ import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.LocalAlertUtils
import info.nightscout.androidaps.utils.ProcessLifecycleListener
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.widget.updateWidget
import info.nightscout.shared.logging.AAPSLogger
@ -249,7 +249,7 @@ class MainApp : DaggerApplication() {
override fun onTerminate() {
aapsLogger.debug(LTag.CORE, "onTerminate")
unregisterActivityLifecycleCallbacks(activityMonitor)
alarmSoundServiceHelper.stopService(this)
alarmSoundServiceHelper.stopService(this, "onTerminate")
super.onTerminate()
}
}

View file

@ -37,7 +37,7 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.Translator
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.workflow.CalculationWorkflow
import info.nightscout.shared.logging.LTag

View file

@ -11,7 +11,7 @@ import info.nightscout.androidaps.activities.fragments.*
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import javax.inject.Inject
class TreatmentsActivity : NoSplashAppCompatActivity() {

View file

@ -40,7 +40,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag

View file

@ -25,7 +25,7 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger

View file

@ -36,7 +36,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger

View file

@ -35,7 +35,7 @@ import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientR
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag

View file

@ -28,7 +28,7 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.androidNotification.NotificationHolderImpl
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl
import info.nightscout.androidaps.utils.buildHelper.ConfigImpl
import info.nightscout.androidaps.utils.resources.IconsProviderImplementation

View file

@ -3,6 +3,8 @@ package info.nightscout.androidaps.dialogs
import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
@ -24,6 +26,7 @@ import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.databinding.DialogWizardBinding
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.extensions.formatColor
import info.nightscout.androidaps.extensions.runOnUiThread
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.valueToUnits
import info.nightscout.androidaps.interfaces.*
@ -63,6 +66,8 @@ class WizardDialog : DaggerDialogFragment() {
@Inject lateinit var dateUtil: DateUtil
@Inject lateinit var protectionCheck: ProtectionCheck
private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private var queryingProtection = false
private var wizard: BolusWizard? = null
private var calculatedPercentage = 100.0
@ -168,7 +173,7 @@ class WizardDialog : DaggerDialogFragment() {
savedInstanceState?.getDouble("carb_time_input")
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher
)
initDialog()
handler.post { initDialog() }
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
binding.percentUsed.text = rh.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
// ok button
@ -257,6 +262,7 @@ class WizardDialog : DaggerDialogFragment() {
override fun onDestroyView() {
super.onDestroyView()
disposable.clear()
handler.removeCallbacksAndMessages(null)
_binding = null
}
@ -323,14 +329,9 @@ class WizardDialog : DaggerDialogFragment() {
else DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL)
private fun initDialog() {
if (carbsPassedIntoWizard != 0.0) {
binding.carbsInput.value = carbsPassedIntoWizard
}
if (notesPassedIntoWizard.isNotBlank()) {
binding.notesLayout.notes.setText(notesPassedIntoWizard)
}
val profile = profileFunction.getProfile()
val profileStore = activePlugin.activeProfileSource.profile
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
if (profile == null || profileStore == null) {
ToastUtils.showToastInUiThread(ctx, rh.gs(R.string.noprofile))
@ -338,32 +339,40 @@ class WizardDialog : DaggerDialogFragment() {
return
}
val profileList: ArrayList<CharSequence> = profileStore.getProfileList()
profileList.add(0, rh.gs(R.string.active))
context?.let { context ->
binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList))
binding.profileList.setText(profileList[0], false)
}
val units = profileFunction.getUnits()
binding.bgUnits.text = units.asText
binding.bgInput.step = if (units == GlucoseUnit.MGDL) 1.0 else 0.1
// Set BG if not old
binding.bgInput.value = iobCobCalculator.ads.actualBg()?.valueToUnits(units) ?: 0.0
binding.ttCheckbox.isEnabled = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
binding.ttCheckboxIcon.visibility = binding.ttCheckbox.isEnabled.toVisibility()
// IOB calculation
val bolusIob = iobCobCalculator.calculateIobFromBolus().round()
val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
binding.iobInsulin.text = rh.gs(R.string.formatinsulinunits, -bolusIob.iob - basalIob.basaliob)
runOnUiThread {
if (carbsPassedIntoWizard != 0.0) {
binding.carbsInput.value = carbsPassedIntoWizard
}
if (notesPassedIntoWizard.isNotBlank()) {
binding.notesLayout.notes.setText(notesPassedIntoWizard)
}
calculateInsulin()
val profileList: ArrayList<CharSequence> = profileStore.getProfileList()
profileList.add(0, rh.gs(R.string.active))
context?.let { context ->
binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList))
binding.profileList.setText(profileList[0], false)
}
binding.percentUsed.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100 || correctionPercent).toVisibility()
val units = profileFunction.getUnits()
binding.bgUnits.text = units.asText
binding.bgInput.step = if (units == GlucoseUnit.MGDL) 1.0 else 0.1
// Set BG if not old
binding.bgInput.value = iobCobCalculator.ads.actualBg()?.valueToUnits(units) ?: 0.0
binding.ttCheckbox.isEnabled = tempTarget is ValueWrapper.Existing
binding.ttCheckboxIcon.visibility = binding.ttCheckbox.isEnabled.toVisibility()
binding.iobInsulin.text = rh.gs(R.string.formatinsulinunits, -bolusIob.iob - basalIob.basaliob)
calculateInsulin()
binding.percentUsed.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100 || correctionPercent).toVisibility()
}
}
@SuppressLint("SetTextI18n")
@ -496,7 +505,7 @@ class WizardDialog : DaggerDialogFragment() {
override fun onResume() {
super.onResume()
if(!queryingProtection) {
if (!queryingProtection) {
queryingProtection = true
activity?.let { activity ->
val cancelFail = {

View file

@ -60,7 +60,7 @@ class WizardInfoDialog : DaggerDialogFragment() {
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("data", data.toJson(true, dateUtil).toString())
outState.putString("data", data.toJson(true, dateUtil, profileFunction).toString())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -17,7 +17,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProv
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP

View file

@ -23,7 +23,7 @@ import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.PREFERENCES
import info.nightscout.androidaps.interfaces.ResourceHelper

View file

@ -19,7 +19,7 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONObject

View file

@ -39,7 +39,7 @@ import info.nightscout.androidaps.skins.SkinProvider
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers

View file

@ -28,9 +28,9 @@ class AutotuneCore @Inject constructor(
//console.error(isf);
var carbRatio = previousAutotune.ic
//console.error(carbRatio);
var csf = isf / carbRatio
var dia = previousAutotune.dia
var peak = previousAutotune.peak
val csf = isf / carbRatio
val dia = previousAutotune.dia
val peak = previousAutotune.peak
val csfGlucose = preppedGlucose.csfGlucoseData
val isfGlucose = preppedGlucose.isfGlucoseData
val basalGlucose = preppedGlucose.basalGlucoseData

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.general.autotune
import android.graphics.Paint
import android.graphics.Typeface
import android.os.Bundle
import android.text.Editable
@ -79,7 +80,8 @@ class AutotuneFragment : DaggerFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sp.putBoolean(R.string.key_autotune_tune_insulin_curve, false) // put to false tune insulin curve
autotunePlugin.lastRun = sp.getLong(R.string.key_autotune_last_run, 0)
sp.putBoolean(R.string.key_autotune_additional_log, false) // put to false additional log
autotunePlugin.loadLastRun()
if (autotunePlugin.lastNbDays.isEmpty())
autotunePlugin.lastNbDays = sp.getInt(R.string.key_autotune_default_tune_days, 5).toString()
val defaultValue = sp.getInt(R.string.key_autotune_default_tune_days, 5).toDouble()
@ -144,6 +146,7 @@ class AutotuneFragment : DaggerFragment() {
autotunePlugin.tunedProfile?.profilename = localName
autotunePlugin.updateProfile(autotunePlugin.tunedProfile)
autotunePlugin.updateButtonVisibility = View.GONE
autotunePlugin.saveLastRun()
uel.log(
UserEntry.Action.STORE_PROFILE,
UserEntry.Sources.Autotune,
@ -163,6 +166,7 @@ class AutotuneFragment : DaggerFragment() {
autotunePlugin.tunedProfile?.profilename = ""
autotunePlugin.updateProfile(autotunePlugin.pumpProfile)
autotunePlugin.updateButtonVisibility = View.VISIBLE
autotunePlugin.saveLastRun()
uel.log(
UserEntry.Action.STORE_PROFILE,
UserEntry.Sources.Autotune,
@ -251,6 +255,14 @@ class AutotuneFragment : DaggerFragment() {
}
}
}
binding.tuneLastrun.setOnClickListener {
if (!autotunePlugin.calculationRunning) {
autotunePlugin.loadLastRun()
updateGui()
}
}
binding.tuneLastrun.paintFlags = binding.tuneLastrun.paintFlags or Paint.UNDERLINE_TEXT_FLAG
}
@Synchronized
@ -263,7 +275,6 @@ class AutotuneFragment : DaggerFragment() {
updateGui()
}, { fabricPrivacy.logException(it) })
checkNewDay()
binding.tuneDays.value = autotunePlugin.lastNbDays.toDouble()
updateGui()
}
@ -276,6 +287,7 @@ class AutotuneFragment : DaggerFragment() {
@Synchronized
private fun updateGui() {
_binding ?: return
binding.tuneDays.value = autotunePlugin.lastNbDays.toDouble()
profileStore = activePlugin.activeProfileSource.profile ?: ProfileStore(injector, JSONObject(), dateUtil)
profileName = if (binding.profileList.text.toString() == rh.gs(R.string.active)) "" else binding.profileList.text.toString()
profileFunction.getProfile()?.let { currentProfile ->

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.data.LocalInsulin
import info.nightscout.androidaps.data.ProfileSealed
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.extensions.pureProfileFromJson
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
@ -16,9 +17,10 @@ import info.nightscout.androidaps.plugins.general.autotune.events.EventAutotuneU
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import org.json.JSONException
@ -48,7 +50,7 @@ class AutotunePlugin @Inject constructor(
private val autotuneIob: AutotuneIob,
private val autotunePrep: AutotunePrep,
private val autotuneCore: AutotuneCore,
private val buildHelper:BuildHelper,
private val buildHelper: BuildHelper,
private val uel: UserEntryLogger,
aapsLogger: AAPSLogger
) : PluginBase(PluginDescription()
@ -115,37 +117,39 @@ class AutotunePlugin @Inject constructor(
val from = starttime + i * 24 * 60 * 60 * 1000L // get 24 hours BG values from 4 AM to 4 AM next day
val to = from + 24 * 60 * 60 * 1000L
log("Tune day " + (i + 1) + " of " + daysBack)
tunedProfile?.let { tunedProfile ->
autotuneIob.initializeData(from, to, tunedProfile) //autotuneIob contains BG and Treatments data from history (<=> query for ns-treatments and ns-entries)
tunedProfile?.let { it ->
autotuneIob.initializeData(from, to, it) //autotuneIob contains BG and Treatments data from history (<=> query for ns-treatments and ns-entries)
autotuneFS.exportEntries(autotuneIob) //<=> ns-entries.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
autotuneFS.exportTreatments(autotuneIob) //<=> ns-treatments.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine (include treatments ,tempBasal and extended
preppedGlucose = autotunePrep.categorize(tunedProfile) //<=> autotune.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
preppedGlucose = autotunePrep.categorize(it) //<=> autotune.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
preppedGlucose?.let { preppedGlucose ->
autotuneFS.exportPreppedGlucose(preppedGlucose)
tunedProfile = autotuneCore.tuneAllTheThings(preppedGlucose, it, pumpProfile).also { tunedProfile ->
autotuneFS.exportTunedProfile(tunedProfile) //<=> newprofile.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
if (i < daysBack - 1) {
log("Partial result for day ${i + 1}".trimIndent())
result = rh.gs(R.string.autotune_partial_result, i + 1, daysBack)
rxBus.send(EventAutotuneUpdateGui())
}
logResult = showResults(tunedProfile, pumpProfile)
if (detailedLog)
autotuneFS.exportLog(lastRun, i + 1)
}
}
?: {
log("preppedGlucose is null on day ${i + 1}")
tunedProfile = null
}
}
if (preppedGlucose == null || tunedProfile == null) {
if (tunedProfile == null) {
result = rh.gs(R.string.autotune_error)
log(result)
log("TunedProfile is null on day ${i + 1}")
calculationRunning = false
rxBus.send(EventAutotuneUpdateGui())
tunedProfile = null
autotuneFS.exportResult(result)
autotuneFS.exportLogAndZip(lastRun)
return result
}
preppedGlucose?.let { preppedGlucose -> //preppedGlucose and tunedProfile should never be null here
autotuneFS.exportPreppedGlucose(preppedGlucose)
tunedProfile = autotuneCore.tuneAllTheThings(preppedGlucose, tunedProfile!!, pumpProfile)
}
// localInsulin = LocalInsulin("TunedInsulin", tunedProfile!!.peak, tunedProfile!!.dia) // Todo: Add tune Insulin option
autotuneFS.exportTunedProfile(tunedProfile!!) //<=> newprofile.yyyymmdd.json files exported for results compare with oref0 autotune on virtual machine
if (i < daysBack - 1) {
log("Partial result for day ${i + 1}".trimIndent())
result = rh.gs(R.string.autotune_partial_result, i + 1, daysBack)
rxBus.send(EventAutotuneUpdateGui())
}
logResult = showResults(tunedProfile, pumpProfile)
if (detailedLog)
autotuneFS.exportLog(lastRun, i + 1)
}
result = rh.gs(R.string.autotune_result, dateUtil.dateAndTimeString(lastRun))
if (!detailedLog)
@ -161,7 +165,8 @@ class AutotunePlugin @Inject constructor(
updateProfile(tunedP)
uel.log(
UserEntry.Action.STORE_PROFILE,
UserEntry.Sources.Autotune,
UserEntry.Sources.Automation,
rh.gs(R.string.autotune),
ValueWithUnit.SimpleString(tunedP.profilename)
)
updateButtonVisibility = View.GONE
@ -178,22 +183,23 @@ class AutotunePlugin @Inject constructor(
log("Profile Switch succeed ${tunedP.profilename}")
uel.log(
UserEntry.Action.PROFILE_SWITCH,
UserEntry.Sources.Autotune,
"Autotune AutoSwitch",
UserEntry.Sources.Automation,
rh.gs(R.string.autotune),
ValueWithUnit.SimpleString(tunedP.profilename))
}
rxBus.send(EventLocalProfileChanged())
}
}
}
lastRunSuccess = true
sp.putLong(R.string.key_autotune_last_run, lastRun)
rxBus.send(EventAutotuneUpdateGui())
calculationRunning = false
tunedProfile?.let {
lastRunSuccess = true
saveLastRun()
rxBus.send(EventAutotuneUpdateGui())
calculationRunning = false
return result
}
return "No Result" // should never occurs
return rh.gs(R.string.autotune_error)
}
private fun showResults(tunedProfile: ATProfile?, pumpProfile: ATProfile): String {
@ -296,6 +302,64 @@ class AutotunePlugin @Inject constructor(
localProfilePlugin.storeSettings()
}
fun saveLastRun() {
val json = JSONObject()
json.put("lastNbDays", lastNbDays)
json.put("lastRun",lastRun)
json.put("pumpProfile", pumpProfile.profile.toPureNsJson(dateUtil))
json.put("pumpProfileName", pumpProfile.profilename)
json.put("pumpPeak", pumpProfile.peak)
json.put("pumpDia", pumpProfile.dia)
tunedProfile?.let { atProfile ->
json.put("tunedProfile", atProfile.profile.toPureNsJson(dateUtil))
json.put("tunedCircadianProfile", atProfile.circadianProfile.toPureNsJson(dateUtil))
json.put("tunedProfileName", atProfile.profilename)
json.put("tunedPeak", atProfile.peak)
json.put("tunedDia", atProfile.dia)
for (i in 0..23) {
json.put("missingDays_$i", atProfile.basalUntuned[i])
}
}
json.put("result", result)
json.put("updateButtonVisibility", updateButtonVisibility)
sp.putString(R.string.key_autotune_last_run, json.toString())
}
fun loadLastRun() {
result = ""
lastRunSuccess = false
try {
val json = JSONObject(sp.getString(R.string.key_autotune_last_run, ""))
lastNbDays = JsonHelper.safeGetString(json, "lastNbDays", "")
lastRun = JsonHelper.safeGetLong(json, "lastRun")
val pumpPeak = JsonHelper.safeGetInt(json, "pumpPeak")
val pumpDia = JsonHelper.safeGetDouble(json, "pumpDia")
var localInsulin = LocalInsulin("PumpInsulin", pumpPeak, pumpDia)
selectedProfile = JsonHelper.safeGetString(json, "pumpProfileName", "")
val profile = JsonHelper.safeGetJSONObject(json, "pumpProfile", null)?.let { pureProfileFromJson(it, dateUtil) }
?: return
pumpProfile = ATProfile(ProfileSealed.Pure(profile), localInsulin, injector).also { it.profilename = selectedProfile }
val tunedPeak = JsonHelper.safeGetInt(json, "tunedPeak")
val tunedDia = JsonHelper.safeGetDouble(json, "tunedDia")
localInsulin = LocalInsulin("PumpInsulin", tunedPeak, tunedDia)
val tunedProfileName = JsonHelper.safeGetString(json, "tunedProfileName", "")
val tuned = JsonHelper.safeGetJSONObject(json, "tunedProfile", null)?.let { pureProfileFromJson(it, dateUtil) }
?: return
val circadianTuned = JsonHelper.safeGetJSONObject(json, "tunedCircadianProfile", null)?.let { pureProfileFromJson(it, dateUtil) }
?: return
tunedProfile = ATProfile(ProfileSealed.Pure(tuned), localInsulin, injector).also { atProfile ->
atProfile.profilename = tunedProfileName
atProfile.circadianProfile = ProfileSealed.Pure(circadianTuned)
for (i in 0..23) {
atProfile.basalUntuned[i] = JsonHelper.safeGetInt(json,"missingDays_$i")
}
}
result = JsonHelper.safeGetString(json, "result", "")
updateButtonVisibility = JsonHelper.safeGetInt(json, "updateButtonVisibility")
lastRunSuccess = true
} catch (e: Exception) {
}
}
private fun log(message: String) {
atLog("[Plugin] $message")

View file

@ -39,7 +39,7 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.alertDialogs.PrefImportSummaryDialog
import info.nightscout.androidaps.utils.alertDialogs.TwoMessagesAlertDialog
import info.nightscout.androidaps.utils.alertDialogs.WarningDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.androidaps.utils.storage.Storage
import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper

View file

@ -13,7 +13,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import java.io.*

View file

@ -286,14 +286,14 @@ class DataSyncSelectorImplementation @Inject constructor(
bolusCalculatorResult.first.interfaceIDs.nightscoutId == null ->
nsClientPlugin.nsClientService?.dbAdd(
"treatments",
bolusCalculatorResult.first.toJson(true, dateUtil),
bolusCalculatorResult.first.toJson(true, dateUtil, profileFunction),
DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id),
"$startId/$lastDbId"
)
// with nsId = update
bolusCalculatorResult.first.interfaceIDs.nightscoutId != null ->
nsClientPlugin.nsClientService?.dbUpdate(
"treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(false, dateUtil),
"treatments", bolusCalculatorResult.first.interfaceIDs.nightscoutId, bolusCalculatorResult.first.toJson(false, dateUtil, profileFunction),
DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId"
)
}

View file

@ -27,7 +27,7 @@ import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetLong
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.shared.sharedPreferences.SP
import java.util.concurrent.TimeUnit
import javax.inject.Inject

View file

@ -14,7 +14,7 @@ import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject

View file

@ -33,7 +33,7 @@ import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientServ
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper.fromHtml
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag

View file

@ -48,7 +48,7 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.androidaps.utils.JsonHelper.safeGetStringAllowNull
import info.nightscout.androidaps.utils.T.Companion.mins
import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag

View file

@ -251,7 +251,6 @@ class OverviewData @Inject constructor(
var bgReadingGraphSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> = PointsWithLabelGraphSeries()
var predictionsGraphSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> = PointsWithLabelGraphSeries()
var maxBasalValueFound = 0.0
val basalScale = Scale()
var baseBasalGraphSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
var tempBasalGraphSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()

View file

@ -66,7 +66,7 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.TrendCalculator
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.ui.SingleClickButton
@ -224,7 +224,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverviewIobCob::class.java)
.debounce(1L, TimeUnit.SECONDS)
.observeOn(aapsSchedulers.main)
.observeOn(aapsSchedulers.io)
.subscribe({ updateIobCob() }, fabricPrivacy::logException)
disposable += activePlugin.activeOverview.overviewBus
.toObservable(EventUpdateOverviewSensitivity::class.java)
@ -256,7 +256,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
disposable += rxBus
.toObservable(EventNewBG::class.java)
.debounce(1L, TimeUnit.SECONDS)
.observeOn(aapsSchedulers.main)
.observeOn(aapsSchedulers.io)
.subscribe({ updateBg() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventRefreshOverview::class.java)
@ -287,19 +287,19 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
.observeOn(aapsSchedulers.main)
.observeOn(aapsSchedulers.io)
.subscribe({ updateProfile() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventTempTargetChange::class.java)
.observeOn(aapsSchedulers.main)
.observeOn(aapsSchedulers.io)
.subscribe({ updateTemporaryTarget() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventExtendedBolusChange::class.java)
.observeOn(aapsSchedulers.main)
.observeOn(aapsSchedulers.io)
.subscribe({ updateExtendedBolus() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventTempBasalChange::class.java)
.observeOn(aapsSchedulers.main)
.observeOn(aapsSchedulers.io)
.subscribe({ updateTemporaryBasal() }, fabricPrivacy::logException)
refreshLoop = Runnable {
@ -316,17 +316,19 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
fun refreshAll() {
runOnUiThread {
_binding ?: return@runOnUiThread
updateBg()
updateTime()
updateProfile()
updateTemporaryBasal()
updateExtendedBolus()
updateTemporaryTarget()
updateIobCob()
updateSensitivity()
updateGraph()
updateNotification()
}
updateBg()
updateTemporaryBasal()
updateExtendedBolus()
updateIobCob()
processButtonsVisibility()
processAps()
updateProfile()
updateTemporaryTarget()
}
@Synchronized
@ -513,13 +515,16 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// QuickWizard button
val quickWizardEntry = quickWizard.getActive()
if (quickWizardEntry != null && lastBG != null && profile != null && pump.isInitialized() && !pump.isSuspended() && !loop.isDisconnected) {
binding.buttonsLayout.quickWizardButton.visibility = View.VISIBLE
val wizard = quickWizardEntry.doCalc(profile, profileName, lastBG, false)
binding.buttonsLayout.quickWizardButton.text = quickWizardEntry.buttonText() + "\n" + rh.gs(R.string.format_carbs, quickWizardEntry.carbs()) +
" " + rh.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin)
if (wizard.calculatedTotalInsulin <= 0) binding.buttonsLayout.quickWizardButton.visibility = View.GONE
} else binding.buttonsLayout.quickWizardButton.visibility = View.GONE
runOnUiThread {
_binding ?: return@runOnUiThread
if (quickWizardEntry != null && lastBG != null && profile != null && pump.isInitialized() && !pump.isSuspended() && !loop.isDisconnected) {
binding.buttonsLayout.quickWizardButton.visibility = View.VISIBLE
val wizard = quickWizardEntry.doCalc(profile, profileName, lastBG, false)
binding.buttonsLayout.quickWizardButton.text = quickWizardEntry.buttonText() + "\n" + rh.gs(R.string.format_carbs, quickWizardEntry.carbs()) +
" " + rh.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin)
if (wizard.calculatedTotalInsulin <= 0) binding.buttonsLayout.quickWizardButton.visibility = View.GONE
} else binding.buttonsLayout.quickWizardButton.visibility = View.GONE
}
// **** Temp button ****
val lastRun = loop.lastRun
@ -530,72 +535,76 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
(lastRun.lastOpenModeAccept == 0L || lastRun.lastOpenModeAccept < lastRun.lastAPSRun) &&// never accepted or before last result
lastRun.constraintsProcessed?.isChangeRequested == true // change is requested
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && (loop as PluginBase).isEnabled()) {
binding.buttonsLayout.acceptTempButton.visibility = View.VISIBLE
binding.buttonsLayout.acceptTempButton.text = "${rh.gs(R.string.setbasalquestion)}\n${lastRun!!.constraintsProcessed}"
} else {
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
}
// **** Various treatment buttons ****
binding.buttonsLayout.carbsButton.visibility =
((!activePlugin.activePump.pumpDescription.storesCarbInfo || pump.isInitialized() && !pump.isSuspended()) && profile != null
&& sp.getBoolean(R.string.key_show_carbs_button, true)).toVisibility()
binding.buttonsLayout.treatmentButton.visibility = (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null
&& sp.getBoolean(R.string.key_show_treatment_button, false)).toVisibility()
binding.buttonsLayout.wizardButton.visibility = (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null
&& sp.getBoolean(R.string.key_show_wizard_button, true)).toVisibility()
binding.buttonsLayout.insulinButton.visibility = (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null
&& sp.getBoolean(R.string.key_show_insulin_button, true)).toVisibility()
// **** Calibration & CGM buttons ****
val xDripIsBgSource = xdripPlugin.isEnabled()
val dexcomIsSource = dexcomPlugin.isEnabled()
binding.buttonsLayout.calibrationButton.visibility = (xDripIsBgSource && actualBG != null && sp.getBoolean(R.string.key_show_calibration_button, true)).toVisibility()
if (dexcomIsSource) {
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_byoda), null, null)
for (drawable in binding.buttonsLayout.cgmButton.compoundDrawables) {
drawable?.mutate()
drawable?.colorFilter = PorterDuffColorFilter(rh.gac(context, R.attr.cgmDexColor), PorterDuff.Mode.SRC_IN)
runOnUiThread {
_binding ?: return@runOnUiThread
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && (loop as PluginBase).isEnabled()) {
binding.buttonsLayout.acceptTempButton.visibility = View.VISIBLE
binding.buttonsLayout.acceptTempButton.text = "${rh.gs(R.string.setbasalquestion)}\n${lastRun!!.constraintsProcessed}"
} else {
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
}
binding.buttonsLayout.cgmButton.setTextColor(rh.gac(context, R.attr.cgmDexColor))
} else if (xDripIsBgSource) {
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_xdrip), null, null)
for (drawable in binding.buttonsLayout.cgmButton.compoundDrawables) {
drawable?.mutate()
drawable?.colorFilter = PorterDuffColorFilter(rh.gac(context, R.attr.cgmXdripColor), PorterDuff.Mode.SRC_IN)
// **** Various treatment buttons ****
binding.buttonsLayout.carbsButton.visibility =
((!activePlugin.activePump.pumpDescription.storesCarbInfo || pump.isInitialized() && !pump.isSuspended()) && profile != null
&& sp.getBoolean(R.string.key_show_carbs_button, true)).toVisibility()
binding.buttonsLayout.treatmentButton.visibility = (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null
&& sp.getBoolean(R.string.key_show_treatment_button, false)).toVisibility()
binding.buttonsLayout.wizardButton.visibility = (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null
&& sp.getBoolean(R.string.key_show_wizard_button, true)).toVisibility()
binding.buttonsLayout.insulinButton.visibility = (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null
&& sp.getBoolean(R.string.key_show_insulin_button, true)).toVisibility()
// **** Calibration & CGM buttons ****
val xDripIsBgSource = xdripPlugin.isEnabled()
val dexcomIsSource = dexcomPlugin.isEnabled()
binding.buttonsLayout.calibrationButton.visibility = (xDripIsBgSource && actualBG != null && sp.getBoolean(R.string.key_show_calibration_button, true)).toVisibility()
if (dexcomIsSource) {
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_byoda), null, null)
for (drawable in binding.buttonsLayout.cgmButton.compoundDrawables) {
drawable?.mutate()
drawable?.colorFilter = PorterDuffColorFilter(rh.gac(context, R.attr.cgmDexColor), PorterDuff.Mode.SRC_IN)
}
binding.buttonsLayout.cgmButton.setTextColor(rh.gac(context, R.attr.cgmDexColor))
} else if (xDripIsBgSource) {
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_xdrip), null, null)
for (drawable in binding.buttonsLayout.cgmButton.compoundDrawables) {
drawable?.mutate()
drawable?.colorFilter = PorterDuffColorFilter(rh.gac(context, R.attr.cgmXdripColor), PorterDuff.Mode.SRC_IN)
}
binding.buttonsLayout.cgmButton.setTextColor(rh.gac(context, R.attr.cgmXdripColor))
}
binding.buttonsLayout.cgmButton.setTextColor(rh.gac(context, R.attr.cgmXdripColor))
}
binding.buttonsLayout.cgmButton.visibility = (sp.getBoolean(R.string.key_show_cgm_button, false) && (xDripIsBgSource || dexcomIsSource)).toVisibility()
binding.buttonsLayout.cgmButton.visibility = (sp.getBoolean(R.string.key_show_cgm_button, false) && (xDripIsBgSource || dexcomIsSource)).toVisibility()
// Automation buttons
binding.buttonsLayout.userButtonsLayout.removeAllViews()
val events = automationPlugin.userEvents()
if (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null)
for (event in events)
if (event.isEnabled && event.trigger.shouldRun())
context?.let { context ->
SingleClickButton(context).also {
it.setTextColor(rh.gac(context, R.attr.treatmentButton))
it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f)
it.layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 0.5f).also { l ->
l.setMargins(0, 0, rh.dpToPx(-4), 0)
}
it.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_danar_useropt), null, null)
it.text = event.title
// Automation buttons
binding.buttonsLayout.userButtonsLayout.removeAllViews()
val events = automationPlugin.userEvents()
if (!loop.isDisconnected && pump.isInitialized() && !pump.isSuspended() && profile != null)
for (event in events)
if (event.isEnabled && event.trigger.shouldRun())
context?.let { context ->
SingleClickButton(context).also {
it.setTextColor(rh.gac(context, R.attr.treatmentButton))
it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f)
it.layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 0.5f).also { l ->
l.setMargins(0, 0, rh.dpToPx(-4), 0)
}
it.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_danar_useropt), null, null)
it.text = event.title
it.setOnClickListener {
OKDialog.showConfirmation(context, rh.gs(R.string.run_question, event.title), { handler.post { automationPlugin.processEvent(event) } })
it.setOnClickListener {
OKDialog.showConfirmation(context, rh.gs(R.string.run_question, event.title), { handler.post { automationPlugin.processEvent(event) } })
}
binding.buttonsLayout.userButtonsLayout.addView(it)
}
binding.buttonsLayout.userButtonsLayout.addView(it)
}
}
binding.buttonsLayout.userButtonsLayout.visibility = events.isNotEmpty().toVisibility()
binding.buttonsLayout.userButtonsLayout.visibility = events.isNotEmpty().toVisibility()
}
}
private fun processAps() {
val pump = activePlugin.activePump
val profile = profileFunction.getProfile()
// aps mode
val closedLoopEnabled = constraintChecker.isClosedLoopAllowed()
@ -608,103 +617,106 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
}
if (config.APS && pump.pumpDescription.isTempBasalCapable) {
binding.infoLayout.apsMode.visibility = View.VISIBLE
binding.infoLayout.timeLayout.visibility = View.GONE
when {
(loop as PluginBase).isEnabled() && loop.isSuperBolus -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus)
apsModeSetA11yLabel(R.string.superbolus)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
runOnUiThread {
_binding ?: return@runOnUiThread
if (config.APS && pump.pumpDescription.isTempBasalCapable) {
binding.infoLayout.apsMode.visibility = View.VISIBLE
binding.infoLayout.timeLayout.visibility = View.GONE
when {
(loop as PluginBase).isEnabled() && loop.isSuperBolus -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_superbolus)
apsModeSetA11yLabel(R.string.superbolus)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
loop.isDisconnected -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected)
apsModeSetA11yLabel(R.string.disconnected)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
loop.isDisconnected -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disconnected)
apsModeSetA11yLabel(R.string.disconnected)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
(loop as PluginBase).isEnabled() && loop.isSuspended -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused)
apsModeSetA11yLabel(R.string.suspendloop_label)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
(loop as PluginBase).isEnabled() && loop.isSuspended -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_paused)
apsModeSetA11yLabel(R.string.suspendloop_label)
binding.infoLayout.apsModeText.text = dateUtil.age(loop.minutesToEndOfSuspend() * 60000L, true, rh)
binding.infoLayout.apsModeText.visibility = View.VISIBLE
}
pump.isSuspended() -> {
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.
// The only way to 'reconnect' it, is through the Omnipod tab
apsModeSetA11yLabel(R.string.disconnected)
R.drawable.ic_loop_disconnected
} else {
apsModeSetA11yLabel(R.string.pump_paused)
R.drawable.ic_loop_paused
}
)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() && loop.isLGS -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_lgs)
apsModeSetA11yLabel(R.string.uel_lgs_loop_mode)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_closed)
apsModeSetA11yLabel(R.string.closedloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && !closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_open)
apsModeSetA11yLabel(R.string.openloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
else -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disabled)
apsModeSetA11yLabel(R.string.disabledloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
}
// Show variable sensitivity
val request = loop.lastRun?.request
if (request is DetermineBasalResultSMB) {
val isfMgdl = profileFunction.getProfile()?.getIsfMgdl()
val variableSens = request.variableSens
if (variableSens != isfMgdl && variableSens != null && isfMgdl != null) {
binding.infoLayout.variableSensitivity.text =
String.format(
Locale.getDefault(), "%1$.1f→%2$.1f",
Profile.toUnits(isfMgdl, isfMgdl * Constants.MGDL_TO_MMOLL, profileFunction.getUnits()),
Profile.toUnits(variableSens, variableSens * Constants.MGDL_TO_MMOLL, profileFunction.getUnits())
pump.isSuspended() -> {
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.
// The only way to 'reconnect' it, is through the Omnipod tab
apsModeSetA11yLabel(R.string.disconnected)
R.drawable.ic_loop_disconnected
} else {
apsModeSetA11yLabel(R.string.pump_paused)
R.drawable.ic_loop_paused
}
)
binding.infoLayout.variableSensitivity.visibility = View.VISIBLE
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() && loop.isLGS -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_lgs)
apsModeSetA11yLabel(R.string.uel_lgs_loop_mode)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_closed)
apsModeSetA11yLabel(R.string.closedloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
(loop as PluginBase).isEnabled() && !closedLoopEnabled.value() -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_open)
apsModeSetA11yLabel(R.string.openloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
else -> {
binding.infoLayout.apsMode.setImageResource(R.drawable.ic_loop_disabled)
apsModeSetA11yLabel(R.string.disabledloop)
binding.infoLayout.apsModeText.visibility = View.GONE
}
}
// Show variable sensitivity
val request = loop.lastRun?.request
if (request is DetermineBasalResultSMB) {
val isfMgdl = profile?.getIsfMgdl()
val variableSens = request.variableSens
if (variableSens != isfMgdl && variableSens != null && isfMgdl != null) {
binding.infoLayout.variableSensitivity.text =
String.format(
Locale.getDefault(), "%1$.1f→%2$.1f",
Profile.toUnits(isfMgdl, isfMgdl * Constants.MGDL_TO_MMOLL, profileFunction.getUnits()),
Profile.toUnits(variableSens, variableSens * Constants.MGDL_TO_MMOLL, profileFunction.getUnits())
)
binding.infoLayout.variableSensitivity.visibility = View.VISIBLE
} else binding.infoLayout.variableSensitivity.visibility = View.GONE
} else binding.infoLayout.variableSensitivity.visibility = View.GONE
} else binding.infoLayout.variableSensitivity.visibility = View.GONE
} else {
//nsclient
binding.infoLayout.apsMode.visibility = View.GONE
binding.infoLayout.apsModeText.visibility = View.GONE
binding.infoLayout.timeLayout.visibility = View.VISIBLE
} else {
//nsclient
binding.infoLayout.apsMode.visibility = View.GONE
binding.infoLayout.apsModeText.visibility = View.GONE
binding.infoLayout.timeLayout.visibility = View.VISIBLE
}
// pump status from ns
binding.pump.text = nsDeviceStatus.pumpStatus
binding.pump.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.pump), nsDeviceStatus.extendedPumpStatus) } }
// OpenAPS status from ns
binding.openaps.text = nsDeviceStatus.openApsStatus
binding.openaps.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.openaps), nsDeviceStatus.extendedOpenApsStatus) } }
// Uploader status from ns
binding.uploader.text = nsDeviceStatus.uploaderStatusSpanned
binding.uploader.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.uploader), nsDeviceStatus.extendedUploaderStatus) } }
}
// pump status from ns
binding.pump.text = nsDeviceStatus.pumpStatus
binding.pump.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.pump), nsDeviceStatus.extendedPumpStatus) } }
// OpenAPS status from ns
binding.openaps.text = nsDeviceStatus.openApsStatus
binding.openaps.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.openaps), nsDeviceStatus.extendedOpenApsStatus) } }
// Uploader status from ns
binding.uploader.text = nsDeviceStatus.uploaderStatusSpanned
binding.uploader.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.uploader), nsDeviceStatus.extendedUploaderStatus) } }
}
private fun prepareGraphsIfNeeded(numOfGraphs: Int) {
@ -760,59 +772,67 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
@SuppressLint("SetTextI18n")
fun updateBg() {
_binding ?: return
val units = profileFunction.getUnits()
binding.infoLayout.bg.text = overviewData.lastBg?.valueToUnitsString(units)
?: rh.gs(R.string.notavailable)
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor(context))
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor(context))
binding.infoLayout.arrow.contentDescription = overviewData.lastBgDescription + " " + rh.gs(R.string.and) + " " + trendCalculator.getTrendDescription(overviewData.lastBg)
val lastBg = overviewData.lastBg
val lastBgColor = overviewData.lastBgColor(context)
val isActualBg = overviewData.isActualBg
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
if (glucoseStatus != null) {
binding.infoLayout.deltaLarge.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.deltaLarge.setTextColor(overviewData.lastBgColor(context))
binding.infoLayout.delta.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.avgDelta.text = Profile.toSignedUnitsString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.longAvgDelta.text = Profile.toSignedUnitsString(glucoseStatus.longAvgDelta, glucoseStatus.longAvgDelta * Constants.MGDL_TO_MMOLL, units)
} else {
binding.infoLayout.deltaLarge.text = ""
binding.infoLayout.delta.text = "Δ " + rh.gs(R.string.notavailable)
binding.infoLayout.avgDelta.text = ""
binding.infoLayout.longAvgDelta.text = ""
}
val trendDescription = trendCalculator.getTrendDescription(lastBg)
val trendArrow = trendCalculator.getTrendArrow(lastBg)
val lastBgDescription = overviewData.lastBgDescription
runOnUiThread {
_binding ?: return@runOnUiThread
binding.infoLayout.bg.text = lastBg?.valueToUnitsString(units)
?: rh.gs(R.string.notavailable)
binding.infoLayout.bg.setTextColor(lastBgColor)
binding.infoLayout.arrow.setImageResource(trendArrow.directionToIcon())
binding.infoLayout.arrow.setColorFilter(lastBgColor)
binding.infoLayout.arrow.contentDescription = lastBgDescription + " " + rh.gs(R.string.and) + " " + trendDescription
// strike through if BG is old
binding.infoLayout.bg.paintFlags =
if (!overviewData.isActualBg) binding.infoLayout.bg.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else binding.infoLayout.bg.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
val outDate = (if (!overviewData.isActualBg) rh.gs(R.string.a11y_bg_outdated) else "")
binding.infoLayout.bg.contentDescription =
rh.gs(R.string.a11y_blood_glucose) + " " + binding.infoLayout.bg.text.toString() + " " + overviewData.lastBgDescription + " " + outDate
binding.infoLayout.timeAgo.text = dateUtil.minAgo(rh, overviewData.lastBg?.timestamp)
binding.infoLayout.timeAgo.contentDescription = dateUtil.minAgoLong(rh, overviewData.lastBg?.timestamp)
binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(overviewData.lastBg?.timestamp) + ")"
val qualityIcon = bgQualityCheckPlugin.icon()
if (qualityIcon != 0) {
binding.infoLayout.bgQuality.visibility = View.VISIBLE
binding.infoLayout.bgQuality.setImageResource(qualityIcon)
binding.infoLayout.bgQuality.contentDescription = rh.gs(R.string.a11y_bg_quality) + " " + bgQualityCheckPlugin.stateDescription()
binding.infoLayout.bgQuality.setOnClickListener {
context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) }
if (glucoseStatus != null) {
binding.infoLayout.deltaLarge.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.deltaLarge.setTextColor(lastBgColor)
binding.infoLayout.delta.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.avgDelta.text = Profile.toSignedUnitsString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units)
binding.infoLayout.longAvgDelta.text = Profile.toSignedUnitsString(glucoseStatus.longAvgDelta, glucoseStatus.longAvgDelta * Constants.MGDL_TO_MMOLL, units)
} else {
binding.infoLayout.deltaLarge.text = ""
binding.infoLayout.delta.text = "Δ " + rh.gs(R.string.notavailable)
binding.infoLayout.avgDelta.text = ""
binding.infoLayout.longAvgDelta.text = ""
}
// strike through if BG is old
binding.infoLayout.bg.paintFlags =
if (!isActualBg) binding.infoLayout.bg.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else binding.infoLayout.bg.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
val outDate = (if (!isActualBg) rh.gs(R.string.a11y_bg_outdated) else "")
binding.infoLayout.bg.contentDescription = rh.gs(R.string.a11y_blood_glucose) + " " + binding.infoLayout.bg.text.toString() + " " + lastBgDescription + " " + outDate
binding.infoLayout.timeAgo.text = dateUtil.minAgo(rh, lastBg?.timestamp)
binding.infoLayout.timeAgo.contentDescription = dateUtil.minAgoLong(rh, lastBg?.timestamp)
binding.infoLayout.timeAgoShort.text = "(" + dateUtil.minAgoShort(lastBg?.timestamp) + ")"
val qualityIcon = bgQualityCheckPlugin.icon()
if (qualityIcon != 0) {
binding.infoLayout.bgQuality.visibility = View.VISIBLE
binding.infoLayout.bgQuality.setImageResource(qualityIcon)
binding.infoLayout.bgQuality.contentDescription = rh.gs(R.string.a11y_bg_quality) + " " + bgQualityCheckPlugin.stateDescription()
binding.infoLayout.bgQuality.setOnClickListener {
context?.let { context -> OKDialog.show(context, rh.gs(R.string.data_status), bgQualityCheckPlugin.message) }
}
} else {
binding.infoLayout.bgQuality.visibility = View.GONE
}
} else {
binding.infoLayout.bgQuality.visibility = View.GONE
}
}
fun updateProfile() {
_binding ?: return
val profileBackgroundColor =
profileFunction.getProfile()?.let {
val profile = profileFunction.getProfile()
runOnUiThread {
_binding ?: return@runOnUiThread
val profileBackgroundColor = profile?.let {
if (it is ProfileSealed.EPS) {
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
R.attr.ribbonWarningColor
@ -824,8 +844,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
}
} ?: R.attr.ribbonCriticalColor
val profileTextColor =
profileFunction.getProfile()?.let {
val profileTextColor = profile?.let {
if (it is ProfileSealed.EPS) {
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
R.attr.ribbonTextWarningColor
@ -836,27 +855,35 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
R.attr.ribbonTextDefaultColor
}
} ?: R.attr.ribbonTextDefaultColor
setRibbon(binding.activeProfile, profileTextColor, profileBackgroundColor, profileFunction.getProfileNameWithRemainingTime())
setRibbon(binding.activeProfile, profileTextColor, profileBackgroundColor, profileFunction.getProfileNameWithRemainingTime())
}
}
private fun updateTemporaryBasal() {
_binding ?: return
binding.infoLayout.baseBasal.text = overviewData.temporaryBasalText(iobCobCalculator)
binding.infoLayout.baseBasal.setTextColor(overviewData.temporaryBasalColor(context, iobCobCalculator))
binding.infoLayout.baseBasalIcon.setImageResource(overviewData.temporaryBasalIcon(iobCobCalculator))
binding.infoLayout.basalLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.basal), overviewData.temporaryBasalDialogText(iobCobCalculator)) }
val temporaryBasalText = overviewData.temporaryBasalText(iobCobCalculator)
val temporaryBasalColor = overviewData.temporaryBasalColor(context, iobCobCalculator)
val temporaryBasalIcon = overviewData.temporaryBasalIcon(iobCobCalculator)
val temporaryBasalDialogText = overviewData.temporaryBasalDialogText(iobCobCalculator)
runOnUiThread {
_binding ?: return@runOnUiThread
binding.infoLayout.baseBasal.text = temporaryBasalText
binding.infoLayout.baseBasal.setTextColor(temporaryBasalColor)
binding.infoLayout.baseBasalIcon.setImageResource(temporaryBasalIcon)
binding.infoLayout.basalLayout.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.basal), temporaryBasalDialogText) } }
}
}
private fun updateExtendedBolus() {
_binding ?: return
val pump = activePlugin.activePump
binding.infoLayout.extendedBolus.text = overviewData.extendedBolusText(iobCobCalculator)
binding.infoLayout.extendedLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), overviewData.extendedBolusDialogText(iobCobCalculator)) }
val extendedBolus = iobCobCalculator.getExtendedBolus(dateUtil.now())
val extendedBolusText = overviewData.extendedBolusText(iobCobCalculator)
val extendedBolusDialogText = overviewData.extendedBolusDialogText(iobCobCalculator)
runOnUiThread {
_binding ?: return@runOnUiThread
binding.infoLayout.extendedBolus.text = extendedBolusText
binding.infoLayout.extendedLayout.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), extendedBolusDialogText) } }
binding.infoLayout.extendedLayout.visibility = (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
}
binding.infoLayout.extendedLayout.visibility = (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
}
fun updateTime() {
@ -887,69 +914,73 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
binding.statusLightsLayout.pbAge,
binding.statusLightsLayout.batteryLevel
)
processButtonsVisibility()
processAps()
}
fun updateIobCob() {
_binding ?: return
binding.infoLayout.iob.text = overviewData.iobText(iobCobCalculator)
binding.infoLayout.iobLayout.setOnClickListener {
activity?.let { OKDialog.show(it, rh.gs(R.string.iob), overviewData.iobDialogText(iobCobCalculator)) }
}
// cob
var cobText = overviewData.cobInfo(iobCobCalculator).displayText(rh, dateUtil, buildHelper.isEngineeringMode()) ?: rh.gs(R.string.value_unavailable_short)
val iobText = overviewData.iobText(iobCobCalculator)
val iobDialogText = overviewData.iobDialogText(iobCobCalculator)
val displayText = overviewData.cobInfo(iobCobCalculator).displayText(rh, dateUtil, buildHelper.isEngineeringMode())
val lastCarbsTime = overviewData.lastCarbsTime
runOnUiThread {
_binding ?: return@runOnUiThread
binding.infoLayout.iob.text = iobText
binding.infoLayout.iobLayout.setOnClickListener { activity?.let { OKDialog.show(it, rh.gs(R.string.iob), iobDialogText) } }
// cob
var cobText = displayText ?: rh.gs(R.string.value_unavailable_short)
val constraintsProcessed = loop.lastRun?.constraintsProcessed
val lastRun = loop.lastRun
if (config.APS && constraintsProcessed != null && lastRun != null) {
if (constraintsProcessed.carbsReq > 0) {
//only display carbsreq when carbs have not been entered recently
if (overviewData.lastCarbsTime < lastRun.lastAPSRun) {
cobText += " | " + constraintsProcessed.carbsReq + " " + rh.gs(R.string.required)
val constraintsProcessed = loop.lastRun?.constraintsProcessed
val lastRun = loop.lastRun
if (config.APS && constraintsProcessed != null && lastRun != null) {
if (constraintsProcessed.carbsReq > 0) {
//only display carbsreq when carbs have not been entered recently
if (lastCarbsTime < lastRun.lastAPSRun) {
cobText += " | " + constraintsProcessed.carbsReq + " " + rh.gs(R.string.required)
}
if (carbAnimation?.isRunning == false)
carbAnimation?.start()
} else {
carbAnimation?.stop()
carbAnimation?.selectDrawable(0)
}
if (carbAnimation?.isRunning == false)
carbAnimation?.start()
} else {
carbAnimation?.stop()
carbAnimation?.selectDrawable(0)
}
binding.infoLayout.cob.text = cobText
}
binding.infoLayout.cob.text = cobText
}
@SuppressLint("SetTextI18n")
fun updateTemporaryTarget() {
_binding ?: return
val units = profileFunction.getUnits()
val tempTarget = overviewData.temporaryTarget
if (tempTarget != null) {
setRibbon(
binding.tempTarget,
R.attr.ribbonTextWarningColor,
R.attr.ribbonWarningColor,
Profile.toTargetRangeString(tempTarget.lowTarget, tempTarget.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.end, rh)
)
} else {
// If the target is not the same as set in the profile then oref has overridden it
profileFunction.getProfile()?.let { profile ->
val targetUsed = loop.lastRun?.constraintsProcessed?.targetBG ?: 0.0
runOnUiThread {
_binding ?: return@runOnUiThread
if (tempTarget != null) {
setRibbon(
binding.tempTarget,
R.attr.ribbonTextWarningColor,
R.attr.ribbonWarningColor,
Profile.toTargetRangeString(tempTarget.lowTarget, tempTarget.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.end, rh)
)
} else {
// If the target is not the same as set in the profile then oref has overridden it
profileFunction.getProfile()?.let { profile ->
val targetUsed = loop.lastRun?.constraintsProcessed?.targetBG ?: 0.0
if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
setRibbon(
binding.tempTarget,
R.attr.ribbonTextWarningColor,
R.attr.tempTargetBackgroundColor,
Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units)
)
} else {
setRibbon(
binding.tempTarget,
R.attr.ribbonTextDefaultColor,
R.attr.ribbonDefaultColor,
Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units)
)
if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
setRibbon(
binding.tempTarget,
R.attr.ribbonTextWarningColor,
R.attr.tempTargetBackgroundColor,
Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units)
)
} else {
setRibbon(
binding.tempTarget,
R.attr.ribbonTextDefaultColor,
R.attr.ribbonDefaultColor,
Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units)
)
}
}
}
}

View file

@ -19,7 +19,7 @@ import info.nightscout.androidaps.interfaces.Loop
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.general.overview
import android.graphics.Color
import android.widget.TextView
import androidx.annotation.StringRes
import info.nightscout.androidaps.R
@ -97,7 +96,7 @@ class StatusLightHandler @Inject constructor(
if (level > OmnipodConstants.MAX_RESERVOIR_READING) {
@Suppress("SetTextI18n")
view?.text = " 50+$units"
view?.setTextColor(Color.WHITE)
view?.setTextColor(rh.gac(view.context, R.attr.defaultTextColor))
} else {
handleLevel(view, criticalSetting, criticalDefaultValue, warnSetting, warnDefaultValue, level, units)
}

View file

@ -73,12 +73,16 @@ class GraphData(
}
fun addBasals() {
val scale = defaultValueHelper.determineLowLine() / maxY / 1.2
overviewData.basalScale.multiplier = 1.0 // get unscaled Y-values for max calculation
var maxBasalValue = maxOf(0.1, overviewData.baseBasalGraphSeries.highestValueY, overviewData.tempBasalGraphSeries.highestValueY)
maxBasalValue = maxOf(maxBasalValue, overviewData.basalLineGraphSeries.highestValueY, overviewData.absoluteBasalGraphSeries.highestValueY)
addSeries(overviewData.baseBasalGraphSeries)
addSeries(overviewData.tempBasalGraphSeries)
addSeries(overviewData.basalLineGraphSeries)
addSeries(overviewData.absoluteBasalGraphSeries)
overviewData.basalScale.multiplier = maxY * scale / overviewData.maxBasalValueFound
maxY = max(maxY, defaultValueHelper.determineHighLine())
val scale = defaultValueHelper.determineLowLine() / maxY / 1.2
overviewData.basalScale.multiplier = maxY * scale / maxBasalValue
}
fun addTargetLine() {

View file

@ -17,12 +17,12 @@ import info.nightscout.androidaps.databinding.OverviewNotificationItemBinding
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IconsProvider
import info.nightscout.androidaps.interfaces.NotificationHolder
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewNotification
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import java.util.*
import javax.inject.Inject
@ -68,7 +68,7 @@ class NotificationStore @Inject constructor(
store.add(n)
if (sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true) && n !is NotificationWithAction)
raiseSystemNotification(n)
if (n.soundId != null && n.soundId != 0) alarmSoundServiceHelper.startAlarm(context, n.soundId!!)
if (n.soundId != null && n.soundId != 0) alarmSoundServiceHelper.startAlarm(context, n.soundId!!, n.text)
Collections.sort(store, NotificationComparator())
return true
}
@ -77,7 +77,7 @@ class NotificationStore @Inject constructor(
fun remove(id: Int): Boolean {
for (i in store.indices) {
if (store[i].id == id) {
if (store[i].soundId != null) alarmSoundServiceHelper.stopService(context)
if (store[i].soundId != null) alarmSoundServiceHelper.stopService(context, "Removed " + store[i].text)
aapsLogger.debug(LTag.NOTIFICATION, "Notification removed: " + store[i].text)
store.removeAt(i)
return true
@ -92,7 +92,7 @@ class NotificationStore @Inject constructor(
while (i < store.size) {
val n = store[i]
if (n.validTo != 0L && n.validTo < System.currentTimeMillis()) {
if (store[i].soundId != null) alarmSoundServiceHelper.stopService(context)
if (store[i].soundId != null) alarmSoundServiceHelper.stopService(context, "Expired " + store[i].text)
aapsLogger.debug(LTag.NOTIFICATION, "Notification expired: " + store[i].text)
store.removeAt(i)
i--

View file

@ -966,6 +966,7 @@ class SmsCommunicatorPlugin @Inject constructor(
var keyTarget = 0
var defaultTargetMMOL = 0.0
var defaultTargetMGDL = 0.0
var reason = TemporaryTarget.Reason.EATING_SOON
when {
isMeal -> {
keyDuration = R.string.key_eatingsoon_duration
@ -973,6 +974,7 @@ class SmsCommunicatorPlugin @Inject constructor(
keyTarget = R.string.key_eatingsoon_target
defaultTargetMMOL = Constants.defaultEatingSoonTTmmol
defaultTargetMGDL = Constants.defaultEatingSoonTTmgdl
reason = TemporaryTarget.Reason.EATING_SOON
}
isActivity -> {
@ -981,6 +983,7 @@ class SmsCommunicatorPlugin @Inject constructor(
keyTarget = R.string.key_activity_target
defaultTargetMMOL = Constants.defaultActivityTTmmol
defaultTargetMGDL = Constants.defaultActivityTTmgdl
reason = TemporaryTarget.Reason.ACTIVITY
}
isHypo -> {
@ -989,6 +992,7 @@ class SmsCommunicatorPlugin @Inject constructor(
keyTarget = R.string.key_hypo_target
defaultTargetMMOL = Constants.defaultHypoTTmmol
defaultTargetMGDL = Constants.defaultHypoTTmgdl
reason = TemporaryTarget.Reason.HYPOGLYCEMIA
}
}
var ttDuration = sp.getInt(keyDuration, defaultTargetDuration)
@ -999,7 +1003,7 @@ class SmsCommunicatorPlugin @Inject constructor(
disposable += repository.runTransactionForResult(InsertAndCancelCurrentTemporaryTargetTransaction(
timestamp = dateUtil.now(),
duration = TimeUnit.MINUTES.toMillis(ttDuration.toLong()),
reason = TemporaryTarget.Reason.EATING_SOON,
reason = reason,
lowTarget = Profile.toMgdl(tt, profileFunction.getUnits()),
highTarget = Profile.toMgdl(tt, profileFunction.getUnits())
)).subscribe({ result ->

View file

@ -30,6 +30,7 @@ import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.workflow.CalculationWorkflow
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
@ -127,10 +128,20 @@ class IobCobCalculatorPlugin @Inject constructor(
}
private fun resetDataAndRunCalculation(reason: String, event: Event?) {
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION,reason)
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION, reason)
clearCache()
ads.reset()
calculationWorkflow.runCalculation(CalculationWorkflow.MAIN_CALCULATION,this, overviewData, reason, System.currentTimeMillis(), bgDataReload = false, limitDataToOldestAvailable = true, cause = event, runLoop = true)
calculationWorkflow.runCalculation(
CalculationWorkflow.MAIN_CALCULATION,
this,
overviewData,
reason,
System.currentTimeMillis(),
bgDataReload = false,
limitDataToOldestAvailable = true,
cause = event,
runLoop = true
)
}
override fun clearCache() {
@ -363,18 +374,21 @@ class IobCobCalculatorPlugin @Inject constructor(
scheduledHistoryPost?.cancel(false)
// prepare task for execution in 1 sec
scheduledEvent = event
scheduledHistoryPost = historyWorker.schedule({
synchronized(this) {
aapsLogger.debug(LTag.AUTOSENS, "Running newHistoryData")
newHistoryData(
event.oldDataTimestamp,
event.reloadBgData,
if (event.newestGlucoseValue != null) EventNewBG(event.newestGlucoseValue) else event
)
scheduledEvent = null
scheduledHistoryPost = null
}
}, 1L, TimeUnit.SECONDS)
scheduledHistoryPost = historyWorker.schedule(
{
synchronized(this) {
aapsLogger.debug(LTag.AUTOSENS, "Running newHistoryData")
repository.clearCachedData(MidnightTime.calc(event.oldDataTimestamp))
newHistoryData(
event.oldDataTimestamp,
event.reloadBgData,
if (event.newestGlucoseValue != null) EventNewBG(event.newestGlucoseValue) else event
)
scheduledEvent = null
scheduledHistoryPost = null
}
}, 1L, TimeUnit.SECONDS
)
} else {
// asked reload is newer -> adjust params only
scheduledEvent?.let {
@ -391,7 +405,7 @@ class IobCobCalculatorPlugin @Inject constructor(
// When historical data is changed (coming from NS etc) finished calculations after this date must be invalidated
private fun newHistoryData(oldDataTimestamp: Long, bgDataReload: Boolean, event: Event) {
//log.debug("Locking onNewHistoryData");
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION,"onEventNewHistoryData")
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION, "onEventNewHistoryData")
synchronized(dataLock) {
// clear up 5 min back for proper COB calculation
@ -415,7 +429,7 @@ class IobCobCalculatorPlugin @Inject constructor(
}
ads.newHistoryData(time, aapsLogger, dateUtil)
}
calculationWorkflow.runCalculation(CalculationWorkflow.MAIN_CALCULATION,this, overviewData, event.javaClass.simpleName, System.currentTimeMillis(), bgDataReload, true, event, runLoop = true)
calculationWorkflow.runCalculation(CalculationWorkflow.MAIN_CALCULATION, this, overviewData, event.javaClass.simpleName, System.currentTimeMillis(), bgDataReload, true, event, runLoop = true)
//log.debug("Releasing onNewHistoryData");
}

View file

@ -30,7 +30,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.workflow.CalculationWorkflow
import info.nightscout.shared.logging.AAPSLogger

View file

@ -28,7 +28,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.workflow.CalculationWorkflow
import info.nightscout.shared.logging.AAPSLogger

View file

@ -10,13 +10,10 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.database.transactions.CgmSourceTransaction
import info.nightscout.androidaps.interfaces.BgSource
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.receivers.DataWorker
import info.nightscout.androidaps.receivers.Intents
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
@ -26,7 +23,9 @@ import javax.inject.Singleton
class AidexPlugin @Inject constructor(
injector: HasAndroidInjector,
rh: ResourceHelper,
aapsLogger: AAPSLogger
aapsLogger: AAPSLogger,
private val buildHelper: BuildHelper,
private val config: Config
) : PluginBase(
PluginDescription()
.mainType(PluginType.BGSOURCE)
@ -49,6 +48,11 @@ class AidexPlugin @Inject constructor(
return advancedFiltering
}
// Allow only for pumpcontrol or dev & engineering_mode
override fun specialEnableCondition(): Boolean {
return config.APS.not() || buildHelper.isDev() && buildHelper.isEngineeringMode()
}
// cannot be inner class because of needed injection
class AidexWorker(
context: Context,

View file

@ -35,7 +35,7 @@ import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
@ -327,7 +327,7 @@ class CommandQueueImplementation @Inject constructor(
}
removeAll(CommandType.BOLUS)
removeAll(CommandType.SMB_BOLUS)
Thread { activePlugin.activePump.stopBolusDelivering() }.run()
Thread { activePlugin.activePump.stopBolusDelivering() }.start()
}
// returns true if command is queued

View file

@ -12,15 +12,15 @@ import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnoun
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
@ -128,7 +128,7 @@ class LocalAlertUtils @Inject constructor(
rxBus.send(EventNewNotification(n))
uel.log(Action.CAREPORTAL, Sources.Aaps, rh.gs(R.string.missed_bg_readings), ValueWithUnit.TherapyEventType(TherapyEvent.Type.ANNOUNCEMENT))
if (sp.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
n.text?.let { disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(it)).subscribe() }
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(n.text)).subscribe()
}
} else if (dateUtil.isOlderThan(bgReading.timestamp, 5).not()) {
rxBus.send(EventDismissNotification(Notification.BG_READINGS_MISSED))

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.utils.buildHelper
import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
import java.io.File

View file

@ -11,6 +11,8 @@ import android.widget.TableRow
import android.widget.TextView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.entities.TotalDailyDose
import info.nightscout.androidaps.extensions.convertedToAbsolute
@ -19,10 +21,10 @@ import info.nightscout.androidaps.extensions.toTableRowHeader
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.IobCobCalculator
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.MidnightTime
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
@ -38,48 +40,62 @@ class TddCalculator @Inject constructor(
) {
fun calculate(days: Long): LongSparseArray<TotalDailyDose> {
val startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
var startTime = MidnightTime.calc(dateUtil.now() - T.days(days).msecs())
val endTime = MidnightTime.calc(dateUtil.now())
val result = LongSparseArray<TotalDailyDose>()
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.forEach { t ->
val midnight = MidnightTime.calc(t.timestamp)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.bolusAmount += t.amount
result.put(midnight, tdd)
}
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
val midnight = MidnightTime.calc(t.timestamp)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.carbs += t.amount
result.put(midnight, tdd)
// Try to load cached values
while (startTime < endTime) {
val tdd = repository.getCalculatedTotalDailyDose(startTime).blockingGet()
if (tdd is ValueWrapper.Existing) result.put(startTime, tdd.value)
else break
startTime += T.hours(24).msecs()
}
val calculationStep = T.mins(5).msecs()
val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep)
for (t in startTime until endTime step calculationStep) {
val midnight = MidnightTime.calc(t)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = tempBasals[t]
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basalAmount += absoluteRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
if (endTime > startTime) {
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.forEach { t ->
val midnight = MidnightTime.calc(t.timestamp)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.bolusAmount += t.amount
result.put(midnight, tdd)
}
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
val midnight = MidnightTime.calc(t.timestamp)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.carbs += t.amount
result.put(midnight, tdd)
}
val calculationStep = T.mins(5).msecs()
val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep)
for (t in startTime until endTime step calculationStep) {
val midnight = MidnightTime.calc(t)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = tempBasals[t]
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basalAmount += absoluteRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
// they are not included in TBRs
val eb = iobCobCalculator.getExtendedBolus(t)
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / T.mins(60).msecs().toDouble() * calculationStep.toDouble()
}
result.put(midnight, tdd)
}
result.put(midnight, tdd)
}
for (i in 0 until result.size()) {
val tdd = result.valueAt(i)
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
if (tdd.interfaceIDs.pumpType != InterfaceIDs.PumpType.CACHE) {
tdd.interfaceIDs.pumpType = InterfaceIDs.PumpType.CACHE
aapsLogger.debug(LTag.CORE, "Storing TDD $tdd")
repository.createTotalDailyDose(tdd)
}
}
aapsLogger.debug(LTag.CORE, result.toString())
return result
}
@ -91,22 +107,13 @@ class TddCalculator @Inject constructor(
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.bolusAmount += t.amount
//result.put(midnight, tdd)
}
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.carbs += t.amount
//result.put(midnight, tdd)
}
val calculationStep = T.mins(5).msecs()
for (t in startTime until endTime step calculationStep) {
//val midnight = MidnightTime.calc(t)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t)
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
@ -118,13 +125,8 @@ class TddCalculator @Inject constructor(
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0
}
//result.put(midnight, tdd)
}
//for (i in 0 until tdd.size()) {
//val tdd = result.valueAt(i)
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
//}
aapsLogger.debug(LTag.CORE, tdd.toString())
return tdd
}
@ -133,27 +135,16 @@ class TddCalculator @Inject constructor(
val startTime = dateUtil.now() - T.hours(hour = 24).msecs()
val endTime = dateUtil.now()
val tdd = TotalDailyDose(timestamp = startTime)
//val result = TotalDailyDose()
repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet()
.filter { it.type != Bolus.Type.PRIMING }
.forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.bolusAmount += t.amount
//result.put(midnight, tdd)
}
repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t ->
//val midnight = MidnightTime.calc(t.timestamp)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
tdd.carbs += t.amount
//result.put(midnight, tdd)
}
val calculationStep = T.mins(5).msecs()
//val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep)
for (t in startTime until endTime step calculationStep) {
//val midnight = MidnightTime.calc(t)
//val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t)
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
@ -165,13 +156,8 @@ class TddCalculator @Inject constructor(
val absoluteEbRate = eb?.rate ?: 0.0
tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0
}
//result.put(midnight, tdd)
}
//for (i in 0 until tdd.size()) {
//val tdd = result.valueAt(i)
tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount
//}
aapsLogger.debug(LTag.CORE, tdd.toString())
return tdd
}

View file

@ -47,7 +47,6 @@ class PrepareBasalDataWorker(
?: return Result.failure(workDataOf("Error" to "missing input data"))
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_BASAL_DATA, 0, null))
data.overviewData.maxBasalValueFound = 0.0
val baseBasalArray: MutableList<ScaledDataPoint> = ArrayList()
val tempBasalArray: MutableList<ScaledDataPoint> = ArrayList()
val basalLineArray: MutableList<ScaledDataPoint> = ArrayList()
@ -104,7 +103,6 @@ class PrepareBasalDataWorker(
lastAbsoluteLineBasal = absoluteLineValue
lastLineBasal = baseBasalValue
lastTempBasal = tempBasalValue
data.overviewData.maxBasalValueFound = max(data.overviewData.maxBasalValueFound, max(tempBasalValue, baseBasalValue))
time += 60 * 1000L
}

View file

@ -140,7 +140,8 @@
android:gravity="start"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textSize="14sp" />
android:textSize="14sp"
android:textColor="@color/colorCalculatorButton"/>
</LinearLayout>

View file

@ -127,6 +127,7 @@
<string name="end_user_license_agreement">Eindverbruiker Lisensie Ooreenkoms</string>
<string name="end_user_license_agreement_text">MOET NIE GEBRUIK WORD OM MEDIESE BESLUITE TE MAAK NIE. DAAR IS GEEN WAARBORG DAT DIE PROGRAM, ONDERWORPE AAN TOEPASSELIKE WETTE EN WETGEWING. TENSY ANDERS GEMELD IN TEKS VOORSIEN DIE KOPIEREG-HOUERS EN / OF ANDER PARTYE DIE PROGRAM \"AS IS\" SONDER ËNIGE WAARBORG VAN ENIGE ORDE, UITDRUKKELIK OF IMPLISIET, INKLUSIEF, MAAR NIE BEPERK TOT DIE IMPLISIETE WAARBORG VAN TOEPAASBAARHEID OF NUT VIR EEN SPESIFIEKE DOEL. DIE TOTALE EN ALLE RISIKOVIR DIE KWALITEIT EN PRESTASIE VAN DIE PROGRAM RUS MET JOUSELF. VIR ENIGE PROGRAM DEFEKTIEWE OF FALINGS MOET JY PERSOONLIK DIE KOSTE EN REGSAANSPREEKLIKHEID DRA VAN ALLE NODIGE AKSIES, DIENS, REPARASIES OF KORREKSIES VIR USELF OF ENIGE DERDE PARTYE EN/OF AKSIES, DIENS, REPARASIES OF KORREKSIES WAT DEUR DIE PROGRAM GEDOEN WAS.</string>
<string name="end_user_license_agreement_i_understand">EK VERSTAAN en STEM IN</string>
<string name="save">Stoor</string>
<string name="reloadprofile">Herlaai profiel</string>
<string name="smscommunicator">SMS Communicator</string>
<string name="smscommunicator_allowednumbers">Toegelate telefoon nommers</string>

View file

@ -879,5 +879,6 @@
<string name="not_available_full">Недостъпно</string>
<!-- Theme switcher dark and light mode-->
<!-- WEAR OS-->
<string name="login">Вход</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -154,6 +154,7 @@
<string name="end_user_license_agreement">Acord de llicència per a l\'usuari final</string>
<string name="end_user_license_agreement_text">NO S\'HA D\'UTILITZAR PER A PRENDRE DECISIONS MÈDIQUES. EL PROGRAMA NO TÉ GARANTIA, EN LA MESURA QUE HO PERMET LA LLEI APLICABLE. EXCEPTE QUAN S\'INDIQUI EL CONTRARI PER ESCRIT, ELS PROPIETARIS DEL COPYRIGHT I/O ALTRES PARTS PROPORCIONEN EL PROGRAMA \"TAL QUAL\" SENSE CAP MENA DE GARANTIA, NI IMPLÍCITA NI EXPLÍCITA, INCLOENT, PERÒ SENSE ESTAR LIMITADES A, LES GARANTIES IMPLÍCITES DE COMERCIALITZACIÓ I ADEQUACIÓ A UN OBJECTIU PARTICULAR. US FEU RESPONSABLES TOTALMENT DELS RISCOS EN QUANT A LA QUALITAT I EL RENDIMENT DEL PROGRAMA. SI EL PROGRAMA FOS DEFECTUÓS, VOSALTRES ASSUMIU EL COST DE TOT SERVEI, REPARACIÓ O CORRECCIÓ.</string>
<string name="end_user_license_agreement_i_understand">ENTENC I ACCEPTO</string>
<string name="save">Desar</string>
<string name="reloadprofile">Recarregar perfil</string>
<string name="smscommunicator">Comunicador SMS</string>
<string name="smscommunicator_allowednumbers">Nrs. de telèfon permesos</string>
@ -314,5 +315,6 @@
<!-- SMS Communicator & OTP Authenticator -->
<!-- Theme switcher dark and light mode-->
<!-- WEAR OS-->
<string name="login">Iniciar sessió</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -159,6 +159,7 @@
<string name="end_user_license_agreement">Endbenutzervereinbarung</string>
<string name="end_user_license_agreement_text">DAS PROGRAMM DARF NICHT FÜR MEDIZINISCHE ENTSCHEIDUNGEN BENUTZT WERDEN. ES GIBT IN DIESEM PROJEKT KEINE GEWÄHRLEISTUNG ODER GARANTIERTE UNTERSTÜTZUNG IN IRGENDEINER ART. WENN DU DICH ENTSCHEIDEST, ES ZU NUTZEN, HÄNGT DIE QUALITÄT UND LEISTUNGSFÄHIGKEIT DIESES PROJEKTES VON DIR SELBST AB. ES WIRD \"WIE BESEHEN\" ZUR VERFÜGUNG GESTELLT. SOLLTE SICH DAS PROGRAMM ALS FEHLERHAFT ERWEISEN, ÜBERNIMMST DU ALLE NOTWENDIGEN KRANKHEITSKOSTEN, SERVICELEISTUNGEN, REPARATUREN ODER KORREKTUREN.</string>
<string name="end_user_license_agreement_i_understand">Ich verstehe und stimme zu.</string>
<string name="save">Speichern</string>
<string name="reloadprofile">Profil neuladen</string>
<string name="smscommunicator">SMS-Kommunikator</string>
<string name="smscommunicator_allowednumbers">Erlaubte Telefonnummern</string>
@ -939,5 +940,7 @@ Unerwartetes Verhalten.</string>
<string name="carbs_and_bolus">Kohlenhydrate &amp; Bolus</string>
<string name="confirm_remove_multiple_items">Sind Sie sicher, dass Sie diese(s) %1$d Element(e) löschen möchten?</string>
<string name="count_selected">%1$d ausgewählt</string>
<string name="sort_label">Sortieren</string>
<string name="login">Login</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -605,7 +605,11 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
<string name="secondcarbsincrement">Deuxième incrément de glucides</string>
<string name="thirdcarbsincrement">Troisième incrément de glucides</string>
<string name="cgm">MGC</string>
<string name="ns_cellular">Utiliser la connexion mobile</string>
<string name="ns_wifi">Utilisez la connexion Wi-Fi</string>
<string name="ns_wifi_ssids">Wi-fi SSID</string>
<string name="ns_charging">Pendant la charge</string>
<string name="ns_battery">Sur batterie</string>
<string name="connectionsettings_title">Paramètres de connexion</string>
<string name="ns_wifi_allowedssids">SSIDs autorisés (séparés par point-virgule)</string>
<string name="ns_allowroaming">Autoriser connexion données itinérance</string>
@ -684,7 +688,7 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
<string name="miscellaneous">Divers</string>
<string name="nav_logsettings">Paramètres journal</string>
<string name="resettodefaults">Réinitialiser les valeurs par défaut</string>
<string name="nsmalfunction">Dysfonctionnement NSClient. Faites une réinitialisation de NS et de NSClient.</string>
<string name="nsmalfunction">Dysfonctionnement NSClient. Redémarrez NS et NSClient.</string>
<string name="time_offset">Décalage horaire</string>
<string name="bolus_reminder">Rappel du bolus plus tard</string>
<string name="setupwizard_preferred_aps_mode">Mode APS préféré</string>
@ -1035,4 +1039,6 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
<string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string>
<string name="description_source_aidex">Recevoir les valeurs de glycémie du MGC GlucoRx Aidex.</string>
<string name="blocked_by_charging">Bloqué par les options de recharge</string>
<string name="blocked_by_connectivity">Bloqué par les options de connectivité</string>
</resources>

View file

@ -59,6 +59,7 @@
<string name="nav_export">Socruithe Easpórtáil</string>
<string name="nav_import">Socruithe Iompórtáil</string>
<string name="check_preferences_import_btn">Iompórtáil</string>
<string name="save">Sábháil</string>
<string name="reloadprofile">Athlódáil próifíl</string>
<string name="smscommunicator_loophasbeendisabled">Is lúb díchumasaithe</string>
<string name="smscommunicator_loophasbeenenabled">Is lúb cumasaithe</string>

View file

@ -155,6 +155,7 @@
<string name="end_user_license_agreement">최종 사용자 라이선스 동의서</string>
<string name="end_user_license_agreement_text">이 프로그램을 의학적 결정을 내리는 데 사용해서는 안되며, 여기에 대한 어떠한 보증도 없습니다. 이 프로그램의 품질과 성능에 관한 모든 위험은 사용자에게 있습니다.\nMUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</string>
<string name="end_user_license_agreement_i_understand">모두 이해하였고 동의합니다.</string>
<string name="save">저장</string>
<string name="reloadprofile">프로파일 새로고침</string>
<string name="smscommunicator">SMS 통신기</string>
<string name="smscommunicator_allowednumbers">허가된 전화번호</string>
@ -849,5 +850,6 @@
<string name="calculation_in_progress">계산 진행 중</string>
<!-- Theme switcher dark and light mode-->
<!-- WEAR OS-->
<string name="login">로그인</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -159,6 +159,7 @@
<string name="end_user_license_agreement">Licencinė sutartis su vartotoju</string>
<string name="end_user_license_agreement_text">PROGRAMA NEGALI BŪTI NAUDOJAMA GYDYMO SPRENDIMAMS PRIIMTI. PAGAL GALIOJANČIUS ĮSTATYMUS PROGRAMA NESUTEIKIA JOKIŲ GARANTIJŲ VARTOTOJUI. JEI RAŠTU NENURODYTA KITAIP, PROGRAMOS AUTORINIŲ TEISIŲ TURĖTOJAS IR/AR KITOS ŠALYS PATEIKIA PROGRAMĄ \"KAIP YRA\" BE JOKIŲ GARANTIJŲ, TIEK AKIVAIZDŽIŲ, TIEK NUMANOMŲ, ĮSKAITANT, BET NEAPSIRIBOJANT GALIMYBĘ NAUDOTI PROGRAMĄ KOMERCINIAMS AR KITOKIEMS DALINIAMS TIKSLAMS. RIZIKĄ, KYLANČIĄ NAUDOJANT PROGRAMĄ PRISIIMA PATS VARTOTOJAS. JEI PROGRAMA VEIKIA NETINKAMAI, IŠLAIDOS, SUSIJUSIOS SU PROGRAMOS SERVISU, TAISYMU AR KOREGAVIMU, TENKA VARTOTOJUI.</string>
<string name="end_user_license_agreement_i_understand">SUPRATAU IR SUTINKU</string>
<string name="save">Išsaugoti</string>
<string name="reloadprofile">Atnaujinti profilį</string>
<string name="smscommunicator">SMS komunikatorius</string>
<string name="smscommunicator_allowednumbers">Leidžiami telefono numeriai</string>
@ -893,5 +894,6 @@
<string name="not_available_full">Negalimas</string>
<!-- Theme switcher dark and light mode-->
<!-- WEAR OS-->
<string name="login">Prisijungti</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -159,6 +159,7 @@
<string name="end_user_license_agreement">Umowa licencyjna użytkownika końcowego</string>
<string name="end_user_license_agreement_text">NIE MOŻE BY WYKORZYSTYWANY DO PODEJMOWANIA DECYZJI MEDYCZNYCH. NIE MA ŻADNEJ GWARANCJI NA PROGRAM, W ZAKRESIE DOZWOLONYM PRZEZ OBOWIĄZUJĄCE PRAWO. Z WYJĄTKIEM PRZYPADKÓW, GDY W INNY SPOSÓB PISMO OŚWIADCZENIA PRAW AUTORSKICH I / LUB INNYCH STRON, PRZEDSTAWIAĆ PROGRAM \"W STANIE TAKIM, W JAKIM SIĘ ZNAJDUJE\" BEZ JAKIEJKOLWIEK GWARANCJI, WYRAŹNEJ LUB DOMNIEMANEJ, W TYM MIĘDZY INNYMI DOMNIEMANYCH GWARANCJI PRZYDATNOŚCI HANDLOWEJ I PRZYDATNOŚCI DO OKREŚLONEGO CELU. CAŁKOWITE RYZYKO ZWIĄZANE Z JAKOŚCIĄ I WYNIKIEM PROGRAMU JEST PO PAŃSTWA STRONIE. W PRZYPADKU USZKODZENIA PROGRAMU UŻYTKOWNIK PONOSI KOSZT CAŁEGO NIEZBĘDNEGO SERWISU, NAPRAWY LUB POPRAWEK. W PRZYPADKU NIEPOROZUMIEŃ ZASTOSOWANIE PRAWNE MA UMOWA W ANGIELSKIEJ WERSJI JĘZYKOWEJ!!!</string>
<string name="end_user_license_agreement_i_understand">ROZUMIEM I WYRAŻAM ZGODĘ</string>
<string name="save">ZACHOWAJ</string>
<string name="reloadprofile">Załaduj profil ponownie</string>
<string name="smscommunicator">Komunikator SMS</string>
<string name="smscommunicator_allowednumbers">Dozwolone numery telefonów</string>
@ -893,5 +894,10 @@
<string name="not_available_full">Niedostępne</string>
<!-- Theme switcher dark and light mode-->
<!-- WEAR OS-->
<string name="remove_selected_items">Usuń wybrane pozycje</string>
<string name="confirm_remove_multiple_items">Czy na pewno chcesz usunąć %1$d pozycji</string>
<string name="count_selected">Wybrany %1$d</string>
<string name="sort_label">Sortuj</string>
<string name="login">Zaloguj się</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -159,6 +159,7 @@
<string name="end_user_license_agreement">Condições de Utilização</string>
<string name="end_user_license_agreement_text">NÃO DEVE SER USADO PARA FAZER DECISÕES MÉDICAS. NÃO HÁ NENHUMA GARANTIA PARA O PROGRAMA, NA EXTENSÃO PERMITIDA PELA LEGISLAÇÃO APLICÁVEL. EXCEPTO QUANDO DE OUTRA FORMA, POR ESCRITO, OS TITULARES DOS DIREITOS DE AUTOR E / OU OUTRAS PARTES FORNECEM O PROGRAMA “TAL COMO ESTÁ”, SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO, ÀS GARANTIAS IMPLÍCITAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA. TODO O RISCO QUANTO À QUALIDADE E DESEMPENHO DO PROGRAMA É CONSIGO. CASO O PROGRAMA SEJA DEFEITUOSO, ASSUME O CUSTO DE TODOS OS SERVIÇOS, REPAROS OU CORREÇÕES NECESSÁRIOS.</string>
<string name="end_user_license_agreement_i_understand">EU ENTENDO E CONCORDO</string>
<string name="save">Guardar</string>
<string name="reloadprofile">Recarregar perfil</string>
<string name="smscommunicator">Comunicador SMS</string>
<string name="smscommunicator_allowednumbers">Número de telefones permitidos</string>
@ -894,5 +895,6 @@
<string name="not_available_full">Indisponível</string>
<!-- Theme switcher dark and light mode-->
<!-- WEAR OS-->
<string name="login">Login</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -159,6 +159,7 @@
<string name="end_user_license_agreement">Licență utilizator final</string>
<string name="end_user_license_agreement_text">NU FOLOSIȚI PENTRU LUAREA DE DECIZII MEDICALE. NU EXISTĂ RĂSPUNDERE LEGALĂ SAU GARANȚIE PENTRU ACEST PROGRAM, ÎN LIMITA APLICABILĂ A LEGII. CU EXCEPTIA CAZURILOR SPECIAL MENȚIONATE, AUTORUL ȘI/SAU ALTE PERSOANE IMPLICATE PUN LA DISPOZIȚIE ACEST PROGRAM FĂRĂ NICIO GARANȚIE, IMPLICITĂ SAU EXPLICITĂ, INCLUZÂND, DAR FĂRĂ A SE LIMITA LA, GARANȚIILE LEGATE DE VĂNZAREA SAU POTRIVIREA PENTRU UN ANUME SCOP. ÎNTREGUL RISC LEGAT DE CALITATEA ȘI PERFORMANȚA ACESTUI PROGRAM CAD ÎN RESPONSABILITATEA DUMNEAVOASTRĂ. DACĂ PROGRAMUL SE DOVEDEȘTE A FI DEFECT, DUMNEAVOASTRĂ VĂ ASUMAȚI ÎNTREAGA RĂSPUNDERE, PRECUM ȘI TOATE COSTURILE LEGATE DE SERVICE, REPARAȚII SAU CORECȚII.</string>
<string name="end_user_license_agreement_i_understand">ÎNȚELEG ȘI SUNT DE ACORD</string>
<string name="save">Salvează</string>
<string name="reloadprofile">Reîncarcă profilul</string>
<string name="smscommunicator">Comunicator SMS</string>
<string name="smscommunicator_allowednumbers">Numere de telefon permise</string>
@ -894,5 +895,8 @@
<string name="not_available_full">Nu este disponibil</string>
<!-- Theme switcher dark and light mode-->
<!-- WEAR OS-->
<string name="confirm_remove_multiple_items">Sigur vrei să elimini %1$d element(e)</string>
<string name="sort_label">Sortează</string>
<string name="login">Autentificare</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -161,6 +161,7 @@ Eversense-appen.</string>
<string name="end_user_license_agreement">Licensavtal för slutanvändare</string>
<string name="end_user_license_agreement_text">FÅR INTE ANVÄNDAS FÖR ATT FATTA MEDICINSKA BESLUT. DET FINNS INGEN GARANTI FÖR PROGRAMMET I DEN UTSTRÄCKNING SOM TILLÅTS AV GÄLLANDE LAG. FÖRUTOM NÄR ANNAT ANGES SKRIFTLIGEN LEVERERAS APPLIKATIONEN SOM DEN ÄR HELT UTAN GARANTIER I NÅGON SOM HELST FORM, VARKEN UTTRYCKTA ELLER UNDERFÖRSTÅDDA, INKLUSIVE MEN INTE BEGRÄNSAT TILL SÄLJBARHET OCH LÄMPLIGHET FÖR ETT VISST ÄNDAMÅL. HELA RISKEN VAD GÄLLER KVALITET OCH PRESTANDA AV PROGRAMMET ÅLIGGER ANVÄNDAREN. OM PROGRAMMET VISAR SIG VARA DEFEKT ANTAR ANVÄNDAREN DEN FULLA FÖR KOSTNADEN FÖR ALL NÖDVÄNDIG SERVICE, REPARATION ELLER KORRIGERING.</string>
<string name="end_user_license_agreement_i_understand">JAG FÖRSTÅR OCH GODKÄNNER</string>
<string name="save">Spara</string>
<string name="reloadprofile">Ladda om profil</string>
<string name="smscommunicator">SMS-tjänst</string>
<string name="smscommunicator_allowednumbers">Godkända telefonnummer</string>
@ -962,5 +963,6 @@ Eversense-appen.</string>
<string name="wear_unknown_action_string">Okänt kommando:</string>
<string name="overview_editquickwizard_percentage">Procent</string>
<string name="app_default">Appens standardinställning</string>
<string name="login">Logga in</string>
<!-- Aidex Cgms -->
</resources>

View file

@ -475,6 +475,7 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d
<string name="localalertsettings_title">Yerel uyarılar</string>
<string name="enable_missed_bg_readings_alert">KŞ bilgisi alınmadığında uyar</string>
<string name="enable_pump_unreachable_alert">Pompa ulaşılamıyorsa uyar</string>
<string name="pump_unreachable_threshold">Pompa ulaşılamaz eşiği [dk]</string>
<string name="enable_carbs_req_alert">Karbonhidrat gerekliyse uyar</string>
<string name="urgent_alarm">Acil önemli Alarm</string>
<string name="info">BİLGİ</string>

View file

@ -36,11 +36,12 @@
android:key="@string/key_autotune_circadian_ic_isf"
android:summary="@string/autotune_circadian_ic_isf_summary"
android:title="@string/autotune_circadian_ic_isf_title" />
<!-- Hide autotune_additional_log option
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_autotune_additional_log"
android:summary="@string/autotune_additional_log_summary"
android:title="@string/autotune_additional_log_title" />
-->
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View file

@ -31,7 +31,6 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.source.GlimpPlugin
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Profiler
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl
import info.nightscout.shared.sharedPreferences.SP
import org.junit.Assert

View file

@ -17,7 +17,7 @@ import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.source.GlimpPlugin
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.shared.sharedPreferences.SP
import org.junit.Assert
import org.junit.Before

View file

@ -1,16 +1,52 @@
package info.nightscout.androidaps.plugins.constraints.versionChecker
import org.joda.time.DateTime
import org.joda.time.LocalDate
import org.junit.Assert
import org.junit.Assert.*
import org.json.JSONArray
import org.json.JSONObject
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
class AllowedVersionsTest {
fun generateSupportedVersions(): String =
JSONArray()
// Android API versions
.put(JSONObject().apply {
put("minAndroid", 1) // 1.0
put("maxAndroid", 23) // 6.0.1
})
.put(JSONObject().apply {
put("minAndroid", 24) // 7.0
put("maxAndroid", 25) // 7.1.2
put("supported", "2.6.2")
})
.put(JSONObject().apply {
put("minAndroid", 26) // 8.0
put("maxAndroid", 27) // 8.1
put("supported", "2.8.2")
})
.put(JSONObject().apply {
put("minAndroid", 28) // 9.0
put("maxAndroid", 99)
put("supported", "2.8.2")
})
// Version time limitation
.put(JSONObject().apply {
put("endDate", "2021-11-07")
put("version", "2.9.0-beta1")
})
.put(JSONObject().apply {
put("endDate", "2021-11-07")
put("version", "3.0-beta1")
})
.toString()
@Test
fun generateSupportedVersionsTest() {
val definition = AllowedVersions().generateSupportedVersions()
val definition = generateSupportedVersions()
assertNull(AllowedVersions().findByApi(definition, 0))
assertFalse(AllowedVersions().findByApi(definition, 1)?.has("supported") ?: true)
assertFalse(AllowedVersions().findByApi(definition, 23)?.has("supported") ?: true)
@ -24,9 +60,10 @@ class AllowedVersionsTest {
@Test
fun findByVersionTest() {
//val definition = AllowedVersions().generateSupportedVersions()
val definition = "[{\"minAndroid\":1,\"maxAndroid\":23},{\"minAndroid\":24,\"maxAndroid\":25,\"supported\":\"2.6.2\"},{\"minAndroid\":26,\"maxAndroid\":27,\"supported\":\"2.8.2\"},{\"minAndroid\":28,\"maxAndroid\":99,\"supported\":\"2.8.2\"},{\"endDate\":\"2021-11-07\",\"version\":\"2.9.0-beta1\"},{\"endDate\":\"2021-11-02\",\"version\":\"3.0-beta1\"},{\"endDate\":\"2021-11-04\",\"version\":\"3.0-beta2\"},{\"endDate\":\"2021-11-10\",\"version\":\"3.0-beta3\"},{\"endDate\":\"2021-11-14\",\"version\":\"3.0-beta4\"}\n" +
" ,{\"endDate\":\"2021-11-16\",\"version\":\"3.0-beta5\"}\n" +
"]"
val definition =
"[{\"minAndroid\":1,\"maxAndroid\":23},{\"minAndroid\":24,\"maxAndroid\":25,\"supported\":\"2.6.2\"},{\"minAndroid\":26,\"maxAndroid\":27,\"supported\":\"2.8.2\"},{\"minAndroid\":28,\"maxAndroid\":99,\"supported\":\"2.8.2\"},{\"endDate\":\"2021-11-07\",\"version\":\"2.9.0-beta1\"},{\"endDate\":\"2021-11-02\",\"version\":\"3.0-beta1\"},{\"endDate\":\"2021-11-04\",\"version\":\"3.0-beta2\"},{\"endDate\":\"2021-11-10\",\"version\":\"3.0-beta3\"},{\"endDate\":\"2021-11-14\",\"version\":\"3.0-beta4\"}\n" +
" ,{\"endDate\":\"2021-11-16\",\"version\":\"3.0-beta5\"}\n" +
"]"
assertNull(AllowedVersions().findByVersion(definition, "2.6.0"))
assertTrue(AllowedVersions().findByVersion(definition, "2.9.0-beta1")?.has("endDate") ?: false)
assertEquals("2021-11-07", AllowedVersions().findByVersion(definition, "2.9.0-beta1")?.getString("endDate"))
@ -34,7 +71,7 @@ class AllowedVersionsTest {
@Test
fun endDateToMilliseconds() {
val definition = AllowedVersions().generateSupportedVersions()
val definition = generateSupportedVersions()
val endDate = AllowedVersions().endDateToMilliseconds(AllowedVersions().findByVersion(definition, "2.9.0-beta1")?.getString("endDate") ?: "1000/01/01")
val dateTime = LocalDate(endDate)
assertEquals(2021, dateTime.year)

View file

@ -5,7 +5,7 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import org.junit.Assert

View file

@ -25,7 +25,7 @@ import info.nightscout.androidaps.queue.commands.*
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.BuildHelper
import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers

View file

@ -8,6 +8,9 @@ apply from: "${project.rootDir}/core/android_dependencies.gradle"
apply from: "${project.rootDir}/core/android_module_dependencies.gradle"
apply from: "${project.rootDir}/core/test_dependencies.gradle"
apply from: "${project.rootDir}/core/jacoco_global.gradle"
android {
namespace 'info.nightscout.androidaps.automation'
}
dependencies {

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.nightscout.androidaps.automation">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />

View file

@ -28,7 +28,6 @@ class ActionRunAutotune(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var sp: SP
@Inject lateinit var uel: UserEntryLogger
var defaultValue = 0
private var inputProfileName = InputProfileName(rh, activePlugin, "", true)

View file

@ -113,4 +113,5 @@
<string name="automation_event">Automatisierungs-Ereignis</string>
<string name="reorder_label">Umsortieren</string>
<string name="user_action">Benutzeraktion</string>
<string name="confirm_remove_multiple_items">Sind Sie sicher, dass Sie diese(s) %1$d Element(e) löschen möchten?</string>
</resources>

View file

@ -120,4 +120,7 @@
<string name="confirm_remove_multiple_items">Вы уверены, что хотите удалить %1$d элемент</string>
<string name="sort_label">Сортировать</string>
<string name="system_automation">Автоматизация системы</string>
<string name="run_automations">Запустить автоматизацию</string>
<string name="add_automation">Добавить правило</string>
<string name="remove_sort">Удаление/сортировка</string>
</resources>

View file

@ -2,7 +2,7 @@
buildscript {
ext {
kotlin_version = '1.6.21'
kotlin_version = '1.7.0'
core_version = '1.8.0'
rxjava_version = '3.1.5'
rxandroid_version = '3.0.0'
@ -17,7 +17,7 @@ buildscript {
gson_version = '2.9.0'
nav_version = '2.4.2'
appcompat_version = '1.4.2'
material_version = '1.6.0'
material_version = '1.6.1'
constraintlayout_version = '2.1.4'
preferencektx_version = '1.2.0'
commonslang3_version = '3.12.0'
@ -40,7 +40,7 @@ buildscript {
wearable_version = '2.9.0'
play_services_wearable_version = '17.1.0'
play_services_location_version = '19.0.1'
play_services_location_version = '20.0.0'
}
repositories {
google()
@ -66,7 +66,7 @@ plugins {
id "io.gitlab.arturbosch.detekt" version "1.20.0"
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
id 'org.barfuin.gradle.jacocolog' version '2.0.0'
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
}
allprojects {

View file

@ -8,6 +8,9 @@ apply from: "${project.rootDir}/core/android_dependencies.gradle"
apply from: "${project.rootDir}/core/android_module_dependencies.gradle"
apply from: "${project.rootDir}/core/test_dependencies.gradle"
apply from: "${project.rootDir}/core/jacoco_global.gradle"
android {
namespace 'info.nightscout.androidaps.combo'
}
dependencies {
implementation project(':core')

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.nightscout.androidaps.combo">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:supportsRtl="true">

View file

@ -15,3 +15,7 @@ dependencies {
implementation project(':shared')
implementation project(':database')
}
android {
namespace 'info.nightscout.androidaps.core'
}

View file

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.nightscout.androidaps.core">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@ -9,14 +8,17 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application
android:supportsRtl="true">
<activity android:name="info.nightscout.androidaps.activities.TDDStatsActivity" />
<application android:supportsRtl="true">
<activity
android:name="info.nightscout.androidaps.activities.TDDStatsActivity"
android:exported="false" />
<activity
android:name="info.nightscout.androidaps.activities.BolusProgressHelperActivity"
android:exported="false"
android:theme="@style/Theme.MaterialComponents.Translucent" />
<activity
android:name="info.nightscout.androidaps.activities.ErrorHelperActivity"
android:exported="false"
android:theme="@style/Theme.MaterialComponents.Translucent" />
</application>

View file

@ -74,11 +74,11 @@ class ErrorDialog : DaggerDialogFragment() {
}
binding.mute.setOnClickListener {
uel.log(Action.ERROR_DIALOG_MUTE, Sources.Unknown)
stopAlarm()
stopAlarm("Mute")
}
binding.mute5min.setOnClickListener {
uel.log(Action.ERROR_DIALOG_MUTE_5MIN, Sources.Unknown)
stopAlarm()
stopAlarm("Mute 5 min")
handler.postDelayed(this::startAlarm, T.mins(5).msecs())
}
startAlarm()
@ -110,14 +110,14 @@ class ErrorDialog : DaggerDialogFragment() {
super.dismissAllowingStateLoss()
helperActivity?.finish()
handler.removeCallbacksAndMessages(null)
stopAlarm()
stopAlarm("Dismiss")
}
private fun startAlarm() {
if (sound != 0)
alarmSoundServiceHelper.startAlarm(ctx, sound)
alarmSoundServiceHelper.startAlarm(ctx, sound, "$title:$status")
}
private fun stopAlarm() =
alarmSoundServiceHelper.stopService(ctx)
private fun stopAlarm(reason: String) =
alarmSoundServiceHelper.stopService(ctx, reason)
}

View file

@ -2,22 +2,23 @@ package info.nightscout.androidaps.extensions
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONObject
fun BolusCalculatorResult.toJson(isAdd: Boolean, dateUtil: DateUtil): JSONObject =
fun BolusCalculatorResult.toJson(isAdd: Boolean, dateUtil: DateUtil, profileFunction: ProfileFunction): JSONObject =
JSONObject()
.put("eventType", TherapyEvent.Type.BOLUS_WIZARD.text)
.put("created_at", dateUtil.toISOString(timestamp))
.put("isValid", isValid)
.put("bolusCalculatorResult", Gson().toJson(this))
.put("date", timestamp)
.put("glucose", glucoseValue)
.put("units", Constants.MGDL)
.put("glucose", Profile.fromMgdlToUnits(glucoseValue, profileFunction.getUnits()))
.put("units", profileFunction.getUnits().asText)
.put("notes", note)
.also { if (isAdd && interfaceIDs.nightscoutId != null) it.put("_id", interfaceIDs.nightscoutId) }

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.utils.buildHelper
package info.nightscout.androidaps.interfaces
interface BuildHelper {

View file

@ -2,10 +2,9 @@ package info.nightscout.androidaps.interfaces
import android.text.Spanned
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.queue.commands.CustomCommand
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.queue.commands.CustomCommand
interface CommandQueue {

View file

@ -2,9 +2,7 @@ package info.nightscout.androidaps.interfaces
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile
import io.reactivex.rxjava3.core.Single
interface ImportExportPrefs {

View file

@ -8,7 +8,6 @@ import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal
import info.nightscout.androidaps.utils.DecimalFormatter.to1Decimal
import info.nightscout.androidaps.utils.HardLimits
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.interfaces.ResourceHelper
import org.joda.time.DateTime
import org.json.JSONObject
@ -62,6 +61,7 @@ interface Profile {
* ISF value according to "now"" in MGDL
*/
fun getIsfMgdl(): Double
/**
* ISF value according to timestamp in MGDL
*/

View file

@ -4,43 +4,9 @@ import org.joda.time.LocalDate
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.lang.Exception
class AllowedVersions {
fun generateSupportedVersions(): String =
JSONArray()
// Android API versions
.put(JSONObject().apply {
put("minAndroid", 1) // 1.0
put("maxAndroid", 23) // 6.0.1
})
.put(JSONObject().apply {
put("minAndroid", 24) // 7.0
put("maxAndroid", 25) // 7.1.2
put("supported", "2.6.2")
})
.put(JSONObject().apply {
put("minAndroid", 26) // 8.0
put("maxAndroid", 27) // 8.1
put("supported", "2.8.2")
})
.put(JSONObject().apply {
put("minAndroid", 28) // 9.0
put("maxAndroid", 99)
put("supported", "2.8.2")
})
// Version time limitation
.put(JSONObject().apply {
put("endDate", "2021-11-07")
put("version", "2.9.0-beta1")
})
.put(JSONObject().apply {
put("endDate", "2021-11-07")
put("version", "3.0-beta1")
})
.toString()
fun findByApi(definition: String?, api: Int): JSONObject? {
if (definition == null) return null
try {

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
class Scale(var shift: Double = 0.0, var multiplier: Double = 0.0) {
class Scale(var shift: Double = 0.0, var multiplier: Double = 1.0) {
fun transform(original: Double): Double {
return original * multiplier + shift

View file

@ -8,7 +8,7 @@ open class Notification {
var id = 0
var date: Long = 0
var text: String? = null
var text: String = ""
var level = 0
var validTo: Long = 0
@RawRes var soundId: Int? = null

View file

@ -11,7 +11,8 @@ import kotlin.math.min
@Suppress("unused")
enum class PumpType {
GENERIC_AAPS(description = "Generic AAPS",
GENERIC_AAPS(
description = "Generic AAPS",
manufacturer = ManufacturerType.AndroidAPS,
model = "VirtualPump",
bolusSize = 0.1,
@ -23,9 +24,11 @@ enum class PumpType {
baseBasalMinValue = 0.01,
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
pumpCapability = PumpCapability.VirtualPumpCapabilities
),
CELLNOVO(description = "Cellnovo",
CELLNOVO(
description = "Cellnovo",
manufacturer = ManufacturerType.Cellnovo,
model = "Cellnovo",
bolusSize = 0.05,
@ -37,9 +40,11 @@ enum class PumpType {
baseBasalMinValue = 0.05,
baseBasalStep = 0.05,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
pumpCapability = PumpCapability.VirtualPumpCapabilities
),
ACCU_CHEK_COMBO(description = "Accu-Chek Combo",
ACCU_CHEK_COMBO(
description = "Accu-Chek Combo",
manufacturer = ManufacturerType.Roche,
model = "Combo",
bolusSize = 0.1,
@ -53,8 +58,10 @@ enum class PumpType {
baseBasalSpecialSteps = DoseStepSize.ComboBasal,
pumpCapability = PumpCapability.ComboCapabilities,
source = Sources.Combo,
supportBatteryLevel = false),
ACCU_CHEK_SPIRIT(description = "Accu-Chek Spirit",
supportBatteryLevel = false
),
ACCU_CHEK_SPIRIT(
description = "Accu-Chek Spirit",
manufacturer = ManufacturerType.Roche,
model = "Spirit",
bolusSize = 0.1,
@ -66,8 +73,10 @@ enum class PumpType {
baseBasalMinValue = 0.01,
baseBasalStep = 0.1,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
ACCU_CHEK_INSIGHT_VIRTUAL(description = "Accu-Chek Insight",
pumpCapability = PumpCapability.VirtualPumpCapabilities
),
ACCU_CHEK_INSIGHT_VIRTUAL(
description = "Accu-Chek Insight",
manufacturer = ManufacturerType.Roche,
model = "Insight",
bolusSize = 0.05,
@ -79,8 +88,10 @@ enum class PumpType {
baseBasalMinValue = 0.02,
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.InsightCapabilities),
ACCU_CHEK_INSIGHT(description = "Accu-Chek Insight",
pumpCapability = PumpCapability.InsightCapabilities
),
ACCU_CHEK_INSIGHT(
description = "Accu-Chek Insight",
manufacturer = ManufacturerType.Roche,
model = "Insight",
bolusSize = 0.01,
@ -94,8 +105,10 @@ enum class PumpType {
baseBasalStep = 0.01,
baseBasalSpecialSteps = DoseStepSize.InsightBasal,
pumpCapability = PumpCapability.InsightCapabilities,
source = Sources.Insight),
ACCU_CHEK_SOLO(description = "Accu-Chek Solo",
source = Sources.Insight
),
ACCU_CHEK_SOLO(
description = "Accu-Chek Solo",
manufacturer = ManufacturerType.Roche,
model = "Solo",
bolusSize = 0.01,
@ -108,9 +121,11 @@ enum class PumpType {
baseBasalMaxValue = null,
baseBasalStep = 0.01,
baseBasalSpecialSteps = DoseStepSize.InsightBolus,
pumpCapability = PumpCapability.InsightCapabilities),
pumpCapability = PumpCapability.InsightCapabilities
),
ANIMAS_VIBE(description = "Animas Vibe",
ANIMAS_VIBE(
description = "Animas Vibe",
manufacturer = ManufacturerType.Animas,
model = "Vibe",
bolusSize = 0.05,
@ -123,9 +138,11 @@ enum class PumpType {
baseBasalMaxValue = 5.0,
baseBasalStep = 0.0,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
pumpCapability = PumpCapability.VirtualPumpCapabilities
),
ANIMAS_PING(description = "Animas Ping", model = "Ping", parent = ANIMAS_VIBE),
DANA_R(description = "DanaR",
DANA_R(
description = "DanaR",
manufacturer = ManufacturerType.Sooil,
model = "DanaR",
bolusSize = 0.05,
@ -138,8 +155,10 @@ enum class PumpType {
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.DanaCapabilities,
source = Sources.DanaR),
DANA_R_KOREAN(description = "DanaR Korean",
source = Sources.DanaR
),
DANA_R_KOREAN(
description = "DanaR Korean",
manufacturer = ManufacturerType.Sooil,
model = "DanaRKorean",
bolusSize = 0.05,
@ -152,8 +171,10 @@ enum class PumpType {
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.DanaCapabilities,
source = Sources.DanaRC),
DANA_RS(description = "DanaRS",
source = Sources.DanaRC
),
DANA_RS(
description = "DanaRS",
manufacturer = ManufacturerType.Sooil,
model = "DanaRS",
bolusSize = 0.05,
@ -166,11 +187,13 @@ enum class PumpType {
baseBasalStep = 0.01,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.DanaWithHistoryCapabilities,
source = Sources.DanaRS),
source = Sources.DanaRS
),
DANA_RS_KOREAN(description = "DanaRSKorean", model = "DanaRSKorean", parent = DANA_RS),
DANA_I(description = "DanaI", model = "DanaI", parent = DANA_RS, source = Sources.DanaI),
DANA_RV2(description = "DanaRv2", model = "DanaRv2", parent = DANA_RS, source = Sources.DanaRv2),
OMNIPOD_EROS(description = "Omnipod Eros",
OMNIPOD_EROS(
description = "Omnipod Eros",
manufacturer = ManufacturerType.Insulet,
model = "Eros",
bolusSize = 0.05,
@ -188,8 +211,10 @@ enum class PumpType {
isPatchPump = true,
useHardwareLink = true,
supportBatteryLevel = false,
source = Sources.OmnipodEros),
OMNIPOD_DASH(description = "Omnipod Dash",
source = Sources.OmnipodEros
),
OMNIPOD_DASH(
description = "Omnipod Dash",
manufacturer = ManufacturerType.Insulet,
model = "Dash",
bolusSize = 0.05,
@ -205,8 +230,10 @@ enum class PumpType {
isPatchPump = true,
pumpCapability = PumpCapability.OmnipodCapabilities,
hasCustomUnreachableAlertCheck = false,
supportBatteryLevel = false),
MEDTRONIC_512_712(description = "Medtronic 512/712",
supportBatteryLevel = false
),
MEDTRONIC_512_712(
description = "Medtronic 512/712",
manufacturer = ManufacturerType.Medtronic,
model = "512/712",
bolusSize = 0.1,
@ -219,14 +246,20 @@ enum class PumpType {
baseBasalStep = 0.05,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.MedtronicCapabilities,
source = Sources.Medtronic),
MEDTRONIC_515_715(description = "Medtronic 515/715",
source = Sources.Medtronic
),
MEDTRONIC_515_715(
description = "Medtronic 515/715",
model = "515/715",
parent = MEDTRONIC_512_712),
MEDTRONIC_522_722(description = "Medtronic 522/722",
parent = MEDTRONIC_512_712
),
MEDTRONIC_522_722(
description = "Medtronic 522/722",
model = "522/722",
parent = MEDTRONIC_512_712),
MEDTRONIC_523_723_REVEL(description = "Medtronic 523/723 (Revel)",
parent = MEDTRONIC_512_712
),
MEDTRONIC_523_723_REVEL(
description = "Medtronic 523/723 (Revel)",
manufacturer = ManufacturerType.Medtronic,
model = "523/723 (Revel)",
bolusSize = 0.05,
@ -239,9 +272,11 @@ enum class PumpType {
baseBasalStep = 0.025,
baseBasalSpecialSteps = DoseStepSize.MedtronicVeoBasal,
pumpCapability = PumpCapability.MedtronicCapabilities,
source = Sources.Medtronic),
source = Sources.Medtronic
),
MEDTRONIC_554_754_VEO(description = "Medtronic 554/754 (Veo)", model = "554/754 (Veo)", parent = MEDTRONIC_523_723_REVEL),
MEDTRONIC_640G(description = "Medtronic 640G",
MEDTRONIC_640G(
description = "Medtronic 640G",
manufacturer = ManufacturerType.Medtronic,
model = "640G",
bolusSize = 0.025,
@ -253,9 +288,11 @@ enum class PumpType {
baseBasalMinValue = 0.025,
baseBasalStep = 0.025,
baseBasalSpecialSteps = DoseStepSize.MedtronicVeoBasal,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
pumpCapability = PumpCapability.VirtualPumpCapabilities
),
TANDEM_T_SLIM(description = "Tandem t:slim",
TANDEM_T_SLIM(
description = "Tandem t:slim",
manufacturer = ManufacturerType.Tandem,
model = "t:slim",
bolusSize = 0.01,
@ -267,12 +304,14 @@ enum class PumpType {
baseBasalMinValue = 0.1,
baseBasalStep = 0.001,
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.VirtualPumpCapabilities),
pumpCapability = PumpCapability.VirtualPumpCapabilities
),
TANDEM_T_FLEX(description = "Tandem t:flex", model = "t:flex", parent = TANDEM_T_SLIM),
TANDEM_T_SLIM_G4(description = "Tandem t:slim G4", model = "t:slim G4", parent = TANDEM_T_SLIM),
TANDEM_T_SLIM_X2(description = "Tandem t:slim X2", model = "t:slim X2", parent = TANDEM_T_SLIM),
YPSOPUMP(description = "YpsoPump",
YPSOPUMP(
description = "YpsoPump",
manufacturer = ManufacturerType.Ypsomed,
model = "Ypsopump",
bolusSize = 0.1,
@ -285,26 +324,39 @@ enum class PumpType {
baseBasalMaxValue = 40.0,
baseBasalStep = 0.01,
baseBasalSpecialSteps = DoseStepSize.YpsopumpBasal,
pumpCapability = PumpCapability.YpsomedCapabilities),
MDI(description = "MDI",
pumpCapability = PumpCapability.YpsomedCapabilities
),
MDI(
description = "MDI",
manufacturer = ManufacturerType.AndroidAPS,
bolusSize = 0.5,
model = "MDI",
tbrSettings = DoseSettings(1.0, 15, 24 * 60, 0.0, 500.0),
extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1),
pumpCapability = PumpCapability.MDI),
pumpCapability = PumpCapability.MDI
),
// Not real pump. Used for User as a source
USER(description = "USER",
USER(
description = "USER",
manufacturer = ManufacturerType.AndroidAPS,
model = "USER",
tbrSettings = DoseSettings(1.0, 15, 24 * 60, 0.0, 500.0),
extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1),
pumpCapability = PumpCapability.MDI,
source = Sources.MDI),
source = Sources.MDI
),
// Not real, cached value
CACHE(
description = "CACHE",
model = "CACHE",
parent = USER
),
//Diaconn Pump
DIACONN_G8(description = "Diaconn G8",
DIACONN_G8(
description = "Diaconn G8",
manufacturer = ManufacturerType.G2e,
model = "DiaconnG8",
bolusSize = 0.01,
@ -319,7 +371,8 @@ enum class PumpType {
baseBasalSpecialSteps = null,
pumpCapability = PumpCapability.DiaconnCapabilities,
source = Sources.DiaconnG8,
useHardwareLink = true);
useHardwareLink = true
);
val description: String
var manufacturer: ManufacturerType? = null
@ -407,6 +460,7 @@ enum class PumpType {
InterfaceIDs.PumpType.MDI -> MDI
InterfaceIDs.PumpType.USER -> USER
InterfaceIDs.PumpType.DIACONN_G8 -> DIACONN_G8
InterfaceIDs.PumpType.CACHE -> TODO()
}
}
@ -418,25 +472,27 @@ enum class PumpType {
parent.model = model
}
constructor(description: String,
manufacturer: ManufacturerType,
model: String,
bolusSize: Double = 0.0,
specialBolusSize: DoseStepSize? = null,
extendedBolusSettings: DoseSettings,
pumpTempBasalType: PumpTempBasalType? = null,
tbrSettings: DoseSettings,
specialBasalDurations: PumpCapability? = null,
baseBasalMinValue: Double = 0.01,
baseBasalMaxValue: Double? = null,
baseBasalStep: Double = 1.0,
baseBasalSpecialSteps: DoseStepSize? = null,
pumpCapability: PumpCapability,
hasCustomUnreachableAlertCheck: Boolean = false,
isPatchPump: Boolean = false,
supportBatteryLevel: Boolean = true,
useHardwareLink: Boolean = false,
source: Sources = Sources.VirtualPump) {
constructor(
description: String,
manufacturer: ManufacturerType,
model: String,
bolusSize: Double = 0.0,
specialBolusSize: DoseStepSize? = null,
extendedBolusSettings: DoseSettings,
pumpTempBasalType: PumpTempBasalType? = null,
tbrSettings: DoseSettings,
specialBasalDurations: PumpCapability? = null,
baseBasalMinValue: Double = 0.01,
baseBasalMaxValue: Double? = null,
baseBasalStep: Double = 1.0,
baseBasalSpecialSteps: DoseStepSize? = null,
pumpCapability: PumpCapability,
hasCustomUnreachableAlertCheck: Boolean = false,
isPatchPump: Boolean = false,
supportBatteryLevel: Boolean = true,
useHardwareLink: Boolean = false,
source: Sources = Sources.VirtualPump
) {
this.description = description
this.manufacturer = manufacturer
this.model = model
@ -463,12 +519,14 @@ enum class PumpType {
val eb = extendedBolusSettings ?: return "INVALID"
val tbr = tbrSettings ?: return "INVALID"
val extendedNote = if (hasExtendedBasals) rh.gs(R.string.def_extended_note) else ""
return String.format(i18nTemplate,
return String.format(
i18nTemplate,
getStep("" + bolusSize, specialBolusSize),
eb.step, eb.durationStep, eb.maxDuration / 60,
getStep(baseBasalRange(), baseBasalSpecialSteps),
tbr.minDose.toString() + unit + "-" + tbr.maxDose + unit, tbr.step.toString() + unit,
tbr.durationStep, tbr.maxDuration / 60, extendedNote)
tbr.durationStep, tbr.maxDuration / 60, extendedNote
)
}
private fun baseBasalRange(): String =
@ -494,42 +552,45 @@ enum class PumpType {
fun determineCorrectBasalSize(basalAmount: Double): Double {
val tSettings = tbrSettings ?: throw IllegalStateException()
return Round.roundTo(min(basalAmount, tSettings.maxDose), baseBasalSpecialSteps?.getStepSizeForAmount(basalAmount)
?: baseBasalStep)
return Round.roundTo(
min(basalAmount, tSettings.maxDose), baseBasalSpecialSteps?.getStepSizeForAmount(basalAmount)
?: baseBasalStep
)
}
fun toDbPumpType(): InterfaceIDs.PumpType =
when (this) {
GENERIC_AAPS -> InterfaceIDs.PumpType.GENERIC_AAPS
CELLNOVO -> InterfaceIDs.PumpType.CELLNOVO
ACCU_CHEK_COMBO -> InterfaceIDs.PumpType.ACCU_CHEK_COMBO
ACCU_CHEK_SPIRIT -> InterfaceIDs.PumpType.ACCU_CHEK_SPIRIT
GENERIC_AAPS -> InterfaceIDs.PumpType.GENERIC_AAPS
CELLNOVO -> InterfaceIDs.PumpType.CELLNOVO
ACCU_CHEK_COMBO -> InterfaceIDs.PumpType.ACCU_CHEK_COMBO
ACCU_CHEK_SPIRIT -> InterfaceIDs.PumpType.ACCU_CHEK_SPIRIT
ACCU_CHEK_INSIGHT_VIRTUAL -> InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT
ACCU_CHEK_INSIGHT -> InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT_BLUETOOTH
ACCU_CHEK_SOLO -> InterfaceIDs.PumpType.ACCU_CHEK_SOLO
ANIMAS_VIBE -> InterfaceIDs.PumpType.ANIMAS_VIBE
ANIMAS_PING -> InterfaceIDs.PumpType.ANIMAS_PING
DANA_R -> InterfaceIDs.PumpType.DANA_R
DANA_R_KOREAN -> InterfaceIDs.PumpType.DANA_R_KOREAN
DANA_RS -> InterfaceIDs.PumpType.DANA_RS
DANA_RS_KOREAN -> InterfaceIDs.PumpType.DANA_RS_KOREAN
DANA_RV2 -> InterfaceIDs.PumpType.DANA_RV2
DANA_I -> InterfaceIDs.PumpType.DANA_I
OMNIPOD_EROS -> InterfaceIDs.PumpType.OMNIPOD_EROS
OMNIPOD_DASH -> InterfaceIDs.PumpType.OMNIPOD_DASH
MEDTRONIC_512_712 -> InterfaceIDs.PumpType.MEDTRONIC_512_517
MEDTRONIC_515_715 -> InterfaceIDs.PumpType.MEDTRONIC_515_715
MEDTRONIC_522_722 -> InterfaceIDs.PumpType.MEDTRONIC_522_722
MEDTRONIC_523_723_REVEL -> InterfaceIDs.PumpType.MEDTRONIC_523_723_REVEL
MEDTRONIC_554_754_VEO -> InterfaceIDs.PumpType.MEDTRONIC_554_754_VEO
MEDTRONIC_640G -> InterfaceIDs.PumpType.MEDTRONIC_640G
TANDEM_T_SLIM -> InterfaceIDs.PumpType.TANDEM_T_SLIM
TANDEM_T_SLIM_G4 -> InterfaceIDs.PumpType.TANDEM_T_SLIM_G4
TANDEM_T_FLEX -> InterfaceIDs.PumpType.TANDEM_T_FLEX
TANDEM_T_SLIM_X2 -> InterfaceIDs.PumpType.TANDEM_T_SLIM_X2
YPSOPUMP -> InterfaceIDs.PumpType.YPSOPUMP
MDI -> InterfaceIDs.PumpType.MDI
USER -> InterfaceIDs.PumpType.USER
DIACONN_G8 -> InterfaceIDs.PumpType.DIACONN_G8
ANIMAS_VIBE -> InterfaceIDs.PumpType.ANIMAS_VIBE
ANIMAS_PING -> InterfaceIDs.PumpType.ANIMAS_PING
DANA_R -> InterfaceIDs.PumpType.DANA_R
DANA_R_KOREAN -> InterfaceIDs.PumpType.DANA_R_KOREAN
DANA_RS -> InterfaceIDs.PumpType.DANA_RS
DANA_RS_KOREAN -> InterfaceIDs.PumpType.DANA_RS_KOREAN
DANA_RV2 -> InterfaceIDs.PumpType.DANA_RV2
DANA_I -> InterfaceIDs.PumpType.DANA_I
OMNIPOD_EROS -> InterfaceIDs.PumpType.OMNIPOD_EROS
OMNIPOD_DASH -> InterfaceIDs.PumpType.OMNIPOD_DASH
MEDTRONIC_512_712 -> InterfaceIDs.PumpType.MEDTRONIC_512_517
MEDTRONIC_515_715 -> InterfaceIDs.PumpType.MEDTRONIC_515_715
MEDTRONIC_522_722 -> InterfaceIDs.PumpType.MEDTRONIC_522_722
MEDTRONIC_523_723_REVEL -> InterfaceIDs.PumpType.MEDTRONIC_523_723_REVEL
MEDTRONIC_554_754_VEO -> InterfaceIDs.PumpType.MEDTRONIC_554_754_VEO
MEDTRONIC_640G -> InterfaceIDs.PumpType.MEDTRONIC_640G
TANDEM_T_SLIM -> InterfaceIDs.PumpType.TANDEM_T_SLIM
TANDEM_T_SLIM_G4 -> InterfaceIDs.PumpType.TANDEM_T_SLIM_G4
TANDEM_T_FLEX -> InterfaceIDs.PumpType.TANDEM_T_FLEX
TANDEM_T_SLIM_X2 -> InterfaceIDs.PumpType.TANDEM_T_SLIM_X2
YPSOPUMP -> InterfaceIDs.PumpType.YPSOPUMP
MDI -> InterfaceIDs.PumpType.MDI
USER -> InterfaceIDs.PumpType.USER
DIACONN_G8 -> InterfaceIDs.PumpType.DIACONN_G8
CACHE -> InterfaceIDs.PumpType.CACHE
}
}

View file

@ -28,8 +28,8 @@ class AlarmSoundServiceHelper @Inject constructor(
private val notificationHolder: NotificationHolder
) {
fun startAlarm(context: Context, sound: Int) {
aapsLogger.debug(LTag.CORE, "Starting alarm")
fun startAlarm(context: Context, sound: Int, reason: String) {
aapsLogger.debug(LTag.CORE, "Starting alarm from $reason")
val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
// The binder of the service that returns the instance that is created.
@ -62,8 +62,8 @@ class AlarmSoundServiceHelper @Inject constructor(
}
}
fun stopService(context: Context) {
aapsLogger.debug(LTag.CORE, "Stopping alarm")
fun stopService(context: Context, reason: String) {
aapsLogger.debug(LTag.CORE, "Stopping alarm from $reason")
val alarm = Intent(context, AlarmSoundService::class.java)
context.stopService(alarm)
}

View file

@ -2,7 +2,9 @@
<resources>
<!-- Keys-->
<!-- General-->
<string name="save">Stoor</string>
<string name="pump_basebasalrate">%1$.2f U/h</string>
<string name="active"><![CDATA[<Active>]]></string>
<string name="yes">Ja</string>
<string name="no">Nee</string>
<string name="loopdisabled">LOOP UIT AKSIE GESTEL DEUR BEPERKINGS</string>
@ -60,5 +62,6 @@
<!-- HardLimits -->
<string name="valuelimitedto">%1$.2f beperk tot %2$.2f</string>
<!-- Command Queue + readStatus reasons -->
<string name="basal">Basale</string>
<!-- Autotune -->
</resources>

View file

@ -4,6 +4,7 @@
<!-- General-->
<string name="refresh">Обнови</string>
<string name="error">Грешка</string>
<string name="save">Съхрани</string>
<string name="not_set_short">Не е зададен</string>
<string name="failedupdatebasalprofile">Неуспешно обновяване на базалния профил</string>
<string name="profile_set_ok">Профила на помпата е обновен</string>
@ -41,6 +42,7 @@
<string name="carbs">въглехидрати</string>
<string name="invalidprofile">Грешен профил !!!</string>
<string name="noprofileset">НЕ Е АКТИВИРАН ПРОФИЛ</string>
<string name="active"><![CDATA[<Активно>]]></string>
<string name="date">Дата</string>
<string name="units_label">Единици</string>
<string name="dia_label">DIA (Време на действие на инсулина):</string>
@ -285,6 +287,7 @@
<string name="valuelimitedto">%1$.2f ограничен до %2$.2f</string>
<!-- Command Queue + readStatus reasons -->
<string name="sms" comment="26 characters max for translation">SMS</string>
<string name="basal">Базал</string>
<!-- Autotune -->
<plurals name="days">
<item quantity="one">%1$d дeн</item>

View file

@ -2,6 +2,8 @@
<resources>
<!-- Keys-->
<!-- General-->
<string name="save">Desar</string>
<string name="active"><![CDATA[<Actiu>]]></string>
<!-- Constraints-->
<!-- Dialogs-->
<!-- BlePreCheck-->
@ -66,5 +68,6 @@
<string name="valuelimitedto">%1$.2f limitat a %2$.2f</string>
<string name="valueoutofrange">»%1$s« supera els límits</string>
<!-- Command Queue + readStatus reasons -->
<string name="basal">Basal</string>
<!-- Autotune -->
</resources>

View file

@ -464,8 +464,8 @@
<string name="autotune_last_run">Poslední spuštění :</string>
<string name="autotune_warning">Varování :</string>
<string name="autotune_select_profile">Vyberte profil pro ladění</string>
<string name="autotune_ic_warning">Autotune funguje pouze s jedinou hodnotou IC, váš profil má %1$d hodnot. Průměrná hodnota je %2$.2fg/U</string>
<string name="autotune_isf_warning">Autotune funguje pouze s jedinou hodnotou ISF, váš profil má %1$d hodnot. Průměrná hodnota je %2$.1f%3$s/U</string>
<string name="autotune_ic_warning">Vybraný profil má %1$d hodnot IC. Autotune bude používat %2$.2f g/U</string>
<string name="autotune_isf_warning">Vybraný profil má %1$d hodnot ISF. Autotune bude používat %2$.1f %3$s/U</string>
<string name="autotune_error">Chyba vstupních dat, zkuste autotune spustit znovu nebo snížit počet dní</string>
<string name="autotune_warning_during_run">Autotune spuštěno, prosím buďte trpěliví</string>
<string name="autotune_warning_after_run">Před použitím výsledky pečlivě zkontrolujte!</string>

View file

@ -461,8 +461,6 @@
<string name="autotune_last_run">Sidst kørt :</string>
<string name="autotune_warning">Advarsel :</string>
<string name="autotune_select_profile">Vælg profil, der skal justeres</string>
<string name="autotune_ic_warning">Autotune fungerer med kun én IC-værdi, din profil har %1$d værdier. Gennemsnitsværdi er %2$.2fg/E</string>
<string name="autotune_isf_warning">Autotune virker med kun én ISF-værdi, din profil har %1$d værdier. Gennemsnitlig værdi er %2$.1f%3$s/E</string>
<string name="autotune_warning_during_run">Automatisk beregning startet, vær venligst tålmodig</string>
<string name="autotune_warning_after_run">Kontrollér resultaterne omhyggeligt, før du bruger dem!</string>
<string name="autotune_partial_result">Delvis resultat dag %1$d / %2$d justeret</string>

View file

@ -42,6 +42,7 @@
<string name="carbs">Kohlenhydrate</string>
<string name="invalidprofile">Ungültiges oder defektes Profil!</string>
<string name="noprofileset">KEIN PROFIL GESETZT</string>
<string name="active"><![CDATA[<Aktiv>]]></string>
<string name="date">Datum</string>
<string name="units_label">Einheiten</string>
<string name="dia_label">DIA</string>
@ -428,6 +429,9 @@
<string name="insight_refresh_button" comment="26 characters max for translation">Insight Refresh Button</string>
<string name="a11y_min_button_description">abnehmend %1$s mit %2$s</string>
<string name="a11y_plus_button_description">zunehmend %1$s mit %2$s</string>
<string name="basal">Basal</string>
<string name="count_selected">%1$d ausgewählt</string>
<string name="sort_label">Sortieren</string>
<!-- Autotune -->
<plurals name="days">
<item quantity="one">%1$d Tag</item>

View file

@ -2,7 +2,9 @@
<resources>
<!-- Keys-->
<!-- General-->
<string name="save">Αποθήκευση</string>
<string name="pump_basebasalrate">%1$.2f U/h</string>
<string name="active"><![CDATA[<Ενεργή>]]></string>
<string name="yes">Ναι</string>
<string name="no">Όχι</string>
<string name="loopdisabled">ΤΟ ΚΥΚΛΩΜΑ ΑΠΕΝΕΡΓΟΠΟΙΗΘΗΚΕ ΑΠΟ ΠΕΡΙΟΡΙΣΜΟΥΣ</string>
@ -60,5 +62,6 @@
<!-- HardLimits -->
<string name="valuelimitedto">Το %1$.2f περιορίζεται σε %2$.2f</string>
<!-- Command Queue + readStatus reasons -->
<string name="basal">Βασικός Ρυθμός</string>
<!-- Autotune -->
</resources>

View file

@ -464,8 +464,6 @@
<string name="autotune_last_run">Última ejecución :</string>
<string name="autotune_warning">Advertencia :</string>
<string name="autotune_select_profile">Selecciona el perfil para a ajustar</string>
<string name="autotune_ic_warning">Autotune sólo funciona con un valor de IC. Tu perfil tiene %1$d valores. El valor promedio es %2$.2fg/U</string>
<string name="autotune_isf_warning">Autotune sólo funciona con un valor de ISF. Tu perfil tiene %1$d valores. El valor promedio es %2$.1f%3$s/U</string>
<string name="autotune_error">Error en los datos de entrada, intenta ejecutar de nuevo autotune o reducir el número de días</string>
<string name="autotune_warning_during_run">Cálculo de autototune iniciado, por favor ten paciencia</string>
<string name="autotune_warning_after_run">¡Comprueba los resultados cuidadosamente antes de usarlos!</string>

View file

@ -446,7 +446,7 @@
<string name="autotune_description">Aide pour ajuster le profil (SI, rapport G/I et débits de basal)</string>
<string name="autotune_shortname">AT</string>
<string name="autotune_settings">Paramètres Autotune</string>
<string name="autotune_auto_title">Changement de profil avec l\'Automatisation</string>
<string name="autotune_auto_title">Changr le profil avec l\'automatisation</string>
<string name="autotune_auto_summary">Si activé, Autotune mettra à jour automatiquement à jour le profil sélectionné et activera le profil calculé effectué à partir d\'une règle d\'automatisation.</string>
<string name="autotune_categorize_uam_as_basal_title">Catégoriser UAM en tant que Basal</string>
<string name="autotune_categorize_uam_as_basal_summary">Activer uniquement si vous avez correctement saisi tous les glucides consommés, avec cette option, des hausses soudaines vues par Autotune seront utilisées pour modifier les débits de basal.</string>
@ -464,8 +464,8 @@
<string name="autotune_last_run">Dernier run :</string>
<string name="autotune_warning">Avertissement :</string>
<string name="autotune_select_profile">Sélectionnez le profil à optimiser</string>
<string name="autotune_ic_warning">Autotune ne fonctionne qu\'avec une seule valeur G/I, votre profil a %1$d valeurs. La valeur moyenne est de %2$.2f g/U</string>
<string name="autotune_isf_warning">Autotune ne calcule qu\'une seule valeur de SI, votre profil a %1$d valeurs. La valeur moyenne est de %2$.1f %3$s/U</string>
<string name="autotune_ic_warning">Le profil sélectionné %1$d valeurs de G/I. Autotune va utiliser la moyenne %2$.2f g/U</string>
<string name="autotune_isf_warning">Le profil sélectionné a %1$d valeurs de SI. Autotune va utiliser la moyenne %2$.1f %3$s/U</string>
<string name="autotune_error">Erreur dans les données d\'entrée, essayez de relancer le calcul ou réduire le nombre de jours</string>
<string name="autotune_warning_during_run">Le calcul Autotune a commencé, veuillez patienter</string>
<string name="autotune_warning_after_run">Vérifiez attentivement les résultats avant de les utiliser!</string>

View file

@ -3,6 +3,7 @@
<!-- Keys-->
<!-- General-->
<string name="error">Earráid</string>
<string name="save">Sábháil</string>
<string name="waitingforpump">Ag fanacht do caidéil</string>
<string name="connectingfor">Ag nascadh le %1$d s</string>
<string name="bolusdelivering">Ag seachadadh %1$.2f A</string>
@ -114,5 +115,6 @@
<!-- User Entry -->
<!-- HardLimits -->
<!-- Command Queue + readStatus reasons -->
<string name="basal">Bunaidh</string>
<!-- Autotune -->
</resources>

View file

@ -2,8 +2,10 @@
<resources>
<!-- Keys-->
<!-- General-->
<string name="close">Zatvori</string>
<!-- Constraints-->
<!-- Dialogs-->
<string name="cancel">Otkaži</string>
<!-- BlePreCheck-->
<!-- Protection-->
<!-- Profile-->

View file

@ -26,5 +26,6 @@
<!-- User Entry -->
<!-- HardLimits -->
<!-- Command Queue + readStatus reasons -->
<string name="basal">Bázis</string>
<!-- Autotune -->
</resources>

View file

@ -464,8 +464,8 @@
<string name="autotune_last_run">הפעלה אחרונה :</string>
<string name="autotune_warning">אזהרה :</string>
<string name="autotune_select_profile">בחרו פרופיל לכוונון</string>
<string name="autotune_ic_warning">כוונון אוטומטי עובד עם ערך IC אחד בלבד, לפרופיל שלכם יש %1$d ערכים. הערך הממוצע הוא %2$.2f גר\'\\יח\'</string>
<string name="autotune_isf_warning">כוונון אוטומטי עובד עם ערך ISF אחד בלבד, לפרופיל שלכם יש %1$d ערכים. הערך הממוצע הוא %2$.1f %3$s\\יח\'</string>
<string name="autotune_ic_warning">בפרופיל הנבחר יש %1$d ערכי יחס פחמימות. הכיוונון האוטומטי ישתמש ב-%2$.2f גר\'\\יח\'</string>
<string name="autotune_isf_warning">בפרופיל הנבחר יש %1$d ערכי יחס תיקון. הכיוונון האוטומטי ישתמש ב-%2$.1f %3$s\\יח\'</string>
<string name="autotune_error">שגיאה בנתוני הקלט, נסו להפעיל בשנית או שנסו לצמצם את מספר הימים</string>
<string name="autotune_warning_during_run">חישוב הכוונון האוטומטי התחיל, אנא התאזרו בסבלנות</string>
<string name="autotune_warning_after_run">בדקו היטב את התוצאות לפני השימוש בהן!</string>

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