Merge branch 'upstream-dev' into avereha/fix-disconnect

This commit is contained in:
Andrei Vereha 2022-06-17 11:55:13 +02:00
commit 8d23df61bd
340 changed files with 7168 additions and 5580 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

@ -1085,7 +1085,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
@ -1106,7 +1106,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);
}
@ -1273,22 +1273,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
@ -188,11 +188,33 @@ class MainApp : DaggerApplication() {
}
}
@Suppress("SpellCheckingInspection")
private fun doMigrations() {
// set values for different builds
if (!sp.contains(R.string.key_ns_alarms)) sp.putBoolean(R.string.key_ns_alarms, config.NSCLIENT)
if (!sp.contains(R.string.key_ns_announcements)) sp.putBoolean(R.string.key_ns_announcements, config.NSCLIENT)
if (!sp.contains(R.string.key_language)) sp.putString(R.string.key_language, "default")
// 3.1.0
if (sp.contains("ns_wifionly")) {
if (sp.getBoolean("ns_wifionly", false)) {
sp.putBoolean(R.string.key_ns_cellular, false)
sp.putBoolean(R.string.key_ns_wifi, true)
} else {
sp.putBoolean(R.string.key_ns_cellular, true)
sp.putBoolean(R.string.key_ns_wifi, false)
}
sp.remove("ns_wifionly")
}
if (sp.contains("ns_charginonly")) {
if (sp.getBoolean("ns_charginonly", false)) {
sp.putBoolean(R.string.key_ns_battery, false)
sp.putBoolean(R.string.key_ns_charging, true)
} else {
sp.putBoolean(R.string.key_ns_battery, true)
sp.putBoolean(R.string.key_ns_charging, true)
}
sp.remove("ns_charginonly")
}
}
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
@ -227,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
@ -99,7 +99,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
activePlugin,
defaultValueHelper,
profileFunction,
repository
repository,
fabricPrivacy
)
iobCobCalculator =
IobCobCalculatorPlugin(

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

@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.ceil
import kotlin.math.roundToInt
@Singleton
@ -181,7 +182,7 @@ class AutotuneIob @Inject constructor(
// even if profile rate is not the same
private fun toSplittedTimestampTB(tb: TemporaryBasal, tunedProfile: ATProfile) {
var splittedTimestamp = tb.timestamp
val cutInMilliSec = T.mins(30).msecs() //30 min to compare with oref0
val cutInMilliSec = T.mins(60).msecs() //30 min to compare with oref0, 60 min to improve accuracy
var splittedDuration = tb.duration
if (tb.isValid && tb.durationInMinutes > 0) {
val endTimestamp = splittedTimestamp + splittedDuration
@ -248,21 +249,20 @@ class AutotuneIob @Inject constructor(
fun convertToBoluses(eb: ExtendedBolus): MutableList<Bolus> {
val result: MutableList<Bolus> = ArrayList()
val tempBolusSize = 0.05
val tempBolusCount : Int = (eb.amount / tempBolusSize).roundToInt()
if(tempBolusCount > 0) {
val tempBolusSpacing = eb.duration / tempBolusCount
for (j in 0L until tempBolusCount) {
val calcDate = eb.timestamp + j * tempBolusSpacing
val bolusInterfaceIDs = InterfaceIDs().also { it.nightscoutId = eb.interfaceIDs.nightscoutId + "_eb_$j" }
val tempBolusPart = Bolus(
interfaceIDs_backing = bolusInterfaceIDs,
timestamp = calcDate,
amount = tempBolusSize,
type = Bolus.Type.NORMAL
)
result.add(tempBolusPart)
}
val aboutFiveMinIntervals = ceil(eb.duration / 5.0).toInt()
val spacing = eb.duration / aboutFiveMinIntervals.toDouble()
for (j in 0L until aboutFiveMinIntervals) {
// find middle of the interval
val calcDate = (eb.timestamp + j * spacing * 60 * 1000 + 0.5 * spacing * 60 * 1000).toLong()
val tempBolusSize: Double = eb.amount / aboutFiveMinIntervals
val bolusInterfaceIDs = InterfaceIDs().also { it.nightscoutId = eb.interfaceIDs.nightscoutId + "_eb_$j" }
val tempBolusPart = Bolus(
interfaceIDs_backing = bolusInterfaceIDs,
timestamp = calcDate,
amount = tempBolusSize,
type = Bolus.Type.NORMAL
)
result.add(tempBolusPart)
}
return result
}
@ -277,22 +277,20 @@ class AutotuneIob @Inject constructor(
} else {
tbr.rate / 100.0 * basalRate - tunedRate
}, 0.001)
val tempBolusSize = if (netBasalRate < 0 ) -0.05 else 0.05
val netBasalAmount: Double = Round.roundTo(netBasalRate * realDuration / 60.0, 0.01)
val tempBolusCount : Int = (netBasalAmount / tempBolusSize).roundToInt()
if(tempBolusCount > 0) {
val tempBolusSpacing = realDuration * 60 * 1000 / tempBolusCount
for (j in 0L until tempBolusCount) {
val calcDate = tbr.timestamp + j * tempBolusSpacing
val bolusInterfaceIDs = InterfaceIDs().also { it.nightscoutId = tbr.interfaceIDs.nightscoutId + "_tbr_$j" }
val tempBolusPart = Bolus(
interfaceIDs_backing = bolusInterfaceIDs,
timestamp = calcDate,
amount = tempBolusSize,
type = Bolus.Type.NORMAL
)
result.add(tempBolusPart)
}
val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt()
val tempBolusSpacing = realDuration / aboutFiveMinIntervals.toDouble()
for (j in 0L until aboutFiveMinIntervals) {
// find middle of the interval
val calcDate = (tbr.timestamp + j * tempBolusSpacing * 60 * 1000 + 0.5 * tempBolusSpacing * 60 * 1000).toLong()
val tempBolusSize = netBasalRate * tempBolusSpacing / 60.0
val bolusInterfaceIDs = InterfaceIDs().also { it.nightscoutId = tbr.interfaceIDs.nightscoutId + "_tbr_$j" }
val tempBolusPart = Bolus(
interfaceIDs_backing = bolusInterfaceIDs,
timestamp = calcDate,
amount = tempBolusSize,
type = Bolus.Type.NORMAL
)
result.add(tempBolusPart)
}
return result
}

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

@ -21,8 +21,7 @@ import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm
@ -34,12 +33,13 @@ 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.ResourceHelper
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
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.util.*
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import javax.inject.Singleton
@ -80,62 +80,49 @@ class NSClientPlugin @Inject constructor(
var nsClientService: NSClientService? = null
val isAllowed: Boolean
get() = nsClientReceiverDelegate.allowed
val blockingReason: String
get() = nsClientReceiverDelegate.blockingReason
override fun onStart() {
paused = sp.getBoolean(R.string.key_nsclientinternal_paused, false)
autoscroll = sp.getBoolean(R.string.key_nsclientinternal_autoscroll, true)
val intent = Intent(context, NSClientService::class.java)
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
context.bindService(Intent(context, NSClientService::class.java), mConnection, Context.BIND_AUTO_CREATE)
super.onStart()
nsClientReceiverDelegate.grabReceiversState()
disposable.add(
rxBus
.toObservable(EventNSClientStatus::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventNSClientStatus ->
status = event.getStatus(rh)
rxBus.send(EventNSClientUpdateGUI())
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventNetworkChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ if (nsClientService != null) context.unbindService(mConnection) }, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventNSClientNewLog::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventNSClientNewLog ->
addToLog(event)
aapsLogger.debug(LTag.NSCLIENT, event.action + " " + event.logText)
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventChargingState::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventNSClientResend::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
)
disposable += rxBus
.toObservable(EventNSClientStatus::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventNSClientStatus ->
status = event.getStatus(rh)
rxBus.send(EventNSClientUpdateGUI())
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNetworkChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ if (nsClientService != null) context.unbindService(mConnection) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNSClientNewLog::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventNSClientNewLog ->
addToLog(event)
aapsLogger.debug(LTag.NSCLIENT, event.action + " " + event.logText)
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventChargingState::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNSClientResend::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
}
override fun onStop() {

View file

@ -22,19 +22,26 @@ class NsClientReceiverDelegate @Inject constructor(
private var allowedChargingState = true
private var allowedNetworkState = true
var allowed = true
var blockingReason = ""
fun grabReceiversState() {
receiverStatusStore.updateNetworkStatus()
}
fun onStatusEvent(ev: EventPreferenceChange) {
if (ev.isChanged(rh, R.string.key_ns_wifionly) ||
ev.isChanged(rh, R.string.key_ns_wifi_ssids) ||
ev.isChanged(rh, R.string.key_ns_allowroaming)) {
receiverStatusStore.updateNetworkStatus()
onStatusEvent(receiverStatusStore.lastNetworkEvent)
} else if (ev.isChanged(rh, R.string.key_ns_chargingonly)) {
receiverStatusStore.broadcastChargingState()
when {
ev.isChanged(rh, R.string.key_ns_wifi) ||
ev.isChanged(rh, R.string.key_ns_cellular) ||
ev.isChanged(rh, R.string.key_ns_wifi_ssids) ||
ev.isChanged(rh, R.string.key_ns_allow_roaming) -> {
receiverStatusStore.updateNetworkStatus()
receiverStatusStore.lastNetworkEvent?.let { onStatusEvent(it) }
}
ev.isChanged(rh, R.string.key_ns_charging) ||
ev.isChanged(rh, R.string.key_ns_battery) -> {
receiverStatusStore.broadcastChargingState()
}
}
}
@ -42,14 +49,16 @@ class NsClientReceiverDelegate @Inject constructor(
val newChargingState = calculateStatus(ev)
if (newChargingState != allowedChargingState) {
allowedChargingState = newChargingState
blockingReason = rh.gs(R.string.blocked_by_charging)
processStateChange()
}
}
fun onStatusEvent(ev: EventNetworkChange?) {
fun onStatusEvent(ev: EventNetworkChange) {
val newNetworkState = calculateStatus(ev)
if (newNetworkState != allowedNetworkState) {
allowedNetworkState = newNetworkState
blockingReason = rh.gs(R.string.blocked_by_connectivity)
processStateChange()
}
}
@ -62,30 +71,13 @@ class NsClientReceiverDelegate @Inject constructor(
}
}
fun calculateStatus(ev: EventChargingState): Boolean {
val chargingOnly = sp.getBoolean(R.string.key_ns_chargingonly, false)
var newAllowedState = true
if (!ev.isCharging && chargingOnly) {
newAllowedState = false
}
return newAllowedState
}
fun calculateStatus(ev: EventChargingState): Boolean =
!ev.isCharging && sp.getBoolean(R.string.key_ns_battery, true) ||
ev.isCharging && sp.getBoolean(R.string.key_ns_charging, true)
fun calculateStatus(ev: EventNetworkChange?): Boolean {
val wifiOnly = sp.getBoolean(R.string.key_ns_wifionly, false)
val allowedSsidString = sp.getString(R.string.key_ns_wifi_ssids, "")
val allowedSSIDs: List<String> = if (allowedSsidString.isEmpty()) List(0) { "" } else allowedSsidString.split(";")
val allowRoaming = sp.getBoolean(R.string.key_ns_allowroaming, true)
var newAllowedState = true
if (ev?.wifiConnected == true) {
if (allowedSSIDs.isNotEmpty() && !allowedSSIDs.contains(ev.ssid)) {
newAllowedState = false
}
} else {
if (!allowRoaming && ev?.roaming == true || wifiOnly) {
newAllowedState = false
}
}
return newAllowedState
}
fun calculateStatus(ev: EventNetworkChange): Boolean =
ev.mobileConnected && sp.getBoolean(R.string.key_ns_cellular, true) && !ev.roaming ||
ev.mobileConnected && sp.getBoolean(R.string.key_ns_cellular, true) && ev.roaming && sp.getBoolean(R.string.key_ns_allow_roaming, true) ||
ev.wifiConnected && sp.getBoolean(R.string.key_ns_wifi, true) && sp.getString(R.string.key_ns_wifi_ssids, "").isEmpty() ||
ev.wifiConnected && sp.getBoolean(R.string.key_ns_wifi, true) && sp.getString(R.string.key_ns_wifi_ssids, "").split(";").contains(ev.ssid)
}

View file

@ -16,9 +16,14 @@ import info.nightscout.androidaps.events.EventConfigBuilderChange
import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.food.FoodPlugin.FoodWorker
import info.nightscout.androidaps.plugins.general.nsclient.*
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddAckWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientUpdateRemoveAckWorker
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck
@ -43,13 +48,13 @@ 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.ResourceHelper
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
import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.socket.client.IO
import io.socket.client.Socket
import io.socket.emitter.Emitter
@ -114,70 +119,56 @@ class NSClientService : DaggerService() {
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:NSClientService")
wakeLock?.acquire()
initialize()
disposable.add(
rxBus
.toObservable(EventConfigBuilderChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
if (nsEnabled != nsClientPlugin.isEnabled()) {
latestDateInReceivedData = 0
destroy()
initialize()
}
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventPreferenceChange ->
if (event.isChanged(rh, R.string.key_nsclientinternal_url) ||
event.isChanged(rh, R.string.key_nsclientinternal_api_secret) ||
event.isChanged(rh, R.string.key_nsclientinternal_paused)
) {
latestDateInReceivedData = 0
destroy()
initialize()
}
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
aapsLogger.debug(LTag.NSCLIENT, "EventAppExit received")
destroy()
stopSelf()
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventNSClientRestart::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
disposable += rxBus
.toObservable(EventConfigBuilderChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
if (nsEnabled != nsClientPlugin.isEnabled()) {
latestDateInReceivedData = 0
restart()
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(NSAuthAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processAuthAck(ack) }, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(NSUpdateAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processUpdateAck(ack) }, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(NSAddAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processAddAck(ack) }, fabricPrivacy::logException)
)
destroy()
initialize()
}
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventPreferenceChange ->
if (event.isChanged(rh, R.string.key_nsclientinternal_url) ||
event.isChanged(rh, R.string.key_nsclientinternal_api_secret) ||
event.isChanged(rh, R.string.key_nsclientinternal_paused)
) {
latestDateInReceivedData = 0
destroy()
initialize()
}
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
aapsLogger.debug(LTag.NSCLIENT, "EventAppExit received")
destroy()
stopSelf()
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNSClientRestart::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
latestDateInReceivedData = 0
restart()
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(NSAuthAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processAuthAck(ack) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(NSUpdateAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processUpdateAck(ack) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(NSAddAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processAddAck(ack) }, fabricPrivacy::logException)
}
override fun onDestroy() {
@ -234,13 +225,9 @@ class NSClientService : DaggerService() {
get() = this@NSClientService
}
override fun onBind(intent: Intent): IBinder {
return binder
}
override fun onBind(intent: Intent): IBinder = binder
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return START_STICKY
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int = START_STICKY
fun initialize() {
dataCounter = 0
@ -249,8 +236,8 @@ class NSClientService : DaggerService() {
if (nsAPISecret != "") nsApiHashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString()
rxBus.send(EventNSClientStatus("Initializing"))
if (!nsClientPlugin.isAllowed) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "not allowed"))
rxBus.send(EventNSClientStatus("Not allowed"))
rxBus.send(EventNSClientNewLog("NSCLIENT", nsClientPlugin.blockingReason))
rxBus.send(EventNSClientStatus(nsClientPlugin.blockingReason))
} else if (nsClientPlugin.paused) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "paused"))
rxBus.send(EventNSClientStatus("Paused"))

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.sharedPreferences.SP
import java.util.*
@ -44,7 +45,8 @@ class OverviewData @Inject constructor(
private val activePlugin: ActivePlugin,
private val defaultValueHelper: DefaultValueHelper,
private val profileFunction: ProfileFunction,
private val repository: AppRepository
private val repository: AppRepository,
private val fabricPrivacy: FabricPrivacy
) {
var rangeToDisplay = 6 // for graph
@ -205,8 +207,8 @@ class OverviewData @Inject constructor(
* IOB, COB
*/
fun bolusIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromBolus().round()
fun basalIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
fun bolusIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromBolus().round(fabricPrivacy)
fun basalIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round(fabricPrivacy)
fun cobInfo(iobCobCalculator: IobCobCalculator): CobInfo = iobCobCalculator.getCobInfo(true, "Overview COB")
val lastCarbsTime: Long
@ -249,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

@ -123,8 +123,8 @@ class StatusLinePlugin @Inject constructor(
status += activeTemp.toStringShort() + " "
}
//IOB
val bolusIob = iobCobCalculator.calculateIobFromBolus().round()
val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
val bolusIob = iobCobCalculator.calculateIobFromBolus().round(fabricPrivacy)
val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round(fabricPrivacy)
status += DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U"
if (sp.getBoolean(R.string.key_xdripstatus_detailediob, true)) {
status += ("("

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

@ -182,7 +182,7 @@ public class TimeListEdit {
numberPickers1[position].setTextWatcher(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
Double value1 = SafeParse.stringToDouble(numberPickers1[position].getText());
Double value1 = SafeParse.INSTANCE.stringToDouble(numberPickers1[position].getText());
Double value2 = value2(position);
if (data2 != null && value1 > value2) {
value2 = value1;
@ -209,7 +209,7 @@ public class TimeListEdit {
@Override
public void afterTextChanged(Editable s) {
Double value1 = value1(position);
Double value2 = SafeParse.stringToDouble(numberPickers2[position].getText());
Double value2 = SafeParse.INSTANCE.stringToDouble(numberPickers2[position].getText());
if (data2 != null && value2 < value1) {
value1 = value2;
numberPickers1[position].setValue(value1);

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>
@ -457,9 +458,7 @@
<string name="secondcarbsincrement">Tweede koolhidrate inkrement</string>
<string name="thirdcarbsincrement">Derde koolhidrate inkrement</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Gebruik slegs WiFi verbinding</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Slegs wanneer laai</string>
<string name="connectionsettings_title">Verbindinginstellings</string>
<string name="ns_wifi_allowedssids">Toegelate SSID\'s (kommapunt geskei)</string>
<string name="ns_allowroaming">Laat verbindings toe terwyl swerf</string>

View file

@ -591,9 +591,7 @@
<string name="secondcarbsincrement">Стойност на втория бърз бутон [гр]</string>
<string name="thirdcarbsincrement">Стойност на третия бърз бутон [гр]</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Използвай само WiFi</string>
<string name="ns_wifi_ssids">WiFi име</string>
<string name="ns_chargingonly">Само при зареждане на телефона</string>
<string name="connectionsettings_title">Настройки за свързване</string>
<string name="ns_wifi_allowedssids">Разрешени WiFi мрежи(разделени с запетая)</string>
<string name="ns_allowroaming">Позволи връзка в роуминг</string>
@ -881,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

@ -123,6 +123,7 @@
<string name="sensitivity_cannula">Výměna kanyly nebo změna profilu automaticky nastaví Autosense zpět na 100%.</string>
<string name="sensitivity_time">Některé pluginy mají konfigurovatelné časové rozmezí, které může nastavit uživatel.</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/CROWDIN/cs/Configuration/Config-Builder.html#detekce-citlivosti</string>
<string name="sensitivity_hint2">https://androidaps.readthedocs.io/cs/latest/Usage/Open-APS-features.html#autosens</string>
<string name="wrongcarbs_label">Chyby při zadávání sacharidů</string>
<string name="wrongcarbs_whattodo">Co byste měli udělat, pokud jste zadali chybně sacharidy?</string>
<string name="wrongcarbs_treatmentstab">Odstraňte nesprávný záznam v Ošetření a zadejte správnou novou hodnotu sacharidů.</string>

View file

@ -604,9 +604,11 @@
<string name="secondcarbsincrement">Druhý přídavek sacharidů</string>
<string name="thirdcarbsincrement">Třetí přídavek sacharidů</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Používat pouze WiFi</string>
<string name="ns_cellular">Použít mobilní připojení</string>
<string name="ns_wifi">Použít WiFi připojení</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Pouze při nabíjení</string>
<string name="ns_charging">Při nabíjení</string>
<string name="ns_battery">Na baterii</string>
<string name="connectionsettings_title">Nastavení připojení</string>
<string name="ns_wifi_allowedssids">Povolené SSID (oddělené středníkem)</string>
<string name="ns_allowroaming">Povolit připojení pro roamingu</string>
@ -1037,4 +1039,6 @@
<string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string>
<string name="description_source_aidex">Přijímat hodnoty glykémie ze senzoru GlucoRx Aidex.</string>
<string name="blocked_by_charging">Zablokováno možností nabíjení</string>
<string name="blocked_by_connectivity">Zablokováno možností připojení</string>
</resources>

View file

@ -603,9 +603,7 @@
<string name="secondcarbsincrement">Anden kulhydratstigning</string>
<string name="thirdcarbsincrement">Tredje kulhydratstigning</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Brug kun WiFi forbindelse</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Kun under opladning</string>
<string name="connectionsettings_title">Indstillinger for forbindelse</string>
<string name="ns_wifi_allowedssids">Tilladte SSID\'er (semikolon separeret)</string>
<string name="ns_allowroaming">Tillad forbindelse i roaming</string>

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>
@ -597,9 +598,7 @@
<string name="secondcarbsincrement">Zweite KH-Erhöhung</string>
<string name="thirdcarbsincrement">Dritte KH-Erhöhung</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Benutze nur WLAN Verbindung</string>
<string name="ns_wifi_ssids">WLAN SSID</string>
<string name="ns_chargingonly">Nur während des Ladens</string>
<string name="connectionsettings_title">Verbindungs-Einstellungen</string>
<string name="ns_wifi_allowedssids">Erlaubte SSIDs (durch Semikolon getrennt)</string>
<string name="ns_allowroaming">Erlaube Verbindung bei Roaming</string>
@ -941,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

@ -459,9 +459,7 @@
<string name="secondcarbsincrement">Δεύτερη αύξηση υδατανθράκων</string>
<string name="thirdcarbsincrement">Τρίτη αύξηση υδατανθράκων</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Χρησιμοποιήστε μόνο σύνδεση Wi-Fi</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Μόνο κατά τη φόρτιση</string>
<string name="connectionsettings_title">Ρυθμίσεις σύνδεσης</string>
<string name="ns_wifi_allowedssids">Επιτρέπονται SSID (διαχωρίζονται με ελληνικό ερωτηματικό)</string>
<string name="ns_allowroaming">Επιτρέψτε τη σύνδεση περιαγωγής</string>

View file

@ -604,9 +604,11 @@
<string name="secondcarbsincrement">Segundo incremento de carbohidratos</string>
<string name="thirdcarbsincrement">Tercer incremento de carbohidratos</string>
<string name="cgm">MCG</string>
<string name="ns_wifionly">Usar sólo con WiFi</string>
<string name="ns_cellular">Usar conexión móvil</string>
<string name="ns_wifi">Usar conexión WiFi</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Sólo si está cargando</string>
<string name="ns_charging">Durante la carga</string>
<string name="ns_battery">Con batería</string>
<string name="connectionsettings_title">Ajustes de conexión</string>
<string name="ns_wifi_allowedssids">SSID\'s permitidos (separados por punto y coma)</string>
<string name="ns_allowroaming">Permitir conexión en roaming</string>
@ -1037,4 +1039,6 @@
<string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string>
<string name="description_source_aidex">Recibir los valores de glucosa de GlucoRx Aidex CGMS</string>
<string name="blocked_by_charging">Bloqueado por opciones de carga</string>
<string name="blocked_by_connectivity">Bloqueado por opciones de conectividad</string>
</resources>

View file

@ -123,6 +123,7 @@
<string name="sensitivity_cannula">Le changement de canule réinitialisera le ratio Autosens à 100%.</string>
<string name="sensitivity_time">Certaines des options du plugin ont des plages de temps configurables qui peuvent être définies par l\'utilisateur.</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string>
<string name="sensitivity_hint2">https://androidaps.readthedocs.io/fr/latest/Usage/Open-APS-features.html?highlight=Autosens#autosens</string>
<string name="wrongcarbs_label">Entrées de glucides erronées</string>
<string name="wrongcarbs_whattodo">Que devez-vous faire si vous avez renseigné une valeur erronée de glucides ?</string>
<string name="wrongcarbs_treatmentstab">Supprimez l\'entrée incorrecte dans les Traitements et entrez la nouvelle valeur correcte de glucides.</string>

View file

@ -605,9 +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_wifionly">Utilisez uniquement connexion Wi-fi</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_chargingonly">Uniquement si en charge</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>
@ -682,9 +684,11 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
<string name="error_adding_treatment_message">Le traitement (insuline : %1$.2f, glucides : %2$d, à : %3$s) n\'a pas pu être ajouté aux traitements. Vérifiez et ajoutez SVP manuellement ce traitement.</string>
<string name="generated_ecarbs_note">eCarbs : %1$d g (%2$d h), retard : %3$d m</string>
<string name="openaps_noasdata">Pas de données d\'Autosens disponibles</string>
<string name="log_files">Fichiers log</string>
<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>
@ -774,6 +778,11 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
<string name="invalidpct">% saisi invalide</string>
<string name="average">Moyenne</string>
<string name="tir">Cible Gly</string>
<string name="day_tir">TIR Jour</string>
<string name="night_tir">TIR Nuit</string>
<string name="detailed_14_days">Détail de 14 jours</string>
<string name="std_deviation">SD: %1$s</string>
<string name="hba1c">HbA1c : </string>
<string name="activitymonitor">Moniteur d\'activité</string>
<string name="doyouwantresetstats">Voulez-vous réinitialiser les stats d\'activité ?</string>
<string name="statistics">Statistiques</string>
@ -999,6 +1008,10 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
<string name="count_selected">%1$d sélectionnée(s)</string>
<string name="sort_label">Trier</string>
<string name="dialog_canceled">Boîte de dialogue annulée</string>
<string name="veryLow" comment="below 3.1">Très bas</string>
<string name="low" comment="3.1-3.9">Bas</string>
<string name="high" comment="10.0-13.9">Haut</string>
<string name="veryHigh" comment="above 13.9">Très haut</string>
<string name="below" comment="below &quot;in range&quot;">En-dessous</string>
<string name="in_range">Dans la cible</string>
<string name="above" comment="above &quot;in range&quot;">Au-dessus</string>
@ -1008,6 +1021,11 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
<string name="configure">Configurer lopacité</string>
<string name="loop_status">État de la boucle</string>
<string name="graph_scale">Échelle du graph.</string>
<string name="profile1">Profil 1</string>
<string name="profile2">Profil2</string>
<string name="login">Connexion</string>
<string name="remove_all">Supprimer tout</string>
<string name="reset_start">Réinitialiser le démarrage</string>
<string name="a11y_otp_qr_code">Code QR pour configurer un mot de passe à usage unique</string>
<string name="a11y_open_settings">ouvrir les paramètres</string>
<string name="a11y_set_carb_timer">définir l\'alarme du minuteur de glucides</string>
@ -1021,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>
@ -159,7 +160,6 @@
<string name="next_button">Ar Aghaidh</string>
<string name="previous_button">Roimhe seo</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Úsáid WiFi nasc amháin</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="wear_general_settings">Socruithe Ginearálta</string>
<string name="poctech">Poctech</string>

View file

@ -603,9 +603,7 @@
<string name="secondcarbsincrement">Secondo incremento di CHO</string>
<string name="thirdcarbsincrement">Terzo incremento di CHO</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Usa solo connessione WiFi</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Solo se in carica</string>
<string name="connectionsettings_title">Impostazioni connessione</string>
<string name="ns_wifi_allowedssids">SSID ammessi (separati da punto e virgola)</string>
<string name="ns_allowroaming">Consenti connessione in roaming</string>

View file

@ -603,9 +603,7 @@
<string name="secondcarbsincrement">תוספת פחמימות שניה</string>
<string name="thirdcarbsincrement">תוספת פחמימות שלישית</string>
<string name="cgm">סנסור</string>
<string name="ns_wifionly">השתמש בחיבור WiFi בלבד</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">במצב טעינה בלבד</string>
<string name="connectionsettings_title">הגדרות חיבור</string>
<string name="ns_wifi_allowedssids">SSID מורשים (מופרדים בנקודה-פסיק)</string>
<string name="ns_allowroaming">אפשר חיבור בנדידה</string>
@ -678,6 +676,8 @@
<string name="error_adding_treatment_message">לא ניתן להוסיף טיפול (אינסולין: %1$.2f, פחמ\': %2$d, בשעה: %3$s) לטיפולים. נא לבדוק ולהוסיף רשומה באופן ידני כנדרש.</string>
<string name="generated_ecarbs_note">פחמימות ממושכות: %1$d גר\' (%2$d ש\'), עיכוב %3$d דק\'</string>
<string name="openaps_noasdata">אין נתוני Autosens זמינים</string>
<string name="log_files">קבצי יומן</string>
<string name="miscellaneous">שונות</string>
<string name="nav_logsettings">הגדרות יומן רישום</string>
<string name="resettodefaults">אפס לברירת המחדל</string>
<string name="nsmalfunction">תקלה ב-NSClient. שקלו להפעיל את Nightscout ו-NSClient מחדש.</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>
@ -586,9 +587,7 @@
<string name="secondcarbsincrement">2차 탄수화물 증분</string>
<string name="thirdcarbsincrement">3차 탄수화물 증분</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">와이파이 연결만 사용하기</string>
<string name="ns_wifi_ssids">와이파이 SSID</string>
<string name="ns_chargingonly">충전중일때만</string>
<string name="connectionsettings_title">연결 설정</string>
<string name="ns_wifi_allowedssids">허가된 SSIDs(세미콜론으로 구분)</string>
<string name="ns_allowroaming">로밍에서 연결 허용</string>
@ -851,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>
@ -595,9 +596,7 @@
<string name="secondcarbsincrement">Antras angliavandenių kiekio žingsnis</string>
<string name="thirdcarbsincrement">Trečias angliavandenių kiekio žingsnis</string>
<string name="cgm">NGJ</string>
<string name="ns_wifionly">Naudoti tik WiFi</string>
<string name="ns_wifi_ssids">WiFi pavadinimas</string>
<string name="ns_chargingonly">Tik įkraunant</string>
<string name="connectionsettings_title">Ryšio nustatymai</string>
<string name="ns_wifi_allowedssids">Leidžiami tinklai (atskirti kabliataškiais)</string>
<string name="ns_allowroaming">Leisti sujungimą tarptinkliniu ryšiu</string>
@ -895,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

@ -604,9 +604,7 @@
<string name="secondcarbsincrement">Tweede koolhydraten increment</string>
<string name="thirdcarbsincrement">Derde koolhydraten increment</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Gebuik enkel de WiFi verbinding</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Enkel tijdens opladen</string>
<string name="connectionsettings_title">Verbindings instellingen</string>
<string name="ns_wifi_allowedssids">Toegelaten SSIDs (gescheiden door puntkomma)</string>
<string name="ns_allowroaming">Sta verbinding tijdens roaming toe</string>

View file

@ -123,6 +123,7 @@
<string name="sensitivity_cannula">Hvis du logger bytte av kanyle vil Autosens verdien tilbakestilles til 100%.</string>
<string name="sensitivity_time">Noen plugins har konfigurerbare tidsintervall som kan settes av brukeren.</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string>
<string name="sensitivity_hint2">https://androidaps.readthedocs.io/en/latest/Usage/Open-APS-features.html?highlight=Autosens#autosens</string>
<string name="wrongcarbs_label">Feil i KH angivelse</string>
<string name="wrongcarbs_whattodo">Hva skal du gjøre hvis du har gjort en feilaktig registrering av karbohydrater?</string>
<string name="wrongcarbs_treatmentstab">Fjern den feilaktige registreringen i Behandlinger og legg inn riktig verdi for karbohydrater.</string>

View file

@ -604,9 +604,11 @@
<string name="secondcarbsincrement">Andre økning hurtigknapp for karbohydrater</string>
<string name="thirdcarbsincrement">Tredje økning hurtigknapp for karbohydrater</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Bare kun WiFi tilkoblinger</string>
<string name="ns_cellular">Bruk mobildata</string>
<string name="ns_wifi">Bruk Wi-Fi-tilkobling</string>
<string name="ns_wifi_ssids">WiFi nettverksnavn</string>
<string name="ns_chargingonly">Bare under lading</string>
<string name="ns_charging">Under lading</string>
<string name="ns_battery">På batteri</string>
<string name="connectionsettings_title">Tilkoblingsinnstillinger</string>
<string name="ns_wifi_allowedssids">Tillatte nettverksnavn SSID (separert med semikolon)</string>
<string name="ns_allowroaming">Tillat tilkobling i roaming</string>
@ -681,6 +683,8 @@
<string name="error_adding_treatment_message">En behandling (insulin: %1$.2f, karbohydrater: %2$d, tid: %3$s) kunne ikke legges til Behandlinger. Vennligst kontroller og manuelt legg til en registrering der det er aktuelt.</string>
<string name="generated_ecarbs_note">eKarbo: %1$d g (%2$d t), forsinkelse: %3$d m</string>
<string name="openaps_noasdata">Ingen data tilgjengelig for autosens</string>
<string name="log_files">Loggfiler</string>
<string name="miscellaneous">Annet</string>
<string name="nav_logsettings">Logginnstillinger</string>
<string name="resettodefaults">Gjenopprett standardinnstillinger</string>
<string name="nsmalfunction">NSClient feil. Vurder omstart av NS og NSClient.</string>
@ -773,6 +777,11 @@
<string name="invalidpct">Ugyldig % oppføring</string>
<string name="average">Gjennomsnitt</string>
<string name="tir">TIR</string>
<string name="day_tir">Dag TIR</string>
<string name="night_tir">Natt TIR</string>
<string name="detailed_14_days">Detaljert 14 dager</string>
<string name="std_deviation">SD: %1$s</string>
<string name="hba1c">HbA1c: </string>
<string name="activitymonitor">Overvåking av aktivitet</string>
<string name="doyouwantresetstats">Vil du tilbakestille aktivitets statistikk?</string>
<string name="statistics">Statistikk</string>
@ -999,6 +1008,10 @@
<string name="count_selected">%1$d valgt</string>
<string name="sort_label">Sorter</string>
<string name="dialog_canceled">Dialog avbrutt</string>
<string name="veryLow" comment="below 3.1">Veldig lavt</string>
<string name="low" comment="3.1-3.9">Lavt</string>
<string name="high" comment="10.0-13.9">Høyt</string>
<string name="veryHigh" comment="above 13.9">Veldig høyt</string>
<string name="below" comment="below &quot;in range&quot;">Under</string>
<string name="in_range">I målområdet</string>
<string name="above" comment="above &quot;in range&quot;">Over</string>
@ -1026,4 +1039,6 @@
<string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string>
<string name="description_source_aidex">Motta BS verdier fra GlucoRx Aidex CGM.</string>
<string name="blocked_by_charging">Blokkert på grunn av ladealternativer</string>
<string name="blocked_by_connectivity">Blokkert på grunn av tilkoblingsalternativer</string>
</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>
@ -595,9 +596,7 @@
<string name="secondcarbsincrement">Drugi stopień przyrostu węglow.</string>
<string name="thirdcarbsincrement">Trzeci stopień przyrostu węglow.</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Używaj tylko połączenia WiFi</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Tylko gdy się ładuje</string>
<string name="connectionsettings_title">Ustawienia połączenia</string>
<string name="ns_wifi_allowedssids">Dozwolone SSID (rozdzielone średnikiem)</string>
<string name="ns_allowroaming">Zezwalaj na połączenia w roamingu</string>
@ -895,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

@ -570,9 +570,7 @@
<string name="secondcarbsincrement">Segundo incremento hidratos</string>
<string name="thirdcarbsincrement">Terceiro incremento hidratos</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Utilize apenas uma conexão WiFi</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Apenas quando estiver a carregar</string>
<string name="connectionsettings_title">Definições de ligação</string>
<string name="ns_wifi_allowedssids">SSIDs permitidos (separada por ponto e vírgula)</string>
<string name="ns_allowroaming">Permitir ligação em roaming</string>

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>
@ -595,9 +596,7 @@
<string name="secondcarbsincrement">Segundo incremento hidratos</string>
<string name="thirdcarbsincrement">Terceiro incremento hidratos</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Utilize apenas uma conexão WiFi</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Apenas quando estiver a carregar</string>
<string name="connectionsettings_title">Definições de ligação</string>
<string name="ns_wifi_allowedssids">SSIDs permitidos (separada por ponto e vírgula)</string>
<string name="ns_allowroaming">Permitir ligação em roaming</string>
@ -896,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>
@ -595,9 +596,7 @@
<string name="secondcarbsincrement">Al doilea increment de carbohidrați</string>
<string name="thirdcarbsincrement">Al treilea increment de carbohidrați</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Folosește doar conexiune WiFi</string>
<string name="ns_wifi_ssids">SSID WiFi</string>
<string name="ns_chargingonly">Doar când se încarcă</string>
<string name="connectionsettings_title">Setări conexiune</string>
<string name="ns_wifi_allowedssids">SSIDuri permise (separare prin punct și virgulă)</string>
<string name="ns_allowroaming">Permite conexiuni în roaming</string>
@ -896,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

@ -123,6 +123,7 @@
<string name="sensitivity_cannula">Внесение записи о замене катетера вернет коэффициент Autosens к 100%.</string>
<string name="sensitivity_time">У некоторых опций модуля есть настраиваемые диапазоны времени, которые может задать пользователь.</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string>
<string name="sensitivity_hint2">https://androidaps.readthedocs.io/en/latest/Usage/Open-APS-features.html?highlight=Autosens#autosens</string>
<string name="wrongcarbs_label">Ошибки записи углеводов</string>
<string name="wrongcarbs_whattodo">Что нужно делать, если сделан неправильный ввод углеводов?</string>
<string name="wrongcarbs_treatmentstab">Удалить неверную запись в Журнале терапии и заново ввести правильное значение углеводов.</string>

View file

@ -440,6 +440,7 @@
<string name="enableuam_summary">Поиск незапланированного приема пищи</string>
<string name="insulin_oref_peak">Время пика действующего инс IOB</string>
<string name="insulin_peak_time">время пика (в мин.)</string>
<string name="insulin_peak">Пик</string>
<string name="free_peak_oref">Свободный от пиков Oref</string>
<string name="rapid_acting_oref">Быстро действующий Oref</string>
<string name="ultrarapid_oref">Сверхбыстрый Oref</string>
@ -603,9 +604,11 @@
<string name="secondcarbsincrement">Второй шаг увеличения углеводов</string>
<string name="thirdcarbsincrement">Третий шаг увеличения углеводов</string>
<string name="cgm">Мониторинг ГК</string>
<string name="ns_wifionly">Использовать только WiFi соединение</string>
<string name="ns_cellular">Использовать мобильное подключение</string>
<string name="ns_wifi">Использовать WiFi соединение</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Только при зарядке</string>
<string name="ns_charging">Во время зарядки</string>
<string name="ns_battery">От батареи</string>
<string name="connectionsettings_title">Параметры подключения</string>
<string name="ns_wifi_allowedssids">Разрешенные SSID (разделенные точкой с запятой)</string>
<string name="ns_allowroaming">Разрешить подключение в роуминге</string>
@ -680,6 +683,8 @@
<string name="error_adding_treatment_message">Назначение (инсулин: %1$.2f, углеводы: %2$d, в: %3$s) не было добавлено. Пожалуйста, проверьте и при необходимости добавьте запись вручную.</string>
<string name="generated_ecarbs_note">eCarbs: %1$d г. (%2$d h), задержка: %3$d m</string>
<string name="openaps_noasdata">Данные autosens недоступны</string>
<string name="log_files">Файлы журналов</string>
<string name="miscellaneous">Разное</string>
<string name="nav_logsettings">Настройки журнала</string>
<string name="resettodefaults">Восстановить значения по умолчанию</string>
<string name="nsmalfunction">Некорректная работа NSClient. Возможно следует перезапустить NS и NSClient.</string>
@ -772,6 +777,11 @@
<string name="invalidpct">Некорректный ввод %</string>
<string name="average">Средний</string>
<string name="tir">Время в целевом диапазоне TIR</string>
<string name="day_tir">Время в целевом диапазоне днем</string>
<string name="night_tir">Время в целевом диапазоне ночью</string>
<string name="detailed_14_days">Подробно 14 дней</string>
<string name="std_deviation">СтандОткл: %1$s</string>
<string name="hba1c">HbA1c: </string>
<string name="activitymonitor">Монитор активности</string>
<string name="doyouwantresetstats">Хотите сбросить статистику активности?</string>
<string name="statistics">Статистика</string>
@ -966,9 +976,11 @@
<string name="wizard_no_active_profile">Активный профиль не установлен!</string>
<string name="wizard_no_cob">Неизвестный COB! Отсутствуют данные ГК или приложения недавно перезапущено?</string>
<string name="wizard_carbs_constraint">Нарушено ограничение по углеводам!</string>
<string name="wizard_explain_calc">Кальк (IC:%1$.1f ISF: %2$.1f)</string>
<string name="wizard_explain_carbs">Углеводов: %1$.2fгУ</string>
<string name="wizard_explain_cob">Акт Инс COB: %1$.0fг %2$.2fед</string>
<string name="wizard_explain_bg">ГК: %1$.2f</string>
<string name="wizard_explain_iob">IOB: %1$.2fед</string>
<string name="wizard_explain_superbolus">Суперболюсный: %1$.2fед</string>
<string name="wizard_explain_trend">тренд 15\': %1$.2f</string>
<string name="wizard_explain_percent">Процент: %1$.2fU x %2$d%% = %3$.2f</string>
@ -995,6 +1007,10 @@
<string name="count_selected">%1$d выбрано</string>
<string name="sort_label">Сортировать</string>
<string name="dialog_canceled">Диалог отменен</string>
<string name="veryLow" comment="below 3.1">Очень низкий</string>
<string name="low" comment="3.1-3.9">Низкий</string>
<string name="high" comment="10.0-13.9">Высокий</string>
<string name="veryHigh" comment="above 13.9">Очень высокий</string>
<string name="below" comment="below &quot;in range&quot;">Ниже целевых</string>
<string name="in_range">В целевом диапазоне</string>
<string name="above" comment="above &quot;in range&quot;">Выше целевых</string>
@ -1002,5 +1018,26 @@
<string name="show_hide_records">Скрыть записи цикла</string>
<string name="widget_description">Виджет androidAPS</string>
<string name="configure">Настроить прозрачность</string>
<string name="loop_status">Статус цикла</string>
<string name="graph_scale">Масштаб графика</string>
<string name="profile1">Профиль 1</string>
<string name="profile2">Профиль 2</string>
<string name="login">Логин</string>
<string name="remove_all">Удалить всё</string>
<string name="reset_start">Перезапустить старт</string>
<string name="a11y_otp_qr_code">QR код для введения временного пароля</string>
<string name="a11y_open_settings">открыть настройки</string>
<string name="a11y_set_carb_timer">задать оповещение таймера углеводов</string>
<string name="device_all">Все</string>
<string name="device_phone">Телефон</string>
<string name="device_watch">Часы</string>
<string name="a11y_only_on_watch">только на часах</string>
<string name="a11y_only_on_phone">только на телефоне</string>
<string name="a11y_drag_and_drop_handle">якорь перетягивания</string>
<!-- Aidex Cgms -->
<string name="aidex">Aidex GlucoRx</string>
<string name="aidex_short">Aidex </string>
<string name="description_source_aidex">Получить значения ГК от GlucoRx Aidex</string>
<string name="blocked_by_charging">Заблокировано опциями зарядки</string>
<string name="blocked_by_connectivity">Заблокировано настройками подключения</string>
</resources>

View file

@ -604,9 +604,11 @@
<string name="secondcarbsincrement">Druhý prídavok sacharidov</string>
<string name="thirdcarbsincrement">Tretí prídavok sacharidov</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Používať iba WiFi</string>
<string name="ns_cellular">Použiť mobilné pripojenie</string>
<string name="ns_wifi">Použiť WiFi pripojenie</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Len pri nabíjaní</string>
<string name="ns_charging">Počas nabíjania</string>
<string name="ns_battery">Na batérii</string>
<string name="connectionsettings_title">Nastavenie pripojenia</string>
<string name="ns_wifi_allowedssids">Povolené SSID (oddelené bodkočiarkou)</string>
<string name="ns_allowroaming">Povoliť pripojenie pri roamingu</string>
@ -681,6 +683,8 @@
<string name="error_adding_treatment_message">Ošetrenie (inzulín: %1$.2f, sacharidy: %2$d, čas: %3$s) nie je možné pridať. Skontrolujte a podľa potreby manuálne pridajte záznam.</string>
<string name="generated_ecarbs_note">eCarbs: %1$d g (%2$d h), Oneskorenie: %3$d m</string>
<string name="openaps_noasdata">Nedostupné dáta o glykémiách</string>
<string name="log_files">Log súbory</string>
<string name="miscellaneous">Rôzne</string>
<string name="nav_logsettings">Nastavenie logovania</string>
<string name="resettodefaults">Obnoviť predvolené</string>
<string name="nsmalfunction">Chyba NSClienta. Zvážte reštart NS a NSClienta.</string>
@ -1035,4 +1039,6 @@
<string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string>
<string name="description_source_aidex">Prijímať hodnoty glykémie zo senzora GlucoRx Aidex.</string>
<string name="blocked_by_charging">Zablokované možnosti nabíjania</string>
<string name="blocked_by_connectivity">Zablokované možnosti pripojenia</string>
</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>
@ -600,9 +601,7 @@ Eversense-appen.</string>
<string name="secondcarbsincrement">Andra snabbknabben för kolhydrater</string>
<string name="thirdcarbsincrement">Tredje snabbknabben för kolhydrater</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Använd endast WiFi</string>
<string name="ns_wifi_ssids">WiFi nätverksnamn</string>
<string name="ns_chargingonly">Endast vid laddning</string>
<string name="connectionsettings_title">Anslutningsinställningar</string>
<string name="ns_wifi_allowedssids">Tillåtna nätverksnamn (separerade med semikolon)</string>
<string name="ns_allowroaming">Tillåt NS-data vid roaming</string>
@ -964,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

@ -123,6 +123,7 @@
<string name="sensitivity_cannula">Bir kanül değişikliğinin kaydedilmesi, Otoduyarlılık oranını %100\'e sıfırlayacaktır.</string>
<string name="sensitivity_time">Eklenti seçeneklerinden bazıları, kullanıcı tarafından ayarlanabilen yapılandırılabilir zaman aralıklarına sahiptir.</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string>
<string name="sensitivity_hint2">https://androidaps.readthedocs.io/tr/latest/Usage/Open-APS-features.html?highlight=Autosens#autosens</string>
<string name="wrongcarbs_label">Karbonhidrat Giriş Hataları</string>
<string name="wrongcarbs_whattodo">Yanlış bir karbonhidrat girişi yaptıysanız ne yapmalısınız?</string>
<string name="wrongcarbs_treatmentstab">Tedavilerdeki yanlış girişi siler ve doğru karbonhidrat değerini girerim.</string>

View file

@ -475,7 +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 [min]</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>
@ -605,9 +605,11 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d
<string name="secondcarbsincrement">İkinci karbonhidrat artışı</string>
<string name="thirdcarbsincrement">Üçüncü karbonhidrat artışı</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">Sadece WiFi bağlantı kullanın</string>
<string name="ns_cellular">Mobil veri kullan</string>
<string name="ns_wifi">Wi-Fi bağlantısı kullan</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Sadece şarj olurken</string>
<string name="ns_charging">Şarj olurken</string>
<string name="ns_battery">Pilde</string>
<string name="connectionsettings_title">Bağlantı Ayarları</string>
<string name="ns_wifi_allowedssids">İzin verilen SSID (noktalı virgülle ayrılmış)</string>
<string name="ns_allowroaming">Roaming bağlantıya izin ver</string>
@ -682,6 +684,8 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d
<string name="error_adding_treatment_message">Tedavilere (insülin: %1$.2f, karbonhidrat: %2$d, %3$s) şeklinde bir tedavi eklenemedi. Lütfen kontrol edin ve uygun şekilde elle bir kayıt ekleyin.</string>
<string name="generated_ecarbs_note">yKarb: %1$d g (%2$d sa), gecikme: %3$d dk</string>
<string name="openaps_noasdata">Otoduyarlılık verileri mevcut değil</string>
<string name="log_files">Günlük dosyaları</string>
<string name="miscellaneous">Diğer Ayarlar</string>
<string name="nav_logsettings">Günlük ayarları</string>
<string name="resettodefaults">Varsayılanlara sıfırla</string>
<string name="nsmalfunction">NSClient arızası. NS ve NSClient yeniden başlatmayı düşünün.</string>
@ -774,6 +778,11 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d
<string name="invalidpct">Geçersiz % giriş</string>
<string name="average">Ortalama</string>
<string name="tir">TIR</string>
<string name="day_tir">Gündüz TIR</string>
<string name="night_tir">Gece TIR</string>
<string name="detailed_14_days">Ayrıntılı 14 gün</string>
<string name="std_deviation">SD: %1$s</string>
<string name="hba1c">HbA1c: </string>
<string name="activitymonitor">Aktivite monitörü</string>
<string name="doyouwantresetstats">Etkinlik istatistiklerini sıfırlamak istiyor musunuz?</string>
<string name="statistics">İstatistikler</string>
@ -1000,6 +1009,10 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d
<string name="count_selected">%1$d seçildi</string>
<string name="sort_label">Sırala</string>
<string name="dialog_canceled">İletişim kutusu iptal edildi</string>
<string name="veryLow" comment="below 3.1">Çok düşük</string>
<string name="low" comment="3.1-3.9">Düşük</string>
<string name="high" comment="10.0-13.9">Yüksek</string>
<string name="veryHigh" comment="above 13.9">Çok yüksek</string>
<string name="below" comment="below &quot;in range&quot;">Altında</string>
<string name="in_range">Aralık içinde</string>
<string name="above" comment="above &quot;in range&quot;">Üstünde</string>
@ -1027,4 +1040,6 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d
<string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string>
<string name="description_source_aidex">GlucoRx Aidex CGMS\'den KŞ değerleri alır.</string>
<string name="blocked_by_charging">Şarj seçenekleri tarafından engellendi</string>
<string name="blocked_by_connectivity">Bağlantı seçenekleri tarafından engellendi</string>
</resources>

View file

@ -123,6 +123,7 @@
<string name="sensitivity_cannula">记录输注导管更换会将Autosens比率重置回100%。</string>
<string name="sensitivity_time">一些插件选项具有可配置的时间范围,可由用户设置。</string>
<string name="sensitivity_hint1">https://androidaps.readthedocs.io/en/latest/EN/Configuration/Sensitivity-detection-and-COB.html</string>
<string name="sensitivity_hint2">https://androidaps.readthedocs.io/en/latest/Usage/Open-APS-features.html?highlight=Autosens#autosens</string>
<string name="wrongcarbs_label">碳水化合物输入错误</string>
<string name="wrongcarbs_whattodo">如果您输入了不正确的碳水化合物,该怎么办?</string>
<string name="wrongcarbs_treatmentstab">删除治疗数据中的错误条目,并重新输入正确的碳水值。</string>

View file

@ -603,9 +603,7 @@
<string name="secondcarbsincrement">第二碳水化合物增量</string>
<string name="thirdcarbsincrement">第三碳水化合物增量</string>
<string name="cgm">CGM</string>
<string name="ns_wifionly">仅使用 WiFi 连接</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">仅在充电时</string>
<string name="connectionsettings_title">连接设置</string>
<string name="ns_wifi_allowedssids">允许的 SSIDs (分号分隔)</string>
<string name="ns_allowroaming">允许在漫游中连接</string>
@ -772,6 +770,7 @@
<string name="invalidpct">输入的百分比无效</string>
<string name="average">平均</string>
<string name="tir">TIR</string>
<string name="hba1c">糖化血红蛋白: </string>
<string name="activitymonitor">活动监视器</string>
<string name="doyouwantresetstats">您想要重置所有的统计信息吗?</string>
<string name="statistics">统计</string>
@ -967,9 +966,11 @@
<string name="wizard_no_active_profile">没有激活的个人配置文件!</string>
<string name="wizard_no_cob">未知的活性碳水!血糖读取缺失或最近重新启动了应用程序?</string>
<string name="wizard_carbs_constraint">碳水违反约束条件!</string>
<string name="wizard_explain_calc">计算 (IC: %1$.1f, ISF: %2$.1f)</string>
<string name="wizard_explain_carbs">碳水: %1$.2fU</string>
<string name="wizard_explain_cob">活性碳水: %1$.0f克 %2$.2fU</string>
<string name="wizard_explain_bg">血糖: %1$.2fU</string>
<string name="wizard_explain_iob">活性胰岛素: %1$.2fU</string>
<string name="wizard_explain_superbolus">超级大剂量:%1$.2fU</string>
<string name="wizard_explain_trend">15分钟趋势%1$.2fU</string>
<string name="wizard_explain_percent">百分比:%1$.2fU x %2$d%% ≈ %3$.2fU</string>
@ -996,6 +997,10 @@
<string name="count_selected">已选中 %1$d</string>
<string name="sort_label">排序</string>
<string name="dialog_canceled">对话框已取消</string>
<string name="veryLow" comment="below 3.1">非常低</string>
<string name="low" comment="3.1-3.9"></string>
<string name="high" comment="10.0-13.9"></string>
<string name="veryHigh" comment="above 13.9">非常高</string>
<string name="below" comment="below &quot;in range&quot;">底部</string>
<string name="in_range">在范围内</string>
<string name="above" comment="above &quot;in range&quot;">上方</string>
@ -1003,6 +1008,12 @@
<string name="show_hide_records">隐藏闭环记录</string>
<string name="widget_description">AndroidAPS小部件</string>
<string name="configure">配置透明度</string>
<string name="loop_status">闭环状态</string>
<string name="graph_scale">图形缩放</string>
<string name="profile1">配置文件 1</string>
<string name="profile2">配置文件 2</string>
<string name="login">登录</string>
<string name="remove_all">删除全部</string>
<string name="a11y_otp_qr_code">用于安装一次性随机验证码的二维码</string>
<string name="a11y_open_settings">打开设置</string>
<string name="a11y_set_carb_timer">设置碳水计时器提醒</string>
@ -1016,4 +1027,6 @@
<string name="aidex">GlucoRx Aidex动泰</string>
<string name="aidex_short">Aidex动泰</string>
<string name="description_source_aidex">从GlucoRx Aidex动泰持续葡萄糖监测系统接收血糖值。</string>
<string name="blocked_by_charging">被充电选项阻止</string>
<string name="blocked_by_connectivity">被连接选项阻止</string>
</resources>

View file

@ -733,13 +733,17 @@
<string name="secondcarbsincrement">Second carbs increment</string>
<string name="thirdcarbsincrement">Third carbs increment</string>
<string name="cgm">CGM</string>
<string name="key_ns_wifionly" translatable="false">ns_wifionly</string>
<string name="key_ns_cellular" translatable="false">ns_cellular</string>
<string name="key_ns_wifi" translatable="false">ns_wifi</string>
<string name="key_ns_wifi_ssids" translatable="false">ns_wifi_ssids</string>
<string name="key_ns_allowroaming" translatable="false">ns_allowroaming</string>
<string name="key_ns_chargingonly" translatable="false">ns_chargingonly</string>
<string name="ns_wifionly">Use WiFi connection only</string>
<string name="key_ns_allow_roaming" translatable="false">ns_allowroaming</string>
<string name="key_ns_battery" translatable="false">ns_battery</string>
<string name="key_ns_charging" translatable="false">ns_charging</string>
<string name="ns_cellular">Use Cellular connection</string>
<string name="ns_wifi">Use WiFi connection</string>
<string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Only if charging</string>
<string name="ns_charging">During charging</string>
<string name="ns_battery">On battery</string>
<string name="connectionsettings_title">Connection settings</string>
<string name="ns_wifi_allowedssids">Allowed SSIDs (semicolon separated)</string>
<string name="ns_allowroaming">Allow connection in roaming</string>
@ -1240,6 +1244,8 @@
<string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string>
<string name="description_source_aidex">Receive BG values from GlucoRx Aidex CGMS.</string>
<string name="blocked_by_charging">Blocked by charging options</string>
<string name="blocked_by_connectivity">Blocked by connectivity options</string>
</resources>

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

@ -138,26 +138,36 @@
<SwitchPreference
android:defaultValue="false"
android:disableDependentsState="true"
android:key="@string/key_ns_wifionly"
android:title="@string/ns_wifionly" />
android:key="@string/key_ns_cellular"
android:title="@string/ns_cellular" />
<SwitchPreference
android:defaultValue="true"
android:dependency="@string/key_ns_cellular"
android:key="@string/key_ns_allow_roaming"
android:title="@string/ns_allowroaming" />
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_wifi"
android:title="@string/ns_wifi" />
<EditTextPreference
android:dialogMessage="@string/ns_wifi_allowedssids"
android:dependency="@string/key_ns_wifi"
android:inputType="text"
android:key="@string/key_ns_wifi_ssids"
android:title="@string/ns_wifi_ssids" />
<SwitchPreference
android:defaultValue="true"
android:dependency="@string/key_ns_wifionly"
android:key="@string/key_ns_allowroaming"
android:title="@string/ns_allowroaming" />
android:key="@string/key_ns_battery"
android:title="@string/ns_battery" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_ns_chargingonly"
android:title="@string/ns_chargingonly" />
android:defaultValue="true"
android:key="@string/key_ns_charging"
android:title="@string/ns_charging" />
</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

@ -5,17 +5,13 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.events.EventChargingState
import info.nightscout.androidaps.events.EventNetworkChange
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.receivers.ReceiverStatusStore
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.`when`
@ -24,98 +20,71 @@ class NsClientReceiverDelegateTest : TestBase() {
@Mock lateinit var context: Context
@Mock lateinit var sp: SP
@Mock lateinit var rh: ResourceHelper
lateinit var receiverStatusStore: ReceiverStatusStore
val rxBus = RxBus(aapsSchedulers, aapsLogger)
private var sut: NsClientReceiverDelegate? = null
private lateinit var receiverStatusStore: ReceiverStatusStore
private lateinit var sut: NsClientReceiverDelegate
@Before fun prepare() {
@Before
fun prepare() {
receiverStatusStore = ReceiverStatusStore(context, rxBus)
`when`(sp.getLong(anyInt(), anyLong())).thenReturn(0L)
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false)
`when`(sp.getInt(anyInt(), anyInt())).thenReturn(0)
`when`(sp.getString(anyInt(), anyString())).thenReturn("")
sut = NsClientReceiverDelegate(rxBus, rh, sp, receiverStatusStore)
}
@Test fun testCalculateStatusChargingState() {
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false)
var ev = EventChargingState(true, 0)
Assert.assertTrue(sut!!.calculateStatus(ev))
ev = EventChargingState(false, 0)
Assert.assertTrue(sut!!.calculateStatus(ev))
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(true)
ev = EventChargingState(true, 0)
Assert.assertTrue(sut!!.calculateStatus(ev))
ev = EventChargingState(false, 0)
Assert.assertTrue(!sut!!.calculateStatus(ev))
@Test
fun testCalculateStatusChargingState() {
`when`(sp.getBoolean(R.string.key_ns_battery, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_charging, true)).thenReturn(false)
Assert.assertTrue(sut.calculateStatus(EventChargingState(false, 0)))
Assert.assertFalse(sut.calculateStatus(EventChargingState(true, 0)))
`when`(sp.getBoolean(R.string.key_ns_battery, true)).thenReturn(false)
`when`(sp.getBoolean(R.string.key_ns_charging, true)).thenReturn(true)
Assert.assertTrue(sut.calculateStatus(EventChargingState(true, 0)))
Assert.assertFalse(sut.calculateStatus(EventChargingState(false, 0)))
}
@Test fun testCalculateStatusNetworkState() {
// wifiOnly = false
// allowRoaming = false as well
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false)
`when`(sp.getString(anyInt(), anyString())).thenReturn("")
val ev = EventNetworkChange()
ev.ssid = "<unknown ssid>"
ev.mobileConnected = true
ev.wifiConnected = true
Assert.assertTrue(sut!!.calculateStatus(ev))
ev.ssid = "test"
`when`(sp.getString(anyInt(), anyString())).thenReturn("test")
Assert.assertTrue(sut!!.calculateStatus(ev))
ev.ssid = "test"
Assert.assertTrue(sut!!.calculateStatus(ev))
ev.wifiConnected = false
Assert.assertTrue(sut!!.calculateStatus(ev))
@Test
fun testCalculateStatusNetworkState() {
`when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
`when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = true)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = false)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = true, wifiConnected = true)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = false, wifiConnected = true)))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange()))
// wifiOnly = true
// allowRoaming = true as well
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(true)
ev.wifiConnected = true
Assert.assertTrue(sut!!.calculateStatus(ev))
ev.wifiConnected = false
Assert.assertTrue(!sut!!.calculateStatus(ev))
`when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("test")
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = true)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = false)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = true, wifiConnected = true)))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = false, wifiConnected = true)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "test", mobileConnected = true, wifiConnected = true)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "test", mobileConnected = false, wifiConnected = true)))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange()))
// wifiOnly = false
// allowRoaming = false as well
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false)
ev.wifiConnected = false
ev.roaming = true
Assert.assertTrue(!sut!!.calculateStatus(ev))
`when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(false)
`when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(true)
`when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(wifiConnected = true)))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange()))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange(mobileConnected = true)))
// wifiOnly = false
// allowRoaming = true
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(false)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(true)
ev.wifiConnected = false
ev.roaming = true
Assert.assertTrue(sut!!.calculateStatus(ev))
`when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(false)
`when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = false)))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = true)))
// wifiOnly = true
// allowRoaming = true
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(true)
ev.wifiConnected = false
ev.roaming = true
Assert.assertTrue(!sut!!.calculateStatus(ev))
// wifiOnly = true
// allowRoaming = true
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(true)
ev.wifiConnected = true
ev.roaming = true
Assert.assertTrue(sut!!.calculateStatus(ev))
// wifiOnly = false
// allowRoaming = false
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(false)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(false)
ev.wifiConnected = true
ev.roaming = true
Assert.assertTrue(sut!!.calculateStatus(ev))
`when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(true)
`when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = false)))
Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = true)))
}
}

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

@ -261,6 +261,7 @@ class AutomationPlugin @Inject constructor(
@Synchronized
fun add(event: AutomationEvent) {
automationEvents.add(event)
event.position = automationEvents.size - 1
rxBus.send(EventAutomationDataChanged())
}

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuil
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.TimerUtil
import org.json.JSONObject
import javax.inject.Inject
@ -40,7 +39,7 @@ class ActionAlarm(injector: HasAndroidInjector) : Action(injector) {
override fun doAction(callback: Callback) {
timerUtil.scheduleReminder(10, text.value.takeIf { it.isNotBlank() }
?: rh.gs(R.string.app_name))
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
}
override fun toJSON(): String {

View file

@ -33,9 +33,9 @@ class ActionLoopEnable(injector: HasAndroidInjector) : Action(injector) {
configBuilder.storeSettings("ActionLoopEnable")
rxBus.send(EventRefreshOverview("ActionLoopEnable"))
uel.log(UserEntry.Action.LOOP_ENABLED, Sources.Automation, title)
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} else {
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyenabled))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyenabled)).run()
}
}

View file

@ -45,9 +45,9 @@ class ActionLoopResume(injector: HasAndroidInjector) : Action(injector) {
})
rxBus.send(EventRefreshOverview("ActionLoopResume"))
uel.log(UserEntry.Action.RESUME, Sources.Automation, title)
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} else {
callback.result(PumpEnactResult(injector).success(true).comment(R.string.notsuspended))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.notsuspended)).run()
}
}

View file

@ -40,9 +40,9 @@ class ActionLoopSuspend(injector: HasAndroidInjector) : Action(injector) {
UserEntry.Action.SUSPEND, Sources.Automation, title + ": " + rh.gs(R.string.suspendloopforXmin, minutes.getMinutes()),
ValueWithUnit.Minute(minutes.getMinutes())
)
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} else {
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadysuspended))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadysuspended)).run()
}
}

View file

@ -39,7 +39,7 @@ class ActionNotification(injector: HasAndroidInjector) : Action(injector) {
rxBus.send(EventNewNotification(notification))
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(text.value)).subscribe()
rxBus.send(EventRefreshOverview("ActionNotification"))
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
}
override fun toJSON(): String {

View file

@ -10,7 +10,6 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.automation.elements.InputProfileName
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement
@ -18,6 +17,7 @@ import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuil
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.shared.logging.LTag
import org.json.JSONObject
import javax.inject.Inject
@ -39,23 +39,23 @@ class ActionProfileSwitch(injector: HasAndroidInjector) : Action(injector) {
//Check for uninitialized profileName
if (inputProfileName.value == "") {
aapsLogger.error(LTag.AUTOMATION, "Selected profile not initialized")
callback.result(PumpEnactResult(injector).success(false).comment(R.string.error_field_must_not_be_empty))?.run()
callback.result(PumpEnactResult(injector).success(false).comment(R.string.error_field_must_not_be_empty)).run()
return
}
if (profileFunction.getProfile() == null) {
aapsLogger.error(LTag.AUTOMATION, "ProfileFunctions not initialized")
callback.result(PumpEnactResult(injector).success(false).comment(R.string.noprofile))?.run()
callback.result(PumpEnactResult(injector).success(false).comment(R.string.noprofile)).run()
return
}
if (inputProfileName.value == activeProfileName) {
aapsLogger.debug(LTag.AUTOMATION, "Profile is already switched")
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyset))?.run()
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyset)).run()
return
}
val profileStore = activePlugin.activeProfileSource.profile ?: return
if (profileStore.getSpecificProfile(inputProfileName.value) == null) {
aapsLogger.error(LTag.AUTOMATION, "Selected profile does not exist! - ${inputProfileName.value}")
callback.result(PumpEnactResult(injector).success(false).comment(R.string.notexists))?.run()
callback.result(PumpEnactResult(injector).success(false).comment(R.string.notexists)).run()
return
}
uel.log(
@ -64,7 +64,7 @@ class ActionProfileSwitch(injector: HasAndroidInjector) : Action(injector) {
ValueWithUnit.Percent(100)
)
val result = profileFunction.createProfileSwitch(profileStore, inputProfileName.value, 0, 100, 0, dateUtil.now())
callback.result(PumpEnactResult(injector).success(result).comment(R.string.ok))?.run()
callback.result(PumpEnactResult(injector).success(result).comment(R.string.ok)).run()
}
override fun generateDialog(root: LinearLayout) {

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