Merge remote-tracking branch 'Nightscout/dev' into Autotune/TuneWeekDaysClean
This commit is contained in:
commit
3b6a3605a2
1049 changed files with 26413 additions and 12742 deletions
2
.github/ISSUE_TEMPLATE/custom.md
vendored
2
.github/ISSUE_TEMPLATE/custom.md
vendored
|
@ -15,5 +15,5 @@ Reporting bugs
|
|||
upper-right corner).
|
||||
- Obtain the app's log files, which can be found on the phone in
|
||||
_/storage/emulated/0/Android/data/info.nightscout.androidaps/_
|
||||
See https://androidaps.readthedocs.io/en/latest/Usage/Accessing-logfiles.html
|
||||
See https://wiki.aaps.app/en/latest/Usage/Accessing-logfiles.html
|
||||
- Open an issue at https://github.com/nightscout/AndroidAPS/issues/new
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
|
||||
<JetCodeStyleSettings>
|
||||
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
|
||||
<option name="BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES" value="1" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
|
|
|
@ -7,9 +7,9 @@ General rules
|
|||
=============
|
||||
|
||||
* There are plenty of ways you can help, some of them are listed on wiki:
|
||||
https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/How-can-I-help.html
|
||||
https://wiki.aaps.app/en/latest/Getting-Started/How-can-I-help.html
|
||||
* If you wish to help with documentation or translating:
|
||||
https://androidaps.readthedocs.io/en/latest/EN/translations.html
|
||||
https://wiki.aaps.app/en/latest/translations.html
|
||||
|
||||
Development guidelines
|
||||
======================
|
||||
|
|
|
@ -6,5 +6,5 @@ Reporting bugs
|
|||
upper-right corner).
|
||||
- Obtain the app's log files, which can be found on the phone in
|
||||
_/storage/emulated/0/Android/data/info.nightscout.androidaps/_
|
||||
See https://androidaps.readthedocs.io/en/latest/EN/Usage/Accessing-logfiles.html
|
||||
See https://wiki.aaps.app/en/latest/Usage/Accessing-logfiles.html
|
||||
- Open an issue at https://github.com/nightscout/AndroidAPS/issues/new
|
||||
|
|
|
@ -7,12 +7,11 @@
|
|||
[![CircleCI](https://circleci.com/gh/nightscout/AndroidAPS/tree/master.svg?style=svg)](https://circleci.com/gh/nightscout/AndroidAPS/tree/master)
|
||||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/androidaps/localized.svg)](https://translations.aaps.app/project/androidaps)
|
||||
[![Documentation Status](https://readthedocs.org/projects/androidaps/badge/?version=latest)](https://wiki.aaps.app/en/latest/?badge=latest)
|
||||
[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/master/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
|
||||
[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/master/graph/badge.svg?token=EmklfIV6bH)](https://codecov.io/gh/nightscout/AndroidAPS)
|
||||
|
||||
DEV:
|
||||
[![CircleCI](https://circleci.com/gh/nightscout/AndroidAPS/tree/dev.svg?style=svg)](https://circleci.com/gh/nightscout/AndroidAPS/tree/dev)
|
||||
[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/dev/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
|
||||
|
||||
[![codecov](https://codecov.io/gh/nightscout/AndroidAPS/branch/dev/graph/badge.svg?token=EmklfIV6bH)](https://codecov.io/gh/nightscout/AndroidAPS/tree/dev)
|
||||
|
||||
<img src="https://cdn.iconscout.com/icon/free/png-256/bitcoin-384-920569.png" srcset="https://cdn.iconscout.com/icon/free/png-512/bitcoin-384-920569.png 2x" alt="Bitcoin Icon" width="100">
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package info.nightscout.rx.events
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class EventNSClientNewLog(val action: String, val logText: String) : Event() {
|
||||
class EventNSClientNewLog(val action: String, val logText: String?) : Event() {
|
||||
var date = System.currentTimeMillis()
|
||||
|
||||
private var timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
|
||||
|
@ -15,7 +15,6 @@ class EventNSClientNewLog(val action: String, val logText: String) : Event() {
|
|||
stringBuilder.append(action)
|
||||
stringBuilder.append("</b> ")
|
||||
stringBuilder.append(logText)
|
||||
stringBuilder.append("<br>")
|
||||
return stringBuilder
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package info.nightscout.rx.events
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class EventXdripNewLog(val action: String, val logText: String?) : Event() {
|
||||
var date = System.currentTimeMillis()
|
||||
|
||||
private var timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
|
||||
|
||||
fun toPreparedHtml(): StringBuilder {
|
||||
val stringBuilder = StringBuilder()
|
||||
stringBuilder.append(timeFormat.format(date))
|
||||
stringBuilder.append(" <b>")
|
||||
stringBuilder.append(action)
|
||||
stringBuilder.append("</b> ")
|
||||
stringBuilder.append(logText)
|
||||
stringBuilder.append("<br>")
|
||||
return stringBuilder
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ enum class LTag(val tag: String, val defaultValue : Boolean = true, val requires
|
|||
DATATREATMENTS("DATATREATMENTS"),
|
||||
EVENTS("EVENTS", defaultValue = false, requiresRestart = true),
|
||||
GLUCOSE("GLUCOSE", defaultValue = false),
|
||||
HTTP("HTTP"),
|
||||
LOCATION("LOCATION"),
|
||||
NOTIFICATION("NOTIFICATION"),
|
||||
NSCLIENT("NSCLIENT"),
|
||||
|
@ -27,5 +28,6 @@ enum class LTag(val tag: String, val defaultValue : Boolean = true, val requires
|
|||
UI("UI", defaultValue = false),
|
||||
WEAR("WEAR"),
|
||||
WIDGET("WIDGET"),
|
||||
WORKER("WORKER")
|
||||
WORKER("WORKER"),
|
||||
XDRIP("XDRIP")
|
||||
}
|
|
@ -2,7 +2,12 @@
|
|||
<resources>
|
||||
<!-- DateUtil-->
|
||||
<string name="minago">преди %1$d мин</string>
|
||||
<string name="minago_long">Преди %1$d минути</string>
|
||||
<string name="hoursago">преди %1$.1fч</string>
|
||||
<string name="days_ago">преди %1$.1f дни</string>
|
||||
<string name="days_ago_round">преди %1$.0f дни</string>
|
||||
<string name="in_days">за %1$.0f дни</string>
|
||||
<string name="in_days_round">за %1$.0f дни</string>
|
||||
<string name="shorthour">ч</string>
|
||||
<string name="days">дни</string>
|
||||
<string name="hours">часа</string>
|
||||
|
@ -18,6 +23,10 @@
|
|||
<string name="unit_weeks">седмици</string>
|
||||
<string name="shortminute">м</string>
|
||||
<string name="shortday">д</string>
|
||||
<string name="later_today">По-късно днес</string>
|
||||
<string name="tomorrow">Утре</string>
|
||||
<string name="today">Днес</string>
|
||||
<string name="yesterday">Вчера</string>
|
||||
<!-- Rx -->
|
||||
<string name="connecting_for">Свързване %1$d сек</string>
|
||||
<string name="handshaking">Сдвояване</string>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<string name="days_ago_round">vor %1$.0f Tagen</string>
|
||||
<string name="in_days">in %1$.0f Tagen</string>
|
||||
<string name="in_days_round">in %1$.0f Tagen</string>
|
||||
<string name="shorthour">s</string>
|
||||
<string name="shorthour">h</string>
|
||||
<string name="days">Tage</string>
|
||||
<string name="hours">Stunden</string>
|
||||
<string name="unit_second">Sekunde</string>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<resources>
|
||||
<!-- DateUtil-->
|
||||
<string name="minago">%1$d min temu</string>
|
||||
<string name="minago_long">%1$d minut temu</string>
|
||||
<string name="hoursago">%1$.1f godz. temu</string>
|
||||
<string name="days_ago">%1$.1f dni temu</string>
|
||||
<string name="days_ago_round">%1$.0f dni temu</string>
|
||||
|
|
|
@ -111,7 +111,7 @@ android {
|
|||
defaultConfig {
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "3.1.0.3-dev-e"
|
||||
version "3.1.0.3-dev-h"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||
|
@ -177,7 +177,6 @@ allprojects {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':plugins:aps')
|
||||
wearApp project(':wear')
|
||||
|
||||
// in order to use internet's versions you'd need to enable Jetifier again
|
||||
|
@ -201,8 +200,8 @@ dependencies {
|
|||
implementation project(':plugins:constraints')
|
||||
implementation project(':plugins:insulin')
|
||||
implementation project(':plugins:main')
|
||||
implementation project(':plugins:openhumans')
|
||||
implementation project(':plugins:sensitivity')
|
||||
implementation project(':plugins:smoothing')
|
||||
implementation project(':plugins:source')
|
||||
implementation project(':plugins:sync')
|
||||
implementation project(':implementation')
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
<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.g7.EXTERNAL_BROADCAST" />
|
||||
<!-- Receiver from Poctech -->
|
||||
<action android:name="com.china.poctech.data" />
|
||||
<!-- Receiver from Tomato -->
|
||||
|
|
|
@ -51,7 +51,6 @@ import info.nightscout.interfaces.aps.Loop
|
|||
import info.nightscout.interfaces.constraints.Constraints
|
||||
import info.nightscout.interfaces.logging.UserEntryLogger
|
||||
import info.nightscout.interfaces.maintenance.PrefFileListProvider
|
||||
import info.nightscout.interfaces.nsclient.NSSettingsStatus
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.interfaces.plugin.PluginBase
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
|
@ -62,7 +61,6 @@ import info.nightscout.interfaces.versionChecker.VersionCheckerUtils
|
|||
import info.nightscout.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.events.EventAppExit
|
||||
import info.nightscout.rx.events.EventInitializationChanged
|
||||
import info.nightscout.rx.events.EventPreferenceChange
|
||||
import info.nightscout.rx.events.EventRebuildTabs
|
||||
import info.nightscout.rx.logging.LTag
|
||||
|
@ -88,7 +86,6 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
|
|||
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
|
||||
@Inject lateinit var smsCommunicator: SmsCommunicator
|
||||
@Inject lateinit var loop: Loop
|
||||
@Inject lateinit var nsSettingsStatus: NSSettingsStatus
|
||||
@Inject lateinit var config: Config
|
||||
@Inject lateinit var activePlugin: ActivePlugin
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
|
@ -347,11 +344,11 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
|
|||
R.id.nav_about -> {
|
||||
var message = "Build: ${BuildConfig.BUILDVERSION}\n"
|
||||
message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n"
|
||||
message += "${rh.gs(info.nightscout.configuration.R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.getVersion()}"
|
||||
message += "${rh.gs(info.nightscout.configuration.R.string.configbuilder_nightscoutversion_label)} ${activePlugin.activeNsClient?.detectedNsVersion() ?: rh.gs(info.nightscout.plugins.R.string.not_available_full)}"
|
||||
if (config.isEngineeringMode()) message += "\n${rh.gs(info.nightscout.configuration.R.string.engineering_mode_enabled)}"
|
||||
if (config.isUnfinishedMode()) message += "\nUnfinished mode enabled"
|
||||
if (!fabricPrivacy.fabricEnabled()) message += "\n${rh.gs(R.string.fabric_upload_disabled)}"
|
||||
message += rh.gs(info.nightscout.pump.combo.R.string.about_link_urls)
|
||||
if (!fabricPrivacy.fabricEnabled()) message += "\n${rh.gs(info.nightscout.core.ui.R.string.fabric_upload_disabled)}"
|
||||
message += rh.gs(info.nightscout.core.ui.R.string.about_link_urls)
|
||||
val messageSpanned = SpannableString(message)
|
||||
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
|
||||
MaterialAlertDialogBuilder(this, info.nightscout.core.ui.R.style.DialogTheme)
|
||||
|
@ -359,7 +356,7 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
|
|||
.setIcon(iconsProvider.getIcon())
|
||||
.setMessage(messageSpanned)
|
||||
.setPositiveButton(rh.gs(info.nightscout.core.ui.R.string.ok), null)
|
||||
.setNeutralButton(rh.gs(R.string.cta_dont_kill_my_app_info)) { _, _ ->
|
||||
.setNeutralButton(rh.gs(info.nightscout.core.ui.R.string.cta_dont_kill_my_app_info)) { _, _ ->
|
||||
startActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
|
|
|
@ -151,7 +151,7 @@ class MainApp : DaggerApplication() {
|
|||
// schedule widget update
|
||||
refreshWidget = Runnable {
|
||||
handler.postDelayed(refreshWidget, 60000)
|
||||
Widget.updateWidget(this)
|
||||
Widget.updateWidget(this, "ScheduleEveryMin")
|
||||
}
|
||||
handler.postDelayed(refreshWidget, 60000)
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ class MainApp : DaggerApplication() {
|
|||
Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), e)
|
||||
return@setErrorHandler
|
||||
}
|
||||
aapsLogger.warn(LTag.CORE, "Undeliverable exception received, not sure what to do", e.toString())
|
||||
aapsLogger.warn(LTag.CORE, "Undeliverable exception received, not sure what to do", e.localizedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ class HistoryBrowseActivity : DaggerAppCompatActivity() {
|
|||
val menuChartSettings = overviewMenus.setting
|
||||
graphData.addInRangeArea(historyBrowserData.overviewData.fromTime, historyBrowserData.overviewData.endTime, defaultValueHelper.determineLowLine(), defaultValueHelper.determineHighLine())
|
||||
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal], context)
|
||||
if (config.isDev()) graphData.addBucketedData()
|
||||
graphData.addBucketedData()
|
||||
graphData.addTreatments(context)
|
||||
graphData.addEps(context, 0.95)
|
||||
if (menuChartSettings[0][OverviewMenus.CharType.TREAT.ordinal])
|
||||
|
@ -367,7 +367,7 @@ class HistoryBrowseActivity : DaggerAppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun updateCalcProgress(percent: Int) {
|
||||
binding.progressBar.progress = percent
|
||||
binding.progressBar.visibility = (percent != 100).toVisibilityKeepSpace()
|
||||
binding.progressBar.progress = percent
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import info.nightscout.androidaps.R
|
|||
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
|
||||
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
||||
import info.nightscout.androidaps.danar.DanaRPlugin
|
||||
import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploaderPlugin
|
||||
import info.nightscout.plugins.sync.openhumans.OpenHumansUploaderPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.eopatch.EopatchPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
|
||||
|
@ -47,10 +47,10 @@ import info.nightscout.plugins.constraints.safety.SafetyPlugin
|
|||
import info.nightscout.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.plugins.general.wear.WearPlugin
|
||||
import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin
|
||||
import info.nightscout.plugins.sync.nsclient.NSClientPlugin
|
||||
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
|
||||
import info.nightscout.plugins.sync.tidepool.TidepoolPlugin
|
||||
import info.nightscout.plugins.sync.xdrip.XdripPlugin
|
||||
import info.nightscout.pump.combo.ComboPlugin
|
||||
import info.nightscout.pump.combov2.ComboV2Plugin
|
||||
import info.nightscout.pump.diaconn.DiaconnG8Plugin
|
||||
|
@ -116,7 +116,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
|||
@Inject lateinit var intelligoPlugin: IntelligoPlugin
|
||||
@Inject lateinit var aidexPlugin: AidexPlugin
|
||||
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
||||
@Inject lateinit var statusLinePlugin: StatusLinePlugin
|
||||
@Inject lateinit var statusLinePlugin: XdripPlugin
|
||||
@Inject lateinit var tidepoolPlugin: TidepoolPlugin
|
||||
@Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin
|
||||
@Inject lateinit var wearPlugin: WearPlugin
|
||||
|
@ -260,7 +260,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
|||
|
||||
private fun preprocessPreferences() {
|
||||
for (plugin in pluginStore.plugins) {
|
||||
plugin.preprocessPreferences(this)
|
||||
if (plugin.isEnabled()) plugin.preprocessPreferences(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import info.nightscout.androidaps.MainApp
|
|||
import info.nightscout.androidaps.danar.di.DanaRModule
|
||||
import info.nightscout.androidaps.insight.di.InsightDatabaseModule
|
||||
import info.nightscout.androidaps.insight.di.InsightModule
|
||||
import info.nightscout.androidaps.plugin.general.openhumans.di.OpenHumansModule
|
||||
import info.nightscout.plugins.sync.di.OpenHumansModule
|
||||
import info.nightscout.androidaps.plugins.pump.common.di.RileyLinkModule
|
||||
import info.nightscout.androidaps.plugins.pump.eopatch.dagger.EopatchModule
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.di.MedtronicModule
|
||||
|
|
|
@ -34,14 +34,14 @@ open class AppModule {
|
|||
@PluginsListModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||
@PluginsListModule.NotNSClient notNsClient: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||
@PluginsListModule.APS aps: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||
@PluginsListModule.Unfinished unfinished: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>
|
||||
//@PluginsListModule.Unfinished unfinished: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>
|
||||
)
|
||||
: List<@JvmSuppressWildcards PluginBase> {
|
||||
val plugins = allConfigs.toMutableMap()
|
||||
if (config.PUMPDRIVERS) plugins += pumpDrivers.get()
|
||||
if (config.APS) plugins += aps.get()
|
||||
if (!config.NSCLIENT) plugins += notNsClient.get()
|
||||
if (config.isUnfinishedMode()) plugins += unfinished.get()
|
||||
//if (config.isUnfinishedMode()) plugins += unfinished.get()
|
||||
return plugins.toList().sortedBy { it.first }.map { it.second }
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import dagger.multibindings.IntoMap
|
|||
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
|
||||
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
||||
import info.nightscout.androidaps.danar.DanaRPlugin
|
||||
import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploaderPlugin
|
||||
import info.nightscout.plugins.sync.openhumans.OpenHumansUploaderPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.eopatch.EopatchPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
|
||||
|
@ -31,19 +31,19 @@ import info.nightscout.plugins.constraints.safety.SafetyPlugin
|
|||
import info.nightscout.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||
import info.nightscout.plugins.general.actions.ActionsPlugin
|
||||
import info.nightscout.plugins.general.autotune.AutotunePlugin
|
||||
import info.nightscout.plugins.general.dataBroadcaster.DataBroadcastPlugin
|
||||
import info.nightscout.plugins.general.food.FoodPlugin
|
||||
import info.nightscout.plugins.general.overview.OverviewPlugin
|
||||
import info.nightscout.plugins.general.persistentNotification.PersistentNotificationPlugin
|
||||
import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.plugins.general.themes.ThemeSwitcherPlugin
|
||||
import info.nightscout.plugins.general.wear.WearPlugin
|
||||
import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin
|
||||
import info.nightscout.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import info.nightscout.plugins.sync.dataBroadcaster.DataBroadcastPlugin
|
||||
import info.nightscout.plugins.sync.nsclient.NSClientPlugin
|
||||
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
|
||||
import info.nightscout.plugins.sync.tidepool.TidepoolPlugin
|
||||
import info.nightscout.plugins.sync.xdrip.XdripPlugin
|
||||
import info.nightscout.pump.combo.ComboPlugin
|
||||
import info.nightscout.pump.combov2.ComboV2Plugin
|
||||
import info.nightscout.pump.diaconn.DiaconnG8Plugin
|
||||
|
@ -51,6 +51,9 @@ import info.nightscout.pump.virtual.VirtualPumpPlugin
|
|||
import info.nightscout.sensitivity.SensitivityAAPSPlugin
|
||||
import info.nightscout.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.sensitivity.SensitivityWeightedAveragePlugin
|
||||
import info.nightscout.smoothing.AvgSmoothingPlugin
|
||||
import info.nightscout.smoothing.ExponentialSmoothingPlugin
|
||||
import info.nightscout.smoothing.NoSmoothingPlugin
|
||||
import info.nightscout.source.AidexPlugin
|
||||
import info.nightscout.source.DexcomPlugin
|
||||
import info.nightscout.source.GlimpPlugin
|
||||
|
@ -61,7 +64,7 @@ import info.nightscout.source.NSClientSourcePlugin
|
|||
import info.nightscout.source.PoctechPlugin
|
||||
import info.nightscout.source.RandomBgPlugin
|
||||
import info.nightscout.source.TomatoPlugin
|
||||
import info.nightscout.source.XdripPlugin
|
||||
import info.nightscout.source.XdripSourcePlugin
|
||||
import javax.inject.Qualifier
|
||||
|
||||
@Suppress("unused")
|
||||
|
@ -305,26 +308,38 @@ abstract class PluginsListModule {
|
|||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(340)
|
||||
abstract fun bindStatusLinePlugin(plugin: StatusLinePlugin): PluginBase
|
||||
@IntKey(350)
|
||||
abstract fun bindNSClientPlugin(plugin: NSClientPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(360)
|
||||
abstract fun bindNSClientPlugin(plugin: NSClientPlugin): PluginBase
|
||||
@IntKey(355)
|
||||
abstract fun bindNSClientV3Plugin(plugin: NSClientV3Plugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@Unfinished
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(368)
|
||||
@IntKey(360)
|
||||
abstract fun bindTidepoolPlugin(plugin: TidepoolPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@Unfinished
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(362)
|
||||
abstract fun bindNSClientV3Plugin(plugin: NSClientV3Plugin): PluginBase
|
||||
@IntKey(364)
|
||||
abstract fun bindXdripPlugin(plugin: XdripPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(366)
|
||||
abstract fun bindDataBroadcastPlugin(plugin: DataBroadcastPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(368)
|
||||
abstract fun bindsOpenHumansPlugin(plugin: OpenHumansUploaderPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
|
@ -344,17 +359,11 @@ abstract class PluginsListModule {
|
|||
@IntKey(381)
|
||||
abstract fun bindBgQualityCheckPlugin(plugin: BgQualityCheckPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(390)
|
||||
abstract fun bindDataBroadcastPlugin(plugin: DataBroadcastPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(400)
|
||||
abstract fun bindXdripPlugin(plugin: XdripPlugin): PluginBase
|
||||
abstract fun bindXdripSourcePlugin(plugin: XdripSourcePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
|
@ -416,12 +425,6 @@ abstract class PluginsListModule {
|
|||
@IntKey(475)
|
||||
abstract fun bindRandomBgPlugin(plugin: RandomBgPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(480)
|
||||
abstract fun bindsOpenHumansPlugin(plugin: OpenHumansUploaderPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
|
@ -434,6 +437,24 @@ abstract class PluginsListModule {
|
|||
@IntKey(500)
|
||||
abstract fun bindThemeSwitcherPlugin(plugin: ThemeSwitcherPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(600)
|
||||
abstract fun bindNoSmoothingPlugin(plugin: NoSmoothingPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(605)
|
||||
abstract fun bindExponentialSmoothingPlugin(plugin: ExponentialSmoothingPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(610)
|
||||
abstract fun bindAvgSmoothingPlugin(plugin: AvgSmoothingPlugin): PluginBase
|
||||
|
||||
@Qualifier
|
||||
annotation class AllConfigs
|
||||
|
||||
|
|
|
@ -9,12 +9,13 @@ import java.io.File
|
|||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
@Singleton
|
||||
class ConfigImpl @Inject constructor(
|
||||
fileListProvider: PrefFileListProvider
|
||||
) : Config {
|
||||
|
||||
override val SUPPORTEDNSVERSION = 140206 // 14.2.6
|
||||
override val SUPPORTED_NS_VERSION = 150000 // 15.0.0
|
||||
override val APS = BuildConfig.FLAVOR == "full"
|
||||
override val NSCLIENT = BuildConfig.FLAVOR == "aapsclient" || BuildConfig.FLAVOR == "aapsclient2"
|
||||
override val PUMPCONTROL = BuildConfig.FLAVOR == "pumpcontrol"
|
||||
|
|
|
@ -14,8 +14,6 @@ import info.nightscout.androidaps.activities.MyPreferenceFragment
|
|||
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||
import info.nightscout.configuration.activities.SingleFragmentActivity
|
||||
import info.nightscout.core.events.EventNewNotification
|
||||
import info.nightscout.ui.services.AlarmSoundService
|
||||
import info.nightscout.ui.services.AlarmSoundServiceHelper
|
||||
import info.nightscout.core.ui.toast.ToastUtils
|
||||
import info.nightscout.interfaces.notifications.Notification
|
||||
import info.nightscout.interfaces.nsclient.NSAlarm
|
||||
|
@ -24,6 +22,7 @@ import info.nightscout.plugins.general.overview.notifications.NotificationWithAc
|
|||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.ui.activities.BolusProgressHelperActivity
|
||||
import info.nightscout.ui.activities.ErrorHelperActivity
|
||||
import info.nightscout.ui.activities.QuickWizardListActivity
|
||||
import info.nightscout.ui.activities.TDDStatsActivity
|
||||
import info.nightscout.ui.dialogs.BolusProgressDialog
|
||||
import info.nightscout.ui.dialogs.CalibrationDialog
|
||||
|
@ -39,6 +38,8 @@ import info.nightscout.ui.dialogs.TempBasalDialog
|
|||
import info.nightscout.ui.dialogs.TempTargetDialog
|
||||
import info.nightscout.ui.dialogs.TreatmentDialog
|
||||
import info.nightscout.ui.dialogs.WizardDialog
|
||||
import info.nightscout.ui.services.AlarmSoundService
|
||||
import info.nightscout.ui.services.AlarmSoundServiceHelper
|
||||
import info.nightscout.ui.widget.Widget
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -57,6 +58,7 @@ class UiInteractionImpl @Inject constructor(
|
|||
override val singleFragmentActivity: Class<*> = SingleFragmentActivity::class.java
|
||||
override val preferencesActivity: Class<*> = PreferencesActivity::class.java
|
||||
override val myPreferenceFragment: Class<*> = MyPreferenceFragment::class.java
|
||||
override val quickWizardListActivity: Class<*> = QuickWizardListActivity::class.java
|
||||
override val prefGeneral: Int = R.xml.pref_general
|
||||
|
||||
override fun runAlarm(status: String, title: String, @RawRes soundId: Int) {
|
||||
|
@ -68,8 +70,8 @@ class UiInteractionImpl @Inject constructor(
|
|||
context.startActivity(i)
|
||||
}
|
||||
|
||||
override fun updateWidget(context: Context) {
|
||||
Widget.updateWidget(context)
|
||||
override fun updateWidget(context: Context, from: String) {
|
||||
Widget.updateWidget(context, from)
|
||||
}
|
||||
|
||||
override fun runWizardDialog(fragmentManager: FragmentManager, carbs: Int?, name: String?) {
|
||||
|
|
|
@ -32,12 +32,15 @@ class ChargingStateReceiver : DaggerBroadcastReceiver() {
|
|||
var batteryLevel = 0
|
||||
val level = batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1
|
||||
val scale = batteryStatus?.getIntExtra(BatteryManager.EXTRA_SCALE, -1) ?: -1
|
||||
val plugged = batteryStatus?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1
|
||||
if (level != -1 && scale != -1)
|
||||
batteryLevel = (level.toFloat() / scale.toFloat() * 100.0f).toInt()
|
||||
// Status
|
||||
val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
|
||||
val isCharging: Boolean = status == BatteryManager.BATTERY_STATUS_CHARGING
|
||||
|| status == BatteryManager.BATTERY_STATUS_FULL
|
||||
// Plugged
|
||||
val isCharging: Boolean =
|
||||
plugged == BatteryManager.BATTERY_PLUGGED_AC ||
|
||||
plugged == BatteryManager.BATTERY_PLUGGED_USB ||
|
||||
plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS ||
|
||||
plugged == BatteryManager.BATTERY_PLUGGED_DOCK
|
||||
|
||||
return EventChargingState(isCharging, batteryLevel).also { receiverStatusStore.lastChargingEvent = it }
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import info.nightscout.source.GlimpPlugin
|
|||
import info.nightscout.source.MM640gPlugin
|
||||
import info.nightscout.source.PoctechPlugin
|
||||
import info.nightscout.source.TomatoPlugin
|
||||
import info.nightscout.source.XdripPlugin
|
||||
import info.nightscout.source.XdripSourcePlugin
|
||||
import javax.inject.Inject
|
||||
|
||||
open class DataReceiver : DaggerBroadcastReceiver() {
|
||||
|
@ -37,7 +37,7 @@ open class DataReceiver : DaggerBroadcastReceiver() {
|
|||
|
||||
when (intent.action) {
|
||||
Intents.ACTION_NEW_BG_ESTIMATE ->
|
||||
OneTimeWorkRequest.Builder(XdripPlugin.XdripWorker::class.java)
|
||||
OneTimeWorkRequest.Builder(XdripSourcePlugin.XdripSourceWorker::class.java)
|
||||
.setInputData(dataWorkerStorage.storeInputData(bundle, intent.action)).build()
|
||||
Intents.POCTECH_BG ->
|
||||
OneTimeWorkRequest.Builder(PoctechPlugin.PoctechWorker::class.java)
|
||||
|
@ -70,9 +70,11 @@ open class DataReceiver : DaggerBroadcastReceiver() {
|
|||
Intents.EVERSENSE_BG ->
|
||||
OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java)
|
||||
.setInputData(dataWorkerStorage.storeInputData(bundle, intent.action)).build()
|
||||
Intents.DEXCOM_BG ->
|
||||
|
||||
Intents.DEXCOM_BG, Intents.DEXCOM_G7_BG ->
|
||||
OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java)
|
||||
.setInputData(dataWorkerStorage.storeInputData(bundle, intent.action)).build()
|
||||
|
||||
Intents.AIDEX_NEW_BG_ESTIMATE ->
|
||||
OneTimeWorkRequest.Builder(AidexPlugin.AidexWorker::class.java)
|
||||
.setInputData(dataWorkerStorage.storeInputData(bundle, intent.action)).build()
|
||||
|
|
|
@ -14,7 +14,6 @@ import info.nightscout.androidaps.BuildConfig
|
|||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.configuration.maintenance.MaintenancePlugin
|
||||
import info.nightscout.core.profile.ProfileSealed
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
import info.nightscout.core.utils.worker.LoggingWorker
|
||||
import info.nightscout.database.impl.AppRepository
|
||||
import info.nightscout.interfaces.Config
|
||||
|
@ -23,7 +22,6 @@ import info.nightscout.interfaces.aps.Loop
|
|||
import info.nightscout.interfaces.configBuilder.RunningConfiguration
|
||||
import info.nightscout.interfaces.iob.IobCobCalculator
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.interfaces.plugin.PluginBase
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
import info.nightscout.interfaces.queue.Command
|
||||
import info.nightscout.interfaces.queue.CommandQueue
|
||||
|
@ -35,7 +33,7 @@ import info.nightscout.shared.interfaces.ResourceHelper
|
|||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import info.nightscout.shared.utils.DateUtil
|
||||
import info.nightscout.shared.utils.T
|
||||
import info.nightscout.ui.widget.Widget
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
@ -43,7 +41,7 @@ import kotlin.math.abs
|
|||
class KeepAliveWorker(
|
||||
private val context: Context,
|
||||
params: WorkerParameters
|
||||
) : LoggingWorker(context, params) {
|
||||
) : LoggingWorker(context, params, Dispatchers.Default) {
|
||||
|
||||
@Inject lateinit var localAlertUtils: LocalAlertUtils
|
||||
@Inject lateinit var repository: AppRepository
|
||||
|
@ -57,7 +55,6 @@ class KeepAliveWorker(
|
|||
@Inject lateinit var receiverStatusStore: ReceiverStatusStore
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
@Inject lateinit var commandQueue: CommandQueue
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var maintenancePlugin: MaintenancePlugin
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var sp: SP
|
||||
|
@ -76,7 +73,7 @@ class KeepAliveWorker(
|
|||
private const val KA_10 = "KeepAlive_10"
|
||||
}
|
||||
|
||||
override fun doWorkAndLog(): Result {
|
||||
override suspend fun doWorkAndLog(): Result {
|
||||
aapsLogger.debug(LTag.CORE, "KeepAlive received from: " + inputData.getString("schedule"))
|
||||
|
||||
// 15 min interval is WorkManager minimum so schedule another instances to have 5 min interval
|
||||
|
@ -110,7 +107,6 @@ class KeepAliveWorker(
|
|||
}
|
||||
lastRun = dateUtil.now()
|
||||
|
||||
Widget.updateWidget(context)
|
||||
localAlertUtils.shortenSnoozeInterval()
|
||||
localAlertUtils.checkStaleBGAlert()
|
||||
checkPump()
|
||||
|
@ -155,8 +151,7 @@ class KeepAliveWorker(
|
|||
var shouldUploadStatus = false
|
||||
if (config.NSCLIENT) return
|
||||
if (config.PUMPCONTROL) shouldUploadStatus = true
|
||||
else if (!(loop as PluginBase).isEnabled() || iobCobCalculator.ads.actualBg() == null)
|
||||
shouldUploadStatus = true
|
||||
else if (!loop.isEnabled() || iobCobCalculator.ads.actualBg() == null) shouldUploadStatus = true
|
||||
else if (dateUtil.isOlderThan(activePlugin.activeAPS.lastAPSRun, 5)) shouldUploadStatus = true
|
||||
if (dateUtil.isOlderThan(lastIobUpload, IOB_UPDATE_FREQUENCY_IN_MINUTES) && shouldUploadStatus) {
|
||||
lastIobUpload = dateUtil.now()
|
||||
|
@ -176,12 +171,22 @@ class KeepAliveWorker(
|
|||
val requestedProfile = ProfileSealed.PS(ps)
|
||||
val runningProfile = profileFunction.getProfile()
|
||||
val lastConnection = pump.lastDataTime()
|
||||
val isStatusOutdated = lastConnection + STATUS_UPDATE_FREQUENCY < dateUtil.now()
|
||||
val now = dateUtil.now()
|
||||
val isStatusOutdated = lastConnection + STATUS_UPDATE_FREQUENCY < now
|
||||
val isBasalOutdated = abs(requestedProfile.getBasal() - pump.baseBasalRate) > pump.pumpDescription.basalStep
|
||||
aapsLogger.debug(LTag.CORE, "Last connection: " + dateUtil.dateAndTimeString(lastConnection))
|
||||
// sometimes keep alive broadcast stops
|
||||
// as as workaround test if readStatus was requested before an alarm is generated
|
||||
if (lastReadStatus != 0L && lastReadStatus > dateUtil.now() - T.mins(5).msecs()) {
|
||||
// Sometimes it can happen that keepalive is not triggered every 5 minutes as it should.
|
||||
// In some cases, it may not even have been started at all.
|
||||
// If these cases aren't handled, false "pump unreachable" alarms can be produced.
|
||||
// Avoid this by checking that (a) readStatus was requested at least once (lastReadStatus
|
||||
// is != 0 in that case) and (b) the last read status request was not too long ago.
|
||||
//
|
||||
// Also, use 5:30 as the threshold for (b) above instead of 5 minutes sharp. The keepalive
|
||||
// checks come in 5 minute intervals, but due to temporal jitter, the interval between the
|
||||
// last read status attempt and the current time can be slightly over 5 minutes (for example,
|
||||
// 300041 milliseconds instead of exactly 300000). Add 30 extra seconds to allow for
|
||||
// plenty of tolerance.
|
||||
if (lastReadStatus != 0L && (now - lastReadStatus).coerceIn(minimumValue = 0, maximumValue = null) <= T.secs(5 * 60 + 30).msecs()) {
|
||||
localAlertUtils.checkPumpUnreachableAlarm(lastConnection, isStatusOutdated, loop.isDisconnected)
|
||||
}
|
||||
if (loop.isDisconnected) {
|
||||
|
@ -189,10 +194,10 @@ class KeepAliveWorker(
|
|||
} else if (runningProfile == null || ((!pump.isThisProfileSet(requestedProfile) || !requestedProfile.isEqual(runningProfile)) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE))) {
|
||||
rxBus.send(EventProfileSwitchChanged())
|
||||
} else if (isStatusOutdated && !pump.isBusy()) {
|
||||
lastReadStatus = dateUtil.now()
|
||||
lastReadStatus = now
|
||||
commandQueue.readStatus(rh.gs(info.nightscout.core.ui.R.string.keepalive_status_outdated), null)
|
||||
} else if (isBasalOutdated && !pump.isBusy()) {
|
||||
lastReadStatus = dateUtil.now()
|
||||
lastReadStatus = now
|
||||
commandQueue.readStatus(rh.gs(info.nightscout.core.ui.R.string.keepalive_basal_outdated), null)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,17 @@ import android.os.SystemClock
|
|||
import androidx.work.Data
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkContinuation
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.core.graph.OverviewData
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
import info.nightscout.core.utils.receivers.DataWorkerStorage
|
||||
import info.nightscout.core.utils.worker.then
|
||||
import info.nightscout.core.workflow.CalculationWorkflow
|
||||
import info.nightscout.core.workflow.CalculationWorkflow.Companion.JOB
|
||||
import info.nightscout.core.workflow.CalculationWorkflow.Companion.MAIN_CALCULATION
|
||||
import info.nightscout.core.workflow.CalculationWorkflow.Companion.PASS
|
||||
import info.nightscout.interfaces.iob.IobCobCalculator
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
|
@ -42,6 +43,7 @@ import info.nightscout.workflow.PrepareTemporaryTargetDataWorker
|
|||
import info.nightscout.workflow.PrepareTreatmentsDataWorker
|
||||
import info.nightscout.workflow.UpdateGraphWorker
|
||||
import info.nightscout.workflow.UpdateIobCobSensWorker
|
||||
import info.nightscout.workflow.UpdateWidgetWorker
|
||||
import info.nightscout.workflow.iob.IobCobOref1Worker
|
||||
import info.nightscout.workflow.iob.IobCobOrefWorker
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
|
@ -156,7 +158,7 @@ class CalculationWorkflowImpl @Inject constructor(
|
|||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.setInputData(Data.Builder().putString(JOB, job).putInt(PASS, CalculationWorkflow.ProgressData.DRAW_BG.pass).build())
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
|
@ -176,7 +178,7 @@ class CalculationWorkflowImpl @Inject constructor(
|
|||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.setInputData(Data.Builder().putString(JOB, job).putInt(PASS, CalculationWorkflow.ProgressData.DRAW_TT.pass).build())
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
|
@ -196,8 +198,9 @@ class CalculationWorkflowImpl @Inject constructor(
|
|||
.build()
|
||||
)
|
||||
.then(
|
||||
job == MAIN_CALCULATION,
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.setInputData(Data.Builder().putString(JOB, job).putInt(PASS, CalculationWorkflow.ProgressData.DRAW_IOB.pass).build())
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
|
@ -206,6 +209,10 @@ class CalculationWorkflowImpl @Inject constructor(
|
|||
.setInputData(dataWorkerStorage.storeInputData(InvokeLoopWorker.InvokeLoopData(cause)))
|
||||
.build()
|
||||
)
|
||||
.then(
|
||||
job == MAIN_CALCULATION,
|
||||
OneTimeWorkRequest.Builder(UpdateWidgetWorker::class.java).build()
|
||||
)
|
||||
.then(
|
||||
job == MAIN_CALCULATION,
|
||||
OneTimeWorkRequest.Builder(PreparePredictionsWorker::class.java)
|
||||
|
@ -213,17 +220,13 @@ class CalculationWorkflowImpl @Inject constructor(
|
|||
.build()
|
||||
)
|
||||
.then(
|
||||
job == MAIN_CALCULATION,
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putString(JOB, job).build())
|
||||
.setInputData(Data.Builder().putString(JOB, job).putInt(PASS, CalculationWorkflow.ProgressData.DRAW_FINAL.pass).build())
|
||||
.build()
|
||||
)
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
fun WorkContinuation.then(shouldAdd: Boolean, work: OneTimeWorkRequest): WorkContinuation =
|
||||
if (shouldAdd) then(work) else this
|
||||
|
||||
private fun runOnEventTherapyEventChange() {
|
||||
WorkManager.getInstance(context)
|
||||
.beginUniqueWork(
|
||||
|
@ -234,6 +237,7 @@ class CalculationWorkflowImpl @Inject constructor(
|
|||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putInt(PASS, CalculationWorkflow.ProgressData.DRAW_FINAL.pass).build())
|
||||
.build()
|
||||
)
|
||||
.enqueue()
|
||||
|
@ -255,6 +259,7 @@ class CalculationWorkflowImpl @Inject constructor(
|
|||
)
|
||||
.then(
|
||||
OneTimeWorkRequest.Builder(UpdateGraphWorker::class.java)
|
||||
.setInputData(Data.Builder().putInt(PASS, CalculationWorkflow.ProgressData.DRAW_FINAL.pass).build())
|
||||
.build()
|
||||
)
|
||||
.enqueue()
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
package info.nightscout.androidaps.workflow
|
||||
|
||||
import info.nightscout.interfaces.workflow.WorkerClasses
|
||||
import info.nightscout.plugins.general.food.FoodPlugin
|
||||
import info.nightscout.plugins.profile.ProfilePlugin
|
||||
import info.nightscout.source.NSClientSourcePlugin
|
||||
import javax.inject.Inject
|
||||
|
||||
class WorkerClassesImpl @Inject constructor(): WorkerClasses{
|
||||
class WorkerClassesImpl @Inject constructor() : WorkerClasses {
|
||||
|
||||
override val nsClientSourceWorker = NSClientSourcePlugin.NSClientSourceWorker::class.java
|
||||
override val nsProfileWorker = ProfilePlugin.NSProfileWorker::class.java
|
||||
override val foodWorker = FoodPlugin.FoodWorker::class.java
|
||||
//override val nsProfileWorker = ProfilePlugin.NSProfileWorker::class.java
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
<string name="reloadprofile">Презареди профил</string>
|
||||
<string name="correctionbous">Корекция</string>
|
||||
<string name="ns_upload_only">(ОПАСНО ЗА ДЕАКТИВИРАНЕ) Само качвай данни в NS</string>
|
||||
<string name="ns_upload_only_summary">Само каване в NS (изключи синхронизиране). Може да спре данните за КЗ, освен ако не е избран локален източник като xDrip +. Не е ефективно за профила, освен ако не ползвате NS профил.\n!!! ВНИМАНИЕ !!! Деактивирането на тази опция може да причини проблеми и предозиране на инсулин, ако някой от Вашите компоненти (AAPS, NS, xDrip +) е неправилно конфигуриран. Внимателно гледайте, ако данните, показани от AAPS съответстват на състоянието на помпата!</string>
|
||||
<string name="ns_upload_only_summary">Само качване в NS (изключи синхронизиране). Може да спре данните за КЗ, освен ако не е избран локален източник като xDrip +. Не е ефективно за профила, освен ако не ползвате NS профил.\n!!! ВНИМАНИЕ !!! Деактивирането на тази опция може да причини проблеми и предозиране с инсулин, ако някой от Вашите компоненти (AAPS, NS, xDrip +) е неправилно конфигуриран. Внимателно гледайте, ако данните, показани от AAPS съответстват на състоянието на помпата!</string>
|
||||
<string name="wear">Часовник</string>
|
||||
<string name="nav_about">За приложението</string>
|
||||
<string name="smscommunicator_missingphonestatepermission">Липсва разрешение до данни от телефона</string>
|
||||
|
@ -45,10 +45,16 @@
|
|||
<string name="chartmenu">Меню на графиката</string>
|
||||
<string name="authorizationfailed">Удостоверяването неуспешно</string>
|
||||
<string name="copytolocalprofile_invalid">Създаването на профила невъзможно. Профилът е невалиден.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Не убивай приложението?</string>
|
||||
<string name="fabric_upload_disabled">Качването на данни за проблеми е забранено!(Fabric)</string>
|
||||
<string name="clear_filter">Премахни филтъра</string>
|
||||
<string name="cannula">Канюла</string>
|
||||
<string name="email_address">Електронна поща</string>
|
||||
<string name="remove_bg_readings">Премахване показанията нa КЗ</string>
|
||||
<string name="identification_not_set">Идентификацията не е зададена в режим на разработчик</string>
|
||||
<string name="a11y_dialog">диалог</string>
|
||||
<!-- WEAR OS-->
|
||||
<string name="wear_unknown_action_string">Неизвестна команда:</string>
|
||||
<string name="remove_selected_items">Премахнете избраните елементи</string>
|
||||
<string name="count_selected">%1$d избрано</string>
|
||||
<string name="sort_label">Сортиране</string>
|
||||
<string name="search">Търсене</string>
|
||||
</resources>
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
<string name="chartmenu">Menú gràfica</string>
|
||||
<string name="authorizationfailed">L\'autorització ha fallat</string>
|
||||
<string name="copytolocalprofile_invalid">No s\'ha pogut crear el perfil local. Perfil no vàlid.</string>
|
||||
<string name="cta_dont_kill_my_app_info">No matar la meva app?</string>
|
||||
<string name="fabric_upload_disabled">Enviament de logs d\'error desactivat!</string>
|
||||
<string name="clear_filter">Netejar filtres</string>
|
||||
<string name="cannula">Cànula</string>
|
||||
<string name="email_address">Correu electrònic</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Možnosti grafu</string>
|
||||
<string name="authorizationfailed">Autorizace selhala</string>
|
||||
<string name="copytolocalprofile_invalid">Nelze vytvořit profil. Profil je neplatný.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Nezabíjet mou aplikaci?</string>
|
||||
<string name="fabric_upload_disabled">Nahrávání protokolů o pádech zakázáno!</string>
|
||||
<string name="clear_filter">Vymazat filtr</string>
|
||||
<string name="cannula">Kanyla</string>
|
||||
<string name="email_address">E-mailová adresa</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Diagrammenu</string>
|
||||
<string name="authorizationfailed">Godkendelse mislykkedes</string>
|
||||
<string name="copytolocalprofile_invalid">Kunne ikke oprette profil. Profilen er ugyldig.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Luk ikke min app?</string>
|
||||
<string name="fabric_upload_disabled">Upload af Crash logs deaktiveret!</string>
|
||||
<string name="clear_filter">Nulstil filter</string>
|
||||
<string name="cannula">Kanyle</string>
|
||||
<string name="email_address">E-mail adresse</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Diagrammmenü</string>
|
||||
<string name="authorizationfailed">Autorisierung fehlgeschlagen</string>
|
||||
<string name="copytolocalprofile_invalid">Profil kann nicht erstellt werden. Profil ist ungültig.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Don\'t kill my app?</string>
|
||||
<string name="fabric_upload_disabled">Hochladen von Crash-Protokollen deaktiviert!</string>
|
||||
<string name="clear_filter">Filter löschen</string>
|
||||
<string name="cannula">Kanüle</string>
|
||||
<string name="email_address">E‐Mail‐Adresse</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Menú gráfico</string>
|
||||
<string name="authorizationfailed">Ha fallado la autorización</string>
|
||||
<string name="copytolocalprofile_invalid">No se puede crear el perfil. El perfil es inválido.</string>
|
||||
<string name="cta_dont_kill_my_app_info">¿No matar mi aplicación?</string>
|
||||
<string name="fabric_upload_disabled">¡Carga de registros de errores desactivada!</string>
|
||||
<string name="clear_filter">Borrar filtro</string>
|
||||
<string name="cannula">Cánula</string>
|
||||
<string name="email_address">Dirección de Correo Electrónico</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Menu Graph</string>
|
||||
<string name="authorizationfailed">Echec de l\'authentification</string>
|
||||
<string name="copytolocalprofile_invalid">Impossible de créer le profil. Le profil est invalide.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Garder l\'appli en arrière plan ?</string>
|
||||
<string name="fabric_upload_disabled">Téléchargement logs crashs désactivé!</string>
|
||||
<string name="clear_filter">Effacer le filtre</string>
|
||||
<string name="cannula">Canule</string>
|
||||
<string name="email_address">Adresse e-mail</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Menu grafico</string>
|
||||
<string name="authorizationfailed">Autorizzazione fallita</string>
|
||||
<string name="copytolocalprofile_invalid">Impossibile creare il profilo. Il profilo non è valido.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Non terminare l\'app?</string>
|
||||
<string name="fabric_upload_disabled">Caricamento log dei crash disabilitato!</string>
|
||||
<string name="clear_filter">Cancella filtro</string>
|
||||
<string name="cannula">Cannula</string>
|
||||
<string name="email_address">Indirizzo email</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">תפריט תרשים</string>
|
||||
<string name="authorizationfailed">ההרשאה נכשלה</string>
|
||||
<string name="copytolocalprofile_invalid">לא ניתן ליצור פרופיל מקומי. הפרופיל אינו חוקי.</string>
|
||||
<string name="cta_dont_kill_my_app_info">איך לא להשבית את האפליקציה שלי?</string>
|
||||
<string name="fabric_upload_disabled">העלאת רשומות קריסה מושבתת!</string>
|
||||
<string name="clear_filter">נקה סינון</string>
|
||||
<string name="cannula">צינורית</string>
|
||||
<string name="email_address">כתובת דוא\"ל</string>
|
||||
|
|
|
@ -42,8 +42,6 @@
|
|||
<string name="clearqueueconfirm">대기열을 삭제하시겠습니까? 대기열에 있는 모든 데이터가 삭제됩니다!</string>
|
||||
<string name="chartmenu">차트 메뉴</string>
|
||||
<string name="authorizationfailed">인증 실패</string>
|
||||
<string name="cta_dont_kill_my_app_info">앱이 종료되지 않도록 합니다?</string>
|
||||
<string name="fabric_upload_disabled">충돌 로그 업로드가 작동하지 않습니다.</string>
|
||||
<string name="clear_filter">필터 지우기</string>
|
||||
<string name="cannula">캐뉼라</string>
|
||||
<string name="email_address">이메일 주소</string>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<string name="ns_announcements">Sukurkite pranešimus iš NS perspėjimų</string>
|
||||
<string name="ns_alarm_stale_data_value_label">Seni duomenys, riba [min]</string>
|
||||
<string name="ns_alarm_urgent_stale_data_value_label">Kritiškai seni duomenys, riba [min]</string>
|
||||
<string name="sensitivity_warning">Įjungę Autosens funkciją nepamirškite įvedinėti visus valgomus angliavandenius. To nedarant, angliavandenių sukeliami gliukozės svyravimai bus klaidingai identifikuojami kaip jautrumo pasikeitimai!</string>
|
||||
<string name="sensitivity_warning">Įjungę Autosens funkciją nepamirškite įvedinėti visus valgomus angliavandenius. To nedarant, angliavandenių sukeliami glikemijos svyravimai bus klaidingai identifikuojami kaip jautrumo pasikeitimai!</string>
|
||||
<string name="notloadedplugins">Ne visi profiliai įkelti!</string>
|
||||
<string name="valuesnotstored">Reikšmės neišsaugotos!</string>
|
||||
<string name="invalid">KLAIDA</string>
|
||||
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Grafiko meniu</string>
|
||||
<string name="authorizationfailed">Autorizacija nepavyko</string>
|
||||
<string name="copytolocalprofile_invalid">Nepavyksta sukurti profilio. Profilis neteisingas.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Don\'t kill my app?</string>
|
||||
<string name="fabric_upload_disabled">Sutrikimų žurnalo įrašų įkėlimas išjungtas!</string>
|
||||
<string name="clear_filter">Valyti filtrą</string>
|
||||
<string name="cannula">Kaniulė</string>
|
||||
<string name="email_address">El. pašto adresas</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Grafiek menu</string>
|
||||
<string name="authorizationfailed">Autorisatie mislukt</string>
|
||||
<string name="copytolocalprofile_invalid">Kan profiel niet aanmaken. Profiel is ongeldig.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Don\'t kill my app?</string>
|
||||
<string name="fabric_upload_disabled">Upload van crashrapporten is uitgeschakeld!</string>
|
||||
<string name="clear_filter">Verwijder filter</string>
|
||||
<string name="cannula">Canule</string>
|
||||
<string name="email_address">E-mailadres</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Diagram meny</string>
|
||||
<string name="authorizationfailed">Autentisering feilet</string>
|
||||
<string name="copytolocalprofile_invalid">Klarte ikke å opprette profil. Profilen er ikke gyldig.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Avslutte app?</string>
|
||||
<string name="fabric_upload_disabled">Opplast av krasj logger er deaktivert!</string>
|
||||
<string name="clear_filter">Nullstill filtre</string>
|
||||
<string name="cannula">Kanyle</string>
|
||||
<string name="email_address">E-postadresse</string>
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
<string name="enable_carbs_req_alert">Alarm gdy wymagane jest podanie węglowodanów</string>
|
||||
<string name="open_navigation">Otwórz menu</string>
|
||||
<string name="close_navigation">Zamknij menu</string>
|
||||
<string name="remove_items">Usuń elementy</string>
|
||||
<string name="sort_items">Sortuj elementy</string>
|
||||
<string name="error_adding_treatment_title">Niekompletne dane leczenie</string>
|
||||
<string name="error_adding_treatment_message">Leczenie (insulina: %1$.2f, węglowodany: %2$d, czas:%3$s) nie mogą być dodane. Sprawdź i dodaj ręcznie rekord w razie potrzeby.</string>
|
||||
<string name="generated_ecarbs_note">eWęgle: %1$d g (%2$d h), Opóźnienie: %3$d m</string>
|
||||
|
@ -43,14 +45,16 @@
|
|||
<string name="chartmenu">Menu wykresu</string>
|
||||
<string name="authorizationfailed">Autoryzacja nie powiodła się</string>
|
||||
<string name="copytolocalprofile_invalid">Nie można utworzyć profilu. Profil jest nieprawidłowy.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Nie zabij mojej aplikacji?</string>
|
||||
<string name="fabric_upload_disabled">Przesyłanie dzienników awarii jest wyłączone!</string>
|
||||
<string name="clear_filter">Wyczyść filtr</string>
|
||||
<string name="cannula">Kaniula</string>
|
||||
<string name="email_address">Adres e-mail</string>
|
||||
<string name="remove_bg_readings">Usuń odczyty glikemii</string>
|
||||
<string name="identification_not_set">Identyfikator nie jest ustawiony w trybie dev</string>
|
||||
<string name="a11y_dialog">dialog</string>
|
||||
<!-- WEAR OS-->
|
||||
<string name="wear_unknown_action_string">Nieznana akcja:</string>
|
||||
<string name="remove_selected_items">Usuń wybrane pozycje</string>
|
||||
<string name="count_selected">Wybrany %1$d</string>
|
||||
<string name="sort_label">Sortuj</string>
|
||||
<string name="search">Szukaj</string>
|
||||
</resources>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Menu do Gráfico</string>
|
||||
<string name="authorizationfailed">Falha na autorização</string>
|
||||
<string name="copytolocalprofile_invalid">Não foi possível criar o perfil. Perfil inválido.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Não encerre meu aplicativo?</string>
|
||||
<string name="fabric_upload_disabled">Envio de logs de erro desativado!</string>
|
||||
<string name="clear_filter">Limpar filtro</string>
|
||||
<string name="cannula">Cânula</string>
|
||||
<string name="email_address">Endereço de e-mail</string>
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
<string name="chartmenu">Menu do Gráfico</string>
|
||||
<string name="authorizationfailed">Falha na autorização</string>
|
||||
<string name="copytolocalprofile_invalid">Não é possível criar o perfil. O perfil é inválido.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Não encerre minha app?</string>
|
||||
<string name="fabric_upload_disabled">Envio de registos de erro desativado!</string>
|
||||
<string name="clear_filter">Limpar filtros</string>
|
||||
<string name="cannula">Cânula</string>
|
||||
<string name="email_address">Endereço de email</string>
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
<string name="chartmenu">Meniu diagramă</string>
|
||||
<string name="authorizationfailed">Autorizarea a eșuat</string>
|
||||
<string name="copytolocalprofile_invalid">Nu se poate crea profilul. Profilul este invalid.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Nu-mi opri aplicația?</string>
|
||||
<string name="fabric_upload_disabled">Încărcarea jurnalelor de erori este dezactivata!</string>
|
||||
<string name="clear_filter">Șterge filtru</string>
|
||||
<string name="cannula">Canula</string>
|
||||
<string name="email_address">Adresă de e-mail</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Меню графика</string>
|
||||
<string name="authorizationfailed">Ошибка авторизации</string>
|
||||
<string name="copytolocalprofile_invalid">Не удается создать локальный профиль. Настройки профиля неправильны.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Не закрывать приложение?</string>
|
||||
<string name="fabric_upload_disabled">Загрузка журналов сбоя на сервер отключена!</string>
|
||||
<string name="clear_filter">Очистить фильтр</string>
|
||||
<string name="cannula">Катетер помпы</string>
|
||||
<string name="email_address">Адрес электронной почты</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Grafové menu</string>
|
||||
<string name="authorizationfailed">Autorizácia zlyhala</string>
|
||||
<string name="copytolocalprofile_invalid">Nie je možné vytvoriť lokálny profil. Profil je neplatný.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Nepotláčať moju aplikáciu?</string>
|
||||
<string name="fabric_upload_disabled">Odosielanie protokolov o zlyhaní je zakázané!</string>
|
||||
<string name="clear_filter">Vyčistiť filter</string>
|
||||
<string name="cannula">Kanyla</string>
|
||||
<string name="email_address">Emailová adresa</string>
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
<string name="chartmenu">Diagrammeny</string>
|
||||
<string name="authorizationfailed">Behörighetskontroll misslyckades</string>
|
||||
<string name="copytolocalprofile_invalid">Kan inte att skapa profilen. Profilen är felaktig.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Döda inte min app?</string>
|
||||
<string name="fabric_upload_disabled">Uppladdning av kraschloggar inaktiverad!</string>
|
||||
<string name="clear_filter">Rensa filter</string>
|
||||
<string name="cannula">Kanyl</string>
|
||||
<string name="email_address">E-postadress</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">Grafik menüsü</string>
|
||||
<string name="authorizationfailed">Yetkilendirme başarısız oldu</string>
|
||||
<string name="copytolocalprofile_invalid">Profil oluşturulamıyor. Profil geçersiz.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Uygulamamı devre dışı bırakma?</string>
|
||||
<string name="fabric_upload_disabled">Çökme günlükleri yükleme devre dışı bırakıldı!</string>
|
||||
<string name="clear_filter">Filtreyi temizle</string>
|
||||
<string name="cannula">Kanül</string>
|
||||
<string name="email_address">E-posta adresi</string>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
<string name="chartmenu">图表菜单</string>
|
||||
<string name="authorizationfailed">授权失败</string>
|
||||
<string name="copytolocalprofile_invalid">无法创建配置文件。配置文件无效。</string>
|
||||
<string name="cta_dont_kill_my_app_info">不要杀死我的应用程序?</string>
|
||||
<string name="fabric_upload_disabled">已禁用崩溃日志上传!</string>
|
||||
<string name="clear_filter">清除筛选</string>
|
||||
<string name="cannula">输注导管</string>
|
||||
<string name="email_address">电子邮件地址</string>
|
||||
|
|
|
@ -78,8 +78,6 @@
|
|||
<string name="chartmenu">Chart menu</string>
|
||||
<string name="authorizationfailed">Authorization failed</string>
|
||||
<string name="copytolocalprofile_invalid">Unable to create profile. Profile is invalid.</string>
|
||||
<string name="cta_dont_kill_my_app_info">Don\'t kill my app?</string>
|
||||
<string name="fabric_upload_disabled">Crash logs upload disabled!</string>
|
||||
<string name="clear_filter">Clear filter</string>
|
||||
<string name="cannula">Cannula</string>
|
||||
<string name="email_address">Email address</string>
|
||||
|
|
|
@ -11,6 +11,7 @@ import info.nightscout.androidaps.insight.database.InsightDatabaseDao
|
|||
import info.nightscout.androidaps.insight.database.InsightDbHelper
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
import info.nightscout.database.impl.AppRepository
|
||||
import info.nightscout.interfaces.ApsMode
|
||||
import info.nightscout.implementation.iob.GlucoseStatusProviderImpl
|
||||
import info.nightscout.interfaces.bgQualityCheck.BgQualityCheck
|
||||
import info.nightscout.interfaces.constraints.Constraint
|
||||
|
@ -274,13 +275,13 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
|
|||
// 2x Safety & Objectives
|
||||
@Test
|
||||
fun isClosedLoopAllowedTest() {
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("closed")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.CLOSED.name)
|
||||
objectivesPlugin.objectives[Objectives.MAXIOB_ZERO_CL_OBJECTIVE].startedOn = 0
|
||||
var c: Constraint<Boolean> = constraintChecker.isClosedLoopAllowed()
|
||||
aapsLogger.debug("Reason list: " + c.reasonList.toString())
|
||||
// Assertions.assertTrue(c.reasonList[0].toString().contains("Closed loop is disabled")) // Safety & Objectives
|
||||
Assertions.assertEquals(false, c.value())
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("open")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.OPEN.name)
|
||||
c = constraintChecker.isClosedLoopAllowed()
|
||||
Assertions.assertTrue(c.reasonList[0].contains("Closed loop mode disabled in preferences")) // Safety & Objectives
|
||||
// Assertions.assertEquals(3, c.reasonList.size) // 2x Safety & Objectives
|
||||
|
@ -323,7 +324,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
|
|||
openAPSSMBPlugin.setPluginEnabled(PluginType.APS, true)
|
||||
objectivesPlugin.objectives[Objectives.SMB_OBJECTIVE].startedOn = 0
|
||||
`when`(sp.getBoolean(info.nightscout.plugins.aps.R.string.key_use_smb, false)).thenReturn(false)
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("open")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.OPEN.name)
|
||||
// `when`(constraintChecker.isClosedLoopAllowed()).thenReturn(Constraint(true))
|
||||
val c = constraintChecker.isSMBModeEnabled()
|
||||
Assertions.assertEquals(true, c.reasonList.size == 3) // 2x Safety & Objectives
|
||||
|
@ -430,7 +431,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
|
|||
@Test
|
||||
fun iobAMAShouldBeLimited() {
|
||||
// No limit by default
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("closed")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.CLOSED.name)
|
||||
`when`(sp.getDouble(info.nightscout.plugins.aps.R.string.key_openapsma_max_iob, 1.5)).thenReturn(1.5)
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_age, "")).thenReturn("teenage")
|
||||
openAPSAMAPlugin.setPluginEnabled(PluginType.APS, true)
|
||||
|
@ -446,7 +447,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
|
|||
@Test
|
||||
fun iobSMBShouldBeLimited() {
|
||||
// No limit by default
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("closed")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.CLOSED.name)
|
||||
`when`(sp.getDouble(info.nightscout.plugins.aps.R.string.key_openapssmb_max_iob, 3.0)).thenReturn(3.0)
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_age, "")).thenReturn("teenage")
|
||||
openAPSSMBPlugin.setPluginEnabled(PluginType.APS, true)
|
||||
|
|
|
@ -7,6 +7,7 @@ import dagger.android.HasAndroidInjector
|
|||
import info.nightscout.androidaps.TestBase
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
import info.nightscout.database.impl.AppRepository
|
||||
import info.nightscout.interfaces.ApsMode
|
||||
import info.nightscout.interfaces.Config
|
||||
import info.nightscout.interfaces.configBuilder.RunningConfiguration
|
||||
import info.nightscout.interfaces.constraints.Constraints
|
||||
|
@ -70,7 +71,7 @@ class LoopPluginTest : TestBase() {
|
|||
fun testPluginInterface() {
|
||||
`when`(rh.gs(info.nightscout.core.ui.R.string.loop)).thenReturn("Loop")
|
||||
`when`(rh.gs(info.nightscout.plugins.aps.R.string.loop_shortname)).thenReturn("LOOP")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("closed")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.CLOSED.name)
|
||||
val pumpDescription = PumpDescription()
|
||||
`when`(virtualPumpPlugin.pumpDescription).thenReturn(pumpDescription)
|
||||
Assert.assertEquals(LoopFragment::class.java.name, loopPlugin.pluginDescription.fragmentClass)
|
||||
|
|
|
@ -6,7 +6,9 @@ import info.nightscout.androidaps.TestBase
|
|||
import info.nightscout.configuration.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.interfaces.logging.UserEntryLogger
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.interfaces.protection.ProtectionCheck
|
||||
import info.nightscout.interfaces.pump.PumpSync
|
||||
import info.nightscout.interfaces.ui.UiInteraction
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
|
@ -21,6 +23,8 @@ class ConfigBuilderPluginTest : TestBase() {
|
|||
@Mock lateinit var activePlugin: ActivePlugin
|
||||
@Mock lateinit var uel: UserEntryLogger
|
||||
@Mock lateinit var pumpSync: PumpSync
|
||||
@Mock lateinit var protectionCheck: ProtectionCheck
|
||||
@Mock lateinit var uiInteraction: UiInteraction
|
||||
|
||||
private lateinit var configBuilderPlugin: ConfigBuilderPlugin
|
||||
|
||||
|
@ -33,6 +37,6 @@ class ConfigBuilderPluginTest : TestBase() {
|
|||
|
||||
@BeforeEach
|
||||
fun prepareMock() {
|
||||
configBuilderPlugin = ConfigBuilderPlugin(injector, aapsLogger, rh, sp, RxBus(aapsSchedulers, aapsLogger), activePlugin, uel, pumpSync)
|
||||
configBuilderPlugin = ConfigBuilderPlugin(injector, aapsLogger, rh, sp, RxBus(aapsSchedulers, aapsLogger), activePlugin, uel, pumpSync, protectionCheck, uiInteraction)
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import dagger.android.HasAndroidInjector
|
|||
import info.nightscout.androidaps.HardLimitsMock
|
||||
import info.nightscout.androidaps.TestBaseWithProfile
|
||||
import info.nightscout.database.impl.AppRepository
|
||||
import info.nightscout.interfaces.ApsMode
|
||||
import info.nightscout.interfaces.Constants
|
||||
import info.nightscout.interfaces.bgQualityCheck.BgQualityCheck
|
||||
import info.nightscout.interfaces.constraints.Constraint
|
||||
|
@ -98,7 +99,7 @@ class SafetyPluginTest : TestBaseWithProfile() {
|
|||
|
||||
@Test
|
||||
fun disabledEngineeringModeShouldLimitClosedLoop() {
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("closed")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.CLOSED.name)
|
||||
`when`(config.isEngineeringModeOrRelease()).thenReturn(false)
|
||||
var c = Constraint(true)
|
||||
c = safetyPlugin.isClosedLoopAllowed(c)
|
||||
|
@ -108,7 +109,7 @@ class SafetyPluginTest : TestBaseWithProfile() {
|
|||
|
||||
@Test
|
||||
fun setOpenLoopInPreferencesShouldLimitClosedLoop() {
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("open")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.OPEN.name)
|
||||
var c = Constraint(true)
|
||||
c = safetyPlugin.isClosedLoopAllowed(c)
|
||||
Assertions.assertTrue(c.getReasons(aapsLogger).contains("Closed loop mode disabled in preferences"))
|
||||
|
@ -278,7 +279,7 @@ Safety: Limiting max basal rate to 500.00 U/h because of pump limit
|
|||
openAPSSMBPlugin.setPluginEnabled(PluginType.APS, true)
|
||||
//`when`(openAPSSMBPlugin.isEnabled()).thenReturn(true)
|
||||
//`when`(openAPSAMAPlugin.isEnabled()).thenReturn(false)
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, "open")).thenReturn("lgs")
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_aps_mode, ApsMode.OPEN.name)).thenReturn(ApsMode.LGS.name)
|
||||
`when`(sp.getDouble(info.nightscout.plugins.aps.R.string.key_openapsma_max_iob, 1.5)).thenReturn(1.5)
|
||||
`when`(sp.getDouble(info.nightscout.plugins.aps.R.string.key_openapssmb_max_iob, 3.0)).thenReturn(3.0)
|
||||
`when`(sp.getString(info.nightscout.core.utils.R.string.key_age, "")).thenReturn("teenage")
|
||||
|
|
|
@ -7,7 +7,6 @@ import info.nightscout.core.pump.toHtml
|
|||
import info.nightscout.interfaces.pump.PumpEnactResult
|
||||
import info.nightscout.plugins.aps.loop.extensions.json
|
||||
import info.nightscout.pump.virtual.extensions.toText
|
||||
import info.nightscout.plugins.sync.nsShared.extensions.log
|
||||
import org.json.JSONObject
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
|
@ -109,15 +108,6 @@ class PumpEnactResultTest : TestBaseWithProfile() {
|
|||
Assertions.assertEquals(true, per.queued)
|
||||
}
|
||||
|
||||
@Test fun logTest() {
|
||||
val per = PumpEnactResult(injector)
|
||||
|
||||
Assertions.assertEquals(
|
||||
"Success: false Enacted: false Comment: Duration: -1 Absolute: -1.0 Percent: -1 IsPercent: false IsTempCancel: false bolusDelivered: 0.0 Queued: false",
|
||||
per.log()
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun toStringTest() {
|
||||
var per = PumpEnactResult(injector).enacted(true).bolusDelivered(10.0).comment("AAA")
|
||||
Assertions.assertEquals(
|
||||
|
|
28
build.gradle
28
build.gradle
|
@ -2,37 +2,37 @@
|
|||
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.7.22'
|
||||
kotlin_version = '1.8.10'
|
||||
core_version = '1.9.0'
|
||||
rxjava_version = '3.1.5'
|
||||
rxjava_version = '3.1.6'
|
||||
rxandroid_version = '3.0.2'
|
||||
rxkotlin_version = '3.0.1'
|
||||
room_version = '2.4.3'
|
||||
room_version = '2.5.0'
|
||||
lifecycle_version = '2.5.1'
|
||||
dagger_version = '2.44.2'
|
||||
dagger_version = '2.45'
|
||||
coroutines_version = '1.6.4'
|
||||
activity_version = '1.6.1'
|
||||
fragmentktx_version = '1.5.5'
|
||||
ormLite_version = '4.46'
|
||||
gson_version = '2.10'
|
||||
gson_version = '2.10.1'
|
||||
nav_version = '2.5.3'
|
||||
appcompat_version = '1.5.1'
|
||||
material_version = '1.7.0'
|
||||
appcompat_version = '1.6.1'
|
||||
material_version = '1.8.0'
|
||||
gridlayout_version = '1.0.0'
|
||||
constraintlayout_version = '2.1.4'
|
||||
preferencektx_version = '1.2.0'
|
||||
commonslang3_version = '3.12.0'
|
||||
commonscodec_version = '1.15'
|
||||
jodatime_version = '2.10.14'
|
||||
work_version = '2.7.1'
|
||||
tink_version = '1.7.0'
|
||||
work_version = '2.8.0'
|
||||
tink_version = '1.8.0'
|
||||
json_version = '20220320'
|
||||
serialization_version = '1.4.1'
|
||||
joda_version = '2.12.1.1'
|
||||
swipe_version = '1.1.0'
|
||||
|
||||
junit_version = '4.13.2'
|
||||
junit_jupiter_version = '5.9.1'
|
||||
junit_jupiter_version = '5.9.2'
|
||||
mockito_version = '4.6.1'
|
||||
dexmaker_version = '1.2'
|
||||
retrofit2_version = '2.9.0'
|
||||
|
@ -58,9 +58,9 @@ buildscript {
|
|||
maven { url "https://plugins.gradle.org/m2/" } // jacoco 0.2
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.1'
|
||||
classpath 'com.android.tools.build:gradle:7.4.1'
|
||||
classpath 'com.google.gms:google-services:4.3.14'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.4'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
@ -76,8 +76,8 @@ buildscript {
|
|||
plugins {
|
||||
// Test Gradle build, keep disabled under normal circumstances
|
||||
// id "com.osacky.doctor" version "0.8.1"
|
||||
id "org.jlleitschuh.gradle.ktlint" version "11.0.0"
|
||||
id 'org.barfuin.gradle.jacocolog' version '2.0.0'
|
||||
id "org.jlleitschuh.gradle.ktlint" version "11.2.0"
|
||||
id 'org.barfuin.gradle.jacocolog' version '3.1.0'
|
||||
id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false
|
||||
}
|
||||
|
||||
|
|
1
connectwsa.bat
Normal file
1
connectwsa.bat
Normal file
|
@ -0,0 +1 @@
|
|||
adb connect 127.0.0.1:58526
|
|
@ -16,16 +16,18 @@ import info.nightscout.core.graph.data.ScaledDataPoint
|
|||
import info.nightscout.database.entities.GlucoseValue
|
||||
import info.nightscout.database.entities.TemporaryTarget
|
||||
import info.nightscout.interfaces.aps.AutosensData
|
||||
import info.nightscout.interfaces.aps.AutosensDataStore
|
||||
import info.nightscout.interfaces.iob.CobInfo
|
||||
import info.nightscout.interfaces.iob.InMemoryGlucoseValue
|
||||
import info.nightscout.interfaces.iob.IobCobCalculator
|
||||
import info.nightscout.interfaces.iob.IobTotal
|
||||
|
||||
interface OverviewData {
|
||||
|
||||
var rangeToDisplay: Int // for graph
|
||||
var toTime: Long
|
||||
var fromTime: Long
|
||||
var endTime: Long
|
||||
var toTime: Long // current time rounded up to 1 hour
|
||||
var fromTime: Long // toTime - range
|
||||
var endTime: Long // toTime + predictions
|
||||
|
||||
fun reset()
|
||||
fun initRange()
|
||||
|
@ -45,12 +47,12 @@ interface OverviewData {
|
|||
* BG
|
||||
*/
|
||||
|
||||
val lastBg: GlucoseValue?
|
||||
val isLow: Boolean
|
||||
val isHigh: Boolean
|
||||
@ColorInt fun lastBgColor(context: Context?): Int
|
||||
val lastBgDescription: String
|
||||
val isActualBg: Boolean
|
||||
fun lastBg(autosensDataStore: AutosensDataStore): InMemoryGlucoseValue?
|
||||
fun isLow(autosensDataStore: AutosensDataStore): Boolean
|
||||
fun isHigh(autosensDataStore: AutosensDataStore): Boolean
|
||||
@ColorInt fun lastBgColor(context: Context?, autosensDataStore: AutosensDataStore): Int
|
||||
fun lastBgDescription(autosensDataStore: AutosensDataStore): String
|
||||
fun isActualBg(autosensDataStore: AutosensDataStore): Boolean
|
||||
/*
|
||||
* TEMPORARY BASAL
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.database.entities.Bolus
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.interfaces.profile.DefaultValueHelper
|
||||
|
@ -22,7 +23,7 @@ class BolusDataPoint(
|
|||
get() = DecimalFormatter.toPumpSupportedBolus(data.amount, activePlugin.activePump, rh)
|
||||
override val duration = 0L
|
||||
override val size = 2f
|
||||
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL // not used
|
||||
override val shape
|
||||
get() = if (data.type == Bolus.Type.SMB) PointsWithLabelGraphSeries.Shape.SMB else PointsWithLabelGraphSeries.Shape.BOLUS
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.core.graph.R
|
||||
import info.nightscout.database.entities.Carbs
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
|
@ -18,6 +19,7 @@ class CarbsDataPoint(
|
|||
override val duration = 0L
|
||||
override val size = 2f
|
||||
override val shape = PointsWithLabelGraphSeries.Shape.CARBS
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL // not used
|
||||
|
||||
override fun color(context: Context?): Int {
|
||||
return if (data.isValid) rh.gac(context, info.nightscout.core.ui.R.attr.cobColor) else rh.gac(context, info.nightscout.core.ui.R.attr.alarmColor)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import androidx.annotation.ColorInt
|
||||
import com.jjoe64.graphview.series.DataPointInterface
|
||||
|
||||
interface DataPointWithLabelInterface : DataPointInterface {
|
||||
|
@ -13,5 +15,6 @@ interface DataPointWithLabelInterface : DataPointInterface {
|
|||
val duration: Long
|
||||
val shape: PointsWithLabelGraphSeries.Shape
|
||||
val size: Float
|
||||
fun color(context: Context?): Int
|
||||
val paintStyle: Paint.Style
|
||||
@ColorInt fun color(context: Context?): Int
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.database.entities.EffectiveProfileSwitch
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import info.nightscout.shared.utils.T
|
||||
|
@ -22,6 +23,7 @@ class EffectiveProfileSwitchDataPoint(
|
|||
override val duration = 0L
|
||||
override val shape = PointsWithLabelGraphSeries.Shape.PROFILE
|
||||
override val size = 2f
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL // not used
|
||||
override fun color(context: Context?): Int {
|
||||
return rh.gac(context, info.nightscout.core.ui.R.attr.profileSwitchColor)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.database.entities.ExtendedBolus
|
||||
import info.nightscout.interfaces.utils.DecimalFormatter
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
|
@ -18,6 +19,7 @@ class ExtendedBolusDataPoint(
|
|||
override val duration get() = data.duration
|
||||
override val size = 10f
|
||||
override val shape = PointsWithLabelGraphSeries.Shape.EXTENDEDBOLUS
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL // not used
|
||||
override fun color(context: Context?): Int {
|
||||
return rh.gac(context, info.nightscout.core.ui.R.attr.extBolusColor)
|
||||
}
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
import info.nightscout.interfaces.Constants
|
||||
import info.nightscout.interfaces.GlucoseUnit
|
||||
import info.nightscout.interfaces.profile.DefaultValueHelper
|
||||
import info.nightscout.interfaces.profile.Profile
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
|
||||
class GlucoseValueDataPoint(
|
||||
val data: GlucoseValue,
|
||||
private val defaultValueHelper: DefaultValueHelper,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val rh: ResourceHelper
|
||||
) : DataPointWithLabelInterface {
|
||||
|
||||
fun valueToUnits(units: GlucoseUnit): Double =
|
||||
private fun valueToUnits(units: GlucoseUnit): Double =
|
||||
if (units == GlucoseUnit.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL
|
||||
|
||||
override fun getX(): Double = data.timestamp.toDouble()
|
||||
|
@ -26,16 +25,13 @@ class GlucoseValueDataPoint(
|
|||
override val label: String = Profile.toCurrentUnitsString(profileFunction, data.value)
|
||||
override val duration = 0L
|
||||
override val shape get() = if (isPrediction) PointsWithLabelGraphSeries.Shape.PREDICTION else PointsWithLabelGraphSeries.Shape.BG
|
||||
override val size = 1f
|
||||
override val size = if (isPrediction) 1f else 0.6f
|
||||
override val paintStyle: Paint.Style = if (isPrediction) Paint.Style.FILL else Paint.Style.STROKE
|
||||
|
||||
override fun color(context: Context?): Int {
|
||||
val units = profileFunction.getUnits()
|
||||
val lowLine = defaultValueHelper.determineLowLine()
|
||||
val highLine = defaultValueHelper.determineHighLine()
|
||||
return when {
|
||||
isPrediction -> predictionColor(context)
|
||||
valueToUnits(units) < lowLine -> rh.gac(context, info.nightscout.core.ui.R.attr.bgLow)
|
||||
valueToUnits(units) > highLine -> rh.gac(context, info.nightscout.core.ui.R.attr.highColor)
|
||||
else -> rh.gac(context, info.nightscout.core.ui.R.attr.bgInRange)
|
||||
else -> rh.gac(context, info.nightscout.core.ui.R.attr.originalBgValueColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import info.nightscout.interfaces.Constants
|
||||
import info.nightscout.interfaces.GlucoseUnit
|
||||
import info.nightscout.interfaces.iob.InMemoryGlucoseValue
|
||||
import info.nightscout.interfaces.profile.DefaultValueHelper
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
|
||||
class InMemoryGlucoseValueDataPoint(
|
||||
val data: InMemoryGlucoseValue,
|
||||
private val defaultValueHelper: DefaultValueHelper,
|
||||
private val profileFunction: ProfileFunction,
|
||||
private val rh: ResourceHelper
|
||||
) : DataPointWithLabelInterface {
|
||||
|
||||
fun valueToUnits(units: GlucoseUnit): Double =
|
||||
if (units == GlucoseUnit.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL
|
||||
private fun valueToUnits(units: GlucoseUnit): Double =
|
||||
if (units == GlucoseUnit.MGDL) data.recalculated else data.recalculated * Constants.MGDL_TO_MMOLL
|
||||
|
||||
override fun getX(): Double = data.timestamp.toDouble()
|
||||
override fun getY(): Double = valueToUnits(profileFunction.getUnits())
|
||||
|
@ -22,8 +27,20 @@ class InMemoryGlucoseValueDataPoint(
|
|||
override val label: String = ""
|
||||
override val duration = 0L
|
||||
override val shape = PointsWithLabelGraphSeries.Shape.BUCKETED_BG
|
||||
override val size = 0.3f
|
||||
override val size = 1f
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL
|
||||
|
||||
@ColorInt
|
||||
override fun color(context: Context?): Int {
|
||||
return rh.gac(context, info.nightscout.core.ui.R.attr.inMemoryColor)
|
||||
val units = profileFunction.getUnits()
|
||||
val lowLine = defaultValueHelper.determineLowLine()
|
||||
val highLine = defaultValueHelper.determineHighLine()
|
||||
val color = when {
|
||||
valueToUnits(units) < lowLine -> rh.gac(context, info.nightscout.core.ui.R.attr.bgLow)
|
||||
valueToUnits(units) > highLine -> rh.gac(context, info.nightscout.core.ui.R.attr.highColor)
|
||||
else -> rh.gac(context, info.nightscout.core.ui.R.attr.bgInRange)
|
||||
}
|
||||
return if (data.filledGap) ColorUtils.setAlphaComponent(color, 128) else color
|
||||
}
|
||||
|
||||
}
|
|
@ -179,20 +179,20 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
// draw data point
|
||||
if (!overdraw) {
|
||||
if (value.getShape() == Shape.BG || value.getShape() == Shape.COB_FAIL_OVER) {
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setStyle(value.getPaintStyle());
|
||||
mPaint.setStrokeWidth(0);
|
||||
canvas.drawCircle(endX, endY, value.getSize() * scaledPxSize, mPaint);
|
||||
} else if (value.getShape() == Shape.BG || value.getShape() == Shape.IOB_PREDICTION || value.getShape() == Shape.BUCKETED_BG) {
|
||||
mPaint.setColor(value.color(graphView.getContext()));
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setStyle(value.getPaintStyle());
|
||||
mPaint.setStrokeWidth(0);
|
||||
canvas.drawCircle(endX, endY, value.getSize() * scaledPxSize, mPaint);
|
||||
} else if (value.getShape() == Shape.PREDICTION) {
|
||||
mPaint.setColor(value.color(graphView.getContext()));
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setStyle(value.getPaintStyle());
|
||||
mPaint.setStrokeWidth(0);
|
||||
canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setStyle(value.getPaintStyle());
|
||||
mPaint.setStrokeWidth(0);
|
||||
canvas.drawCircle(endX, endY, scaledPxSize / 3, mPaint);
|
||||
} else if (value.getShape() == Shape.RECTANGLE) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.database.entities.TherapyEvent
|
||||
import info.nightscout.interfaces.Constants
|
||||
import info.nightscout.interfaces.Translator
|
||||
|
@ -55,6 +56,7 @@ class TherapyEventDataPoint(
|
|||
duration > 0 -> PointsWithLabelGraphSeries.Shape.GENERAL_WITH_DURATION
|
||||
else -> PointsWithLabelGraphSeries.Shape.GENERAL
|
||||
}
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL // not used
|
||||
|
||||
override val size get() = if (rh.gb(info.nightscout.shared.R.bool.isTablet)) 12.0f else 10.0f
|
||||
override fun color(context: Context?): Int {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="format_carbs">%1$dg</string>
|
||||
<string name="format_carbs">%1$d g</string>
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
import info.nightscout.interfaces.GlucoseUnit
|
||||
import info.nightscout.interfaces.iob.InMemoryGlucoseValue
|
||||
import info.nightscout.interfaces.profile.DefaultValueHelper
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.junit.jupiter.MockitoExtension
|
||||
import org.mockito.junit.jupiter.MockitoSettings
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.quality.Strictness
|
||||
|
||||
@ExtendWith(MockitoExtension::class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
internal class InMemoryGlucoseValueDataPointTest {
|
||||
|
||||
@Mock lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Mock lateinit var profileFunction: ProfileFunction
|
||||
@Mock lateinit var rh: ResourceHelper
|
||||
@Mock lateinit var context: Context
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
Mockito.`when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL)
|
||||
Mockito.`when`(rh.gac(any(), any())).thenReturn(Color.GREEN)
|
||||
}
|
||||
@Test
|
||||
fun alphaShouldBeAddedForFilledGaps() {
|
||||
val gv = InMemoryGlucoseValue(1000, 100.0, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN)
|
||||
val sut = InMemoryGlucoseValueDataPoint(gv, defaultValueHelper, profileFunction, rh)
|
||||
|
||||
var alpha = sut.color(context).ushr(24)
|
||||
Assertions.assertEquals(255, alpha)
|
||||
gv.filledGap = true
|
||||
alpha = sut.color(context).ushr(24)
|
||||
Assertions.assertEquals(128, alpha)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
|
||||
</manifest>
|
|
@ -0,0 +1,13 @@
|
|||
package info.nightscout.interfaces
|
||||
|
||||
enum class ApsMode() {
|
||||
OPEN,
|
||||
CLOSED,
|
||||
LGS,
|
||||
UNDEFINED;
|
||||
|
||||
companion object {
|
||||
|
||||
fun fromString(stringValue: String?) = values().firstOrNull { it.name == stringValue?.uppercase() } ?: UNDEFINED
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package info.nightscout.interfaces
|
|||
|
||||
@Suppress("PropertyName")
|
||||
interface Config {
|
||||
val SUPPORTEDNSVERSION: Int
|
||||
val SUPPORTED_NS_VERSION: Int
|
||||
val APS: Boolean
|
||||
val NSCLIENT: Boolean
|
||||
val PUMPCONTROL: Boolean
|
||||
|
|
|
@ -1,16 +1,59 @@
|
|||
package info.nightscout.interfaces
|
||||
|
||||
import android.widget.LinearLayout
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import info.nightscout.interfaces.plugin.PluginBase
|
||||
import info.nightscout.interfaces.plugin.PluginType
|
||||
|
||||
interface ConfigBuilder {
|
||||
|
||||
/**
|
||||
* Called during start of app to load configuration and start enabled plugins
|
||||
*/
|
||||
fun initialize()
|
||||
|
||||
/**
|
||||
* Store current configuration to SharedPreferences
|
||||
*/
|
||||
fun storeSettings(from: String)
|
||||
|
||||
/**
|
||||
* Enable another plugin and fragment and disable currently enabled if they are mutually exclusive
|
||||
*/
|
||||
fun performPluginSwitch(changedPlugin: PluginBase, enabled: Boolean, type: PluginType)
|
||||
|
||||
/**
|
||||
* Make sure plugins configuration is valid after enabling/disabling plugin
|
||||
*/
|
||||
fun processOnEnabledCategoryChanged(changedPlugin: PluginBase, type: PluginType)
|
||||
|
||||
/**
|
||||
* Fill LinearLayout with list of available plugins and checkboxes for enabling/disabling
|
||||
*
|
||||
* @param title Paragraph title or null if provided elsewhere
|
||||
* @param description comment
|
||||
* @param pluginType plugin category for example SYNC
|
||||
* @param plugins list of plugins
|
||||
* @param pluginViewHolders links to created UI elements (for calling `update` if configuration is changed)
|
||||
* @param fragment
|
||||
* @param activity either fragment or activity must be non null
|
||||
* @param parent UI container to add views
|
||||
*/
|
||||
fun createViewsForPlugins(
|
||||
@StringRes title: Int?,
|
||||
@StringRes description: Int,
|
||||
pluginType: PluginType,
|
||||
plugins: List<PluginBase>,
|
||||
pluginViewHolders: ArrayList<PluginViewHolderInterface>,
|
||||
fragment: Fragment? = null,
|
||||
activity: FragmentActivity? = null,
|
||||
parent: LinearLayout
|
||||
)
|
||||
|
||||
interface PluginViewHolderInterface {
|
||||
|
||||
fun update()
|
||||
}
|
||||
}
|
|
@ -1,14 +1,30 @@
|
|||
package info.nightscout.interfaces
|
||||
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import info.nightscout.interfaces.sync.DataSyncSelector
|
||||
|
||||
/**
|
||||
* Send data to xDrip+ via Inter-app settings
|
||||
*/
|
||||
interface XDripBroadcast {
|
||||
|
||||
/**
|
||||
* Send calibration to xDrip+
|
||||
* Accepting must be enabled in Inter-app settings - Accept Calibrations
|
||||
*/
|
||||
fun sendCalibration(bg: Double): Boolean
|
||||
fun send(glucoseValue: GlucoseValue)
|
||||
fun sendProfile(profileStoreJson: JSONObject)
|
||||
fun sendTreatments(addedOrUpdatedTreatments: JSONArray)
|
||||
fun sendSgvs(sgvs: JSONArray)
|
||||
|
||||
/**
|
||||
* Send data to xDrip+
|
||||
*
|
||||
* Accepting must be enabled in Inter-app settings - Accept Glucose/Treatments
|
||||
*/
|
||||
fun sendToXdrip(collection: String, dataPair: DataSyncSelector.DataPair, progress: String)
|
||||
|
||||
/**
|
||||
* Send data to xDrip+
|
||||
*
|
||||
* Accepting must be enabled in Inter-app settings - Accept Glucose/Treatments
|
||||
*/
|
||||
fun sendToXdrip(collection: String, dataPairs: List<DataSyncSelector.DataPair>, progress:
|
||||
String)
|
||||
}
|
|
@ -15,8 +15,18 @@ interface AutosensDataStore {
|
|||
var bucketedData: MutableList<InMemoryGlucoseValue>?
|
||||
var lastUsed5minCalculation: Boolean?
|
||||
|
||||
fun lastBg(): GlucoseValue?
|
||||
fun actualBg(): GlucoseValue?
|
||||
/**
|
||||
* Return last valid (>39) InMemoryGlucoseValue from bucketed data or null if db is empty
|
||||
*
|
||||
* @return InMemoryGlucoseValue or null
|
||||
*/
|
||||
fun lastBg(): InMemoryGlucoseValue?
|
||||
/**
|
||||
* Provide last bucketed InMemoryGlucoseValue or null if none exists within the last 9 minutes
|
||||
*
|
||||
* @return InMemoryGlucoseValue or null
|
||||
*/
|
||||
fun actualBg(): InMemoryGlucoseValue?
|
||||
fun lastDataTime(dateUtil: DateUtil): String
|
||||
fun clone(): AutosensDataStore
|
||||
fun getBgReadingsDataTableCopy(): List<GlucoseValue>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package info.nightscout.interfaces.configBuilder
|
||||
|
||||
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
|
||||
import info.nightscout.sdk.localmodel.devicestatus.NSDeviceStatus
|
||||
import org.json.JSONObject
|
||||
|
||||
interface RunningConfiguration {
|
||||
|
@ -9,5 +9,5 @@ interface RunningConfiguration {
|
|||
fun configuration(): JSONObject
|
||||
|
||||
// called in NSClient mode only
|
||||
fun apply(configuration: RemoteDeviceStatus.Configuration)
|
||||
fun apply(configuration: NSDeviceStatus.Configuration)
|
||||
}
|
|
@ -2,8 +2,39 @@ package info.nightscout.interfaces.iob
|
|||
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
|
||||
class InMemoryGlucoseValue constructor(var timestamp: Long = 0L, var value: Double = 0.0, var interpolated: Boolean = false) {
|
||||
/**
|
||||
* Simplified [GlucoseValue] for storing in memory and calculations
|
||||
* It may correspond to GlucoseValue value in db
|
||||
* but because of 5 min recalculations and smoothing it may not
|
||||
*/
|
||||
class InMemoryGlucoseValue constructor(
|
||||
var timestamp: Long = 0L,
|
||||
/**
|
||||
* Value in mg/dl
|
||||
*/
|
||||
var value: Double = 0.0,
|
||||
var trendArrow: GlucoseValue.TrendArrow = GlucoseValue.TrendArrow.NONE,
|
||||
/**
|
||||
* Smoothed value. Value is added by smoothing plugin
|
||||
* or null if smoothing was not done
|
||||
*/
|
||||
var smoothed: Double? = null,
|
||||
/**
|
||||
* if true value is not corresponding to received value,
|
||||
* but it was recalculated to fill gap between BGs
|
||||
*/
|
||||
var filledGap: Boolean = false,
|
||||
/**
|
||||
* Taken from GlucoseValue
|
||||
*/
|
||||
var sourceSensor: GlucoseValue.SourceSensor
|
||||
) {
|
||||
|
||||
constructor(gv: GlucoseValue) : this(gv.timestamp, gv.value)
|
||||
// var generated : value doesn't correspond to real value with timestamp close to real BG
|
||||
constructor(gv: GlucoseValue) : this(timestamp = gv.timestamp, value = gv.value, trendArrow = gv.trendArrow, sourceSensor = gv.sourceSensor)
|
||||
|
||||
/**
|
||||
* Provide smoothed value if available,
|
||||
* non smoothed value as a fallback
|
||||
*/
|
||||
val recalculated: Double get() = smoothed ?: value
|
||||
}
|
|
@ -32,11 +32,10 @@ interface IobCobCalculator {
|
|||
/**
|
||||
* Calculate CobInfo to now()
|
||||
*
|
||||
* @param waitForCalculationFinish access autosens data synchronized (wait for result if calculation is running)
|
||||
* @param reason caller identification
|
||||
* @return CobInfo
|
||||
*/
|
||||
fun getCobInfo(waitForCalculationFinish: Boolean, reason: String): CobInfo
|
||||
fun getCobInfo(reason: String): CobInfo
|
||||
|
||||
/**
|
||||
* Calculate IobTotal from boluses and extended boluses to now().
|
||||
|
|
|
@ -48,6 +48,7 @@ interface ProcessedDeviceStatusData {
|
|||
|
||||
var clock = 0L
|
||||
var battery = 0
|
||||
var isCharging: Boolean? = null
|
||||
}
|
||||
|
||||
val uploaderMap: HashMap<String, Uploader>
|
||||
|
|
|
@ -27,11 +27,11 @@ interface StoreDataForDb {
|
|||
val temporaryBasals: MutableList<TemporaryBasal>
|
||||
val profileSwitches: MutableList<ProfileSwitch>
|
||||
val offlineEvents: MutableList<OfflineEvent>
|
||||
val foods: MutableList<Food>
|
||||
|
||||
val nsIdGlucoseValues: MutableList<GlucoseValue>
|
||||
val nsIdBoluses: MutableList<Bolus>
|
||||
val nsIdCarbs: MutableList<Carbs>
|
||||
val nsIdFoods: MutableList<Food>
|
||||
val nsIdTemporaryTargets: MutableList<TemporaryTarget>
|
||||
val nsIdEffectiveProfileSwitches: MutableList<EffectiveProfileSwitch>
|
||||
val nsIdBolusCalculatorResults: MutableList<BolusCalculatorResult>
|
||||
|
@ -41,8 +41,11 @@ interface StoreDataForDb {
|
|||
val nsIdProfileSwitches: MutableList<ProfileSwitch>
|
||||
val nsIdOfflineEvents: MutableList<OfflineEvent>
|
||||
val nsIdDeviceStatuses: MutableList<DeviceStatus>
|
||||
val nsIdFoods: MutableList<Food>
|
||||
|
||||
fun storeTreatmentsToDb()
|
||||
fun storeGlucoseValuesToDb()
|
||||
fun storeFoodsToDb()
|
||||
fun scheduleNsIdUpdate()
|
||||
fun updateNsIds()
|
||||
}
|
|
@ -9,6 +9,7 @@ import info.nightscout.interfaces.insulin.Insulin
|
|||
import info.nightscout.interfaces.iob.IobCobCalculator
|
||||
import info.nightscout.interfaces.profile.ProfileSource
|
||||
import info.nightscout.interfaces.pump.Pump
|
||||
import info.nightscout.interfaces.smoothing.Smoothing
|
||||
import info.nightscout.interfaces.source.BgSource
|
||||
import info.nightscout.interfaces.sync.NsClient
|
||||
import info.nightscout.interfaces.sync.Sync
|
||||
|
@ -74,6 +75,11 @@ interface ActivePlugin {
|
|||
*/
|
||||
val activeObjectives: Objectives?
|
||||
|
||||
/**
|
||||
* Smoothing plugin
|
||||
*/
|
||||
val activeSmoothing: Smoothing
|
||||
|
||||
/**
|
||||
* Currently selected NsClient plugin
|
||||
*/
|
||||
|
|
|
@ -6,5 +6,5 @@ package info.nightscout.interfaces.plugin
|
|||
* set by [info.nightscout.interfaces.PluginDescription.mainType]
|
||||
*/
|
||||
enum class PluginType {
|
||||
GENERAL, SENSITIVITY, PROFILE, APS, PUMP, CONSTRAINTS, LOOP, BGSOURCE, INSULIN, SYNC
|
||||
GENERAL, SENSITIVITY, PROFILE, APS, PUMP, CONSTRAINTS, LOOP, BGSOURCE, INSULIN, SYNC, SMOOTHING
|
||||
}
|
|
@ -1,34 +1,31 @@
|
|||
package info.nightscout.interfaces.profile
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import info.nightscout.interfaces.Constants
|
||||
import org.json.JSONArray
|
||||
|
||||
interface ProfileSource {
|
||||
|
||||
class SingleProfile {
|
||||
|
||||
var name: String? = null
|
||||
var mgdl: Boolean = false
|
||||
var dia: Double = Constants.defaultDIA
|
||||
var ic: JSONArray? = null
|
||||
var isf: JSONArray? = null
|
||||
var basal: JSONArray? = null
|
||||
var targetLow: JSONArray? = null
|
||||
var targetHigh: JSONArray? = null
|
||||
|
||||
fun deepClone(): SingleProfile {
|
||||
val sp = SingleProfile()
|
||||
sp.name = name
|
||||
sp.mgdl = mgdl
|
||||
sp.dia = dia
|
||||
sp.ic = JSONArray(ic.toString())
|
||||
sp.isf = JSONArray(isf.toString())
|
||||
sp.basal = JSONArray(basal.toString())
|
||||
sp.targetLow = JSONArray(targetLow.toString())
|
||||
sp.targetHigh = JSONArray(targetHigh.toString())
|
||||
return sp
|
||||
}
|
||||
class SingleProfile(
|
||||
var name: String,
|
||||
var mgdl: Boolean,
|
||||
var dia: Double,
|
||||
var ic: JSONArray,
|
||||
var isf: JSONArray,
|
||||
var basal: JSONArray,
|
||||
var targetLow: JSONArray,
|
||||
var targetHigh: JSONArray,
|
||||
) {
|
||||
fun deepClone(): SingleProfile =
|
||||
SingleProfile(
|
||||
name = name,
|
||||
mgdl = mgdl,
|
||||
dia = dia,
|
||||
ic = JSONArray(ic.toString()),
|
||||
isf = JSONArray(isf.toString()),
|
||||
basal = JSONArray(basal.toString()),
|
||||
targetLow = JSONArray(targetLow.toString()),
|
||||
targetHigh = JSONArray(targetHigh.toString())
|
||||
)
|
||||
}
|
||||
|
||||
val profile: ProfileStore?
|
||||
|
@ -38,6 +35,7 @@ interface ProfileSource {
|
|||
|
||||
var currentProfileIndex: Int
|
||||
fun currentProfile(): SingleProfile?
|
||||
fun storeSettings(activity: FragmentActivity? = null)
|
||||
fun storeSettings(activity: FragmentActivity? = null, emptyCreated: Boolean = false)
|
||||
fun loadFromStore(store: ProfileStore)
|
||||
|
||||
}
|
|
@ -8,8 +8,14 @@ interface Intents {
|
|||
// AAPS -> Xdrip
|
||||
const val ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT"
|
||||
const val ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE"
|
||||
const val ACTION_NEW_DEVICE_STATUS = "info.nightscout.client.NEW_DEVICESTATUS"
|
||||
const val ACTION_NEW_FOOD = "info.nightscout.client.NEW_FOOD"
|
||||
const val ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV"
|
||||
|
||||
const val EXTRA_STATUSLINE = "com.eveningoutpost.dexdrip.Extras.Statusline"
|
||||
const val ACTION_NEW_EXTERNAL_STATUSLINE = "com.eveningoutpost.dexdrip.ExternalStatusline"
|
||||
const val RECEIVER_PERMISSION = "com.eveningoutpost.dexdrip.permissions.RECEIVE_EXTERNAL_STATUSLINE"
|
||||
|
||||
// AAPS -> xDrip 640G mode
|
||||
const val XDRIP_PLUS_NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR"
|
||||
|
||||
|
@ -27,6 +33,7 @@ interface Intents {
|
|||
const val ACTION_REMOTE_CALIBRATION = "com.eveningoutpost.dexdrip.NewCalibration"
|
||||
const val GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED"
|
||||
const val DEXCOM_BG = "com.dexcom.cgm.EXTERNAL_BROADCAST"
|
||||
const val DEXCOM_G7_BG = "com.dexcom.g7.EXTERNAL_BROADCAST"
|
||||
const val EVERSENSE_BG = "com.senseonics.AndroidAPSEventSubscriber.BROADCAST"
|
||||
const val POCTECH_BG = "com.china.poctech.data"
|
||||
const val TOMATO_BG = "com.fanqies.tomatofn.BgEstimate"
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package info.nightscout.interfaces.smoothing
|
||||
|
||||
import info.nightscout.interfaces.iob.InMemoryGlucoseValue
|
||||
|
||||
interface Smoothing {
|
||||
|
||||
/**
|
||||
* Smooth values in List
|
||||
*
|
||||
* @param data input glucose values ([0] to be the most recent one)
|
||||
* @param updateWindow amount of values to the past to smooth
|
||||
*
|
||||
* @return new List with smoothed values (smoothed values are stored in [InMemoryGlucoseValue.smoothed])
|
||||
*/
|
||||
fun smooth(data: MutableList<InMemoryGlucoseValue>): MutableList<InMemoryGlucoseValue>
|
||||
}
|
|
@ -3,5 +3,6 @@ package info.nightscout.interfaces.source
|
|||
import info.nightscout.database.entities.GlucoseValue
|
||||
|
||||
interface NSClientSource {
|
||||
fun isEnabled(): Boolean
|
||||
fun detectSource(glucoseValue: GlucoseValue)
|
||||
}
|
|
@ -7,10 +7,10 @@ import info.nightscout.database.entities.TotalDailyDose
|
|||
|
||||
interface TddCalculator {
|
||||
|
||||
fun calculate(days: Long): LongSparseArray<TotalDailyDose>
|
||||
fun calculateToday(): TotalDailyDose
|
||||
fun calculateDaily(startHours: Long, endHours: Long): TotalDailyDose
|
||||
fun calculate(startTime: Long, endTime: Long): TotalDailyDose
|
||||
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>): TotalDailyDose?
|
||||
fun calculate(days: Long, allowMissingDays: Boolean): LongSparseArray<TotalDailyDose>?
|
||||
fun calculateToday(): TotalDailyDose?
|
||||
fun calculateDaily(startHours: Long, endHours: Long): TotalDailyDose?
|
||||
fun calculate(startTime: Long, endTime: Long, allowMissingData: Boolean): TotalDailyDose?
|
||||
fun averageTDD(tdds: LongSparseArray<TotalDailyDose>?): TotalDailyDose?
|
||||
fun stats(context: Context): TableLayout
|
||||
}
|
||||
|
|
|
@ -17,70 +17,30 @@ import org.json.JSONObject
|
|||
|
||||
interface DataSyncSelector {
|
||||
|
||||
interface DataPair {
|
||||
interface DataPair {
|
||||
|
||||
val value: Any
|
||||
val id: Long
|
||||
}
|
||||
data class PairTemporaryTarget(override val value: TemporaryTarget, override val id: Long): DataPair
|
||||
data class PairGlucoseValue(override val value: GlucoseValue, override val id: Long): DataPair
|
||||
data class PairTherapyEvent(override val value: TherapyEvent, override val id: Long): DataPair
|
||||
data class PairFood(override val value: Food, override val id: Long): DataPair
|
||||
data class PairBolus(override val value: Bolus, override val id: Long): DataPair
|
||||
data class PairCarbs(override val value: Carbs, override val id: Long): DataPair
|
||||
data class PairBolusCalculatorResult(override val value: BolusCalculatorResult, override val id: Long): DataPair
|
||||
data class PairTemporaryBasal(override val value: TemporaryBasal, override val id: Long): DataPair
|
||||
data class PairExtendedBolus(override val value: ExtendedBolus, override val id: Long): DataPair
|
||||
data class PairProfileSwitch(override val value: ProfileSwitch, override val id: Long): DataPair
|
||||
data class PairEffectiveProfileSwitch(override val value: EffectiveProfileSwitch, override val id: Long): DataPair
|
||||
data class PairOfflineEvent(override val value: OfflineEvent, override val id: Long): DataPair
|
||||
data class PairProfileStore(override val value: JSONObject, override val id: Long): DataPair
|
||||
data class PairDeviceStatus(override val value: DeviceStatus, override val id: Long): DataPair
|
||||
|
||||
data class PairTemporaryTarget(override val value: TemporaryTarget, override val id: Long) : DataPair
|
||||
data class PairGlucoseValue(override val value: GlucoseValue, override val id: Long) : DataPair
|
||||
data class PairTherapyEvent(override val value: TherapyEvent, override val id: Long) : DataPair
|
||||
data class PairFood(override val value: Food, override val id: Long) : DataPair
|
||||
data class PairBolus(override val value: Bolus, override val id: Long) : DataPair
|
||||
data class PairCarbs(override val value: Carbs, override val id: Long) : DataPair
|
||||
data class PairBolusCalculatorResult(override val value: BolusCalculatorResult, override val id: Long) : DataPair
|
||||
data class PairTemporaryBasal(override val value: TemporaryBasal, override val id: Long) : DataPair
|
||||
data class PairExtendedBolus(override val value: ExtendedBolus, override val id: Long) : DataPair
|
||||
data class PairProfileSwitch(override val value: ProfileSwitch, override val id: Long) : DataPair
|
||||
data class PairEffectiveProfileSwitch(override val value: EffectiveProfileSwitch, override val id: Long) : DataPair
|
||||
data class PairOfflineEvent(override val value: OfflineEvent, override val id: Long) : DataPair
|
||||
data class PairProfileStore(override val value: JSONObject, override val id: Long) : DataPair
|
||||
data class PairDeviceStatus(override val value: DeviceStatus, override val id: Long) : DataPair
|
||||
|
||||
fun queueSize(): Long
|
||||
|
||||
fun doUpload()
|
||||
|
||||
fun resetToNextFullSync()
|
||||
|
||||
fun confirmLastBolusIdIfGreater(lastSynced: Long)
|
||||
fun processChangedBolusesCompat()
|
||||
|
||||
fun confirmLastCarbsIdIfGreater(lastSynced: Long)
|
||||
fun processChangedCarbsCompat()
|
||||
|
||||
fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long)
|
||||
fun processChangedBolusCalculatorResultsCompat()
|
||||
|
||||
fun confirmLastTempTargetsIdIfGreater(lastSynced: Long)
|
||||
fun processChangedTempTargetsCompat()
|
||||
|
||||
fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long)
|
||||
fun processChangedGlucoseValuesCompat()
|
||||
|
||||
fun confirmLastTherapyEventIdIfGreater(lastSynced: Long)
|
||||
fun processChangedTherapyEventsCompat()
|
||||
|
||||
fun confirmLastFoodIdIfGreater(lastSynced: Long)
|
||||
fun processChangedFoodsCompat()
|
||||
|
||||
fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long)
|
||||
fun processChangedDeviceStatusesCompat()
|
||||
|
||||
fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long)
|
||||
fun processChangedTemporaryBasalsCompat()
|
||||
|
||||
fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long)
|
||||
fun processChangedExtendedBolusesCompat()
|
||||
|
||||
fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long)
|
||||
fun processChangedProfileSwitchesCompat()
|
||||
|
||||
fun confirmLastEffectiveProfileSwitchIdIfGreater(lastSynced: Long)
|
||||
fun processChangedEffectiveProfileSwitchesCompat()
|
||||
|
||||
fun confirmLastOfflineEventIdIfGreater(lastSynced: Long)
|
||||
fun processChangedOfflineEventsCompat()
|
||||
|
||||
fun confirmLastProfileStore(lastSynced: Long)
|
||||
fun processChangedProfileStore()
|
||||
suspend fun doUpload()
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package info.nightscout.interfaces.sync
|
||||
|
||||
interface DataSyncSelectorV1 : DataSyncSelector {
|
||||
|
||||
fun confirmLastBolusIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedBoluses()
|
||||
|
||||
fun confirmLastCarbsIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedCarbs()
|
||||
|
||||
fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedBolusCalculatorResults()
|
||||
|
||||
fun confirmLastTempTargetsIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedTempTargets()
|
||||
|
||||
fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedGlucoseValues()
|
||||
|
||||
fun confirmLastTherapyEventIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedTherapyEvents()
|
||||
|
||||
fun confirmLastFoodIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedFoods()
|
||||
|
||||
fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedDeviceStatuses()
|
||||
|
||||
fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedTemporaryBasals()
|
||||
|
||||
fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedExtendedBoluses()
|
||||
|
||||
fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedProfileSwitches()
|
||||
|
||||
fun confirmLastEffectiveProfileSwitchIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedEffectiveProfileSwitches()
|
||||
|
||||
fun confirmLastOfflineEventIdIfGreater(lastSynced: Long)
|
||||
suspend fun processChangedOfflineEvents()
|
||||
|
||||
fun confirmLastProfileStore(lastSynced: Long)
|
||||
suspend fun processChangedProfileStore()
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package info.nightscout.interfaces.sync
|
||||
|
||||
interface DataSyncSelectorV3 : DataSyncSelector
|
|
@ -0,0 +1,3 @@
|
|||
package info.nightscout.interfaces.sync
|
||||
|
||||
interface DataSyncSelectorXdrip : DataSyncSelector
|
|
@ -1,27 +1,105 @@
|
|||
package info.nightscout.interfaces.sync
|
||||
|
||||
import android.text.Spanned
|
||||
import info.nightscout.interfaces.nsclient.NSAlarm
|
||||
import info.nightscout.rx.events.EventNSClientNewLog
|
||||
|
||||
/**
|
||||
* Plugin providing communication with Nightscout server
|
||||
*/
|
||||
interface NsClient : Sync {
|
||||
enum class Version {
|
||||
NONE, V1, V3
|
||||
}
|
||||
|
||||
val version: Version
|
||||
/**
|
||||
* NS URL
|
||||
*/
|
||||
val address: String
|
||||
|
||||
/**
|
||||
* Set plugin in paused state
|
||||
*/
|
||||
fun pause(newState: Boolean)
|
||||
fun resend(reason: String)
|
||||
fun textLog(): Spanned
|
||||
fun clearLog()
|
||||
|
||||
/**
|
||||
* Initiate new round of upload/download
|
||||
*/
|
||||
fun resend(reason: String)
|
||||
|
||||
/**
|
||||
* List of log messages for fragment
|
||||
*/
|
||||
val listLog: MutableList<EventNSClientNewLog>
|
||||
|
||||
/**
|
||||
* Used data sync selector
|
||||
*/
|
||||
val dataSyncSelector: DataSyncSelector
|
||||
|
||||
/**
|
||||
* Version of NS server
|
||||
* @return Returns detected version of NS server
|
||||
*/
|
||||
fun detectedNsVersion(): String?
|
||||
|
||||
enum class Collection { ENTRIES, TREATMENTS, FOODS, PROFILE }
|
||||
|
||||
/**
|
||||
* NSC v3 does first load of all data
|
||||
* next loads are using srvModified property for sync
|
||||
* not used for NSCv1
|
||||
*
|
||||
* @return true if inside first load of NSCv3, true for NSCv1
|
||||
*/
|
||||
fun isFirstLoad(collection: Collection): Boolean = true
|
||||
|
||||
/**
|
||||
* Update newest loaded timestamp for entries collection (first load or NSCv1)
|
||||
* Update newest srvModified (sync loads)
|
||||
*
|
||||
* @param latestReceived timestamp
|
||||
*
|
||||
*/
|
||||
fun updateLatestBgReceivedIfNewer(latestReceived: Long)
|
||||
|
||||
/**
|
||||
* Update newest loaded timestamp for treatments collection (first load or NSCv1)
|
||||
* Update newest srvModified (sync loads)
|
||||
*
|
||||
* @param latestReceived timestamp
|
||||
*
|
||||
*/
|
||||
fun updateLatestTreatmentReceivedIfNewer(latestReceived: Long)
|
||||
|
||||
/**
|
||||
* Send alarm confirmation to NS
|
||||
*
|
||||
* @param originalAlarm alarm to be cleared
|
||||
* @param silenceTimeInMilliseconds silence alarm for specified duration
|
||||
*/
|
||||
fun handleClearAlarm(originalAlarm: NSAlarm, silenceTimeInMilliseconds: Long)
|
||||
|
||||
/**
|
||||
* Clear synchronization status
|
||||
*
|
||||
* Next synchronization will start from scratch
|
||||
*/
|
||||
fun resetToFullSync()
|
||||
|
||||
fun dbAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String)
|
||||
fun dbUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String)
|
||||
/**
|
||||
* Upload new record to NS
|
||||
*
|
||||
* @param collection target ns collection
|
||||
* @param dataPair data to upload (data.first) and id of changed record (data.second)
|
||||
* @param progress progress of sync in format "number/number". Only for display in fragment
|
||||
* @return true for successful upload
|
||||
*/
|
||||
suspend fun nsAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String): Boolean
|
||||
|
||||
/**
|
||||
* Upload updated record to NS
|
||||
*
|
||||
* @param collection target ns collection
|
||||
* @param dataPair data to upload (data.first) and id of changed record (data.second)
|
||||
* @param progress progress of sync in format "number/number". Only for display in fragment
|
||||
* @return true for successful upload
|
||||
*/
|
||||
suspend fun nsUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String): Boolean
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package info.nightscout.interfaces.sync
|
||||
|
||||
interface Tidepool : Sync
|
|
@ -21,6 +21,7 @@ interface UiInteraction {
|
|||
val singleFragmentActivity: Class<*>
|
||||
val preferencesActivity: Class<*>
|
||||
val myPreferenceFragment: Class<*>
|
||||
val quickWizardListActivity: Class<*>
|
||||
|
||||
val prefGeneral: Int
|
||||
/**
|
||||
|
@ -32,7 +33,7 @@ interface UiInteraction {
|
|||
*/
|
||||
fun runAlarm(status: String, title: String, @RawRes soundId: Int = 0)
|
||||
|
||||
fun updateWidget(context: Context)
|
||||
fun updateWidget(context: Context, from: String)
|
||||
|
||||
fun runWizardDialog(fragmentManager: FragmentManager, carbs: Int? = null, name: String? = null)
|
||||
fun runLoopDialog(fragmentManager: FragmentManager, showOkCancel: Int)
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
package info.nightscout.interfaces.utils
|
||||
|
||||
import android.text.Html
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
|
||||
object HtmlHelper {
|
||||
fun fromHtml(source: String): Spanned {
|
||||
return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY)
|
||||
}
|
||||
|
||||
fun fromHtml(source: String): Spanned =
|
||||
try {
|
||||
Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY)
|
||||
} catch (e: Exception) {
|
||||
SpannableStringBuilder("")
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package info.nightscout.interfaces.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.provider.AlarmClock
|
||||
import info.nightscout.androidaps.annotations.OpenForTesting
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@OpenForTesting
|
||||
@Singleton
|
||||
open class TimerUtil @Inject constructor(
|
||||
private val context: Context
|
||||
) {
|
||||
|
||||
/**
|
||||
* Schedule alarm in @seconds
|
||||
*/
|
||||
fun scheduleReminder(seconds: Int, text: String) {
|
||||
Intent(AlarmClock.ACTION_SET_TIMER).apply {
|
||||
flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
putExtra(AlarmClock.EXTRA_LENGTH, seconds)
|
||||
putExtra(AlarmClock.EXTRA_SKIP_UI, true)
|
||||
putExtra(AlarmClock.EXTRA_MESSAGE, text)
|
||||
context.startActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package info.nightscout.interfaces.utils
|
||||
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
import info.nightscout.interfaces.aps.AutosensDataStore
|
||||
import info.nightscout.interfaces.iob.InMemoryGlucoseValue
|
||||
|
||||
/**
|
||||
* Convert BG direction value to trend arrow or calculate it if not provided
|
||||
|
@ -15,6 +17,20 @@ interface TrendCalculator {
|
|||
* @return TrendArrow
|
||||
*/
|
||||
fun getTrendArrow(glucoseValue: GlucoseValue?): GlucoseValue.TrendArrow
|
||||
/**
|
||||
* Provide or calculate trend
|
||||
*
|
||||
* @param glucoseValue BG
|
||||
* @return TrendArrow
|
||||
*/
|
||||
fun getTrendArrow(glucoseValue: InMemoryGlucoseValue?): GlucoseValue.TrendArrow
|
||||
/**
|
||||
* Provide or calculate trend from newest bucketed data
|
||||
*
|
||||
* @param autosensDataStore current store from IobCobCalculator
|
||||
* @return TrendArrow
|
||||
*/
|
||||
fun getTrendArrow(autosensDataStore: AutosensDataStore): GlucoseValue.TrendArrow?
|
||||
|
||||
/**
|
||||
* Provide or calculate trend
|
||||
|
@ -23,4 +39,11 @@ interface TrendCalculator {
|
|||
* @return string description of TrendArrow
|
||||
*/
|
||||
fun getTrendDescription(glucoseValue: GlucoseValue?): String
|
||||
/**
|
||||
* Provide or calculate trend from newest bucketed data
|
||||
*
|
||||
* @param autosensDataStore current store from IobCobCalculator
|
||||
* @return string description of TrendArrow
|
||||
*/
|
||||
fun getTrendDescription(autosensDataStore: AutosensDataStore): String
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
package info.nightscout.interfaces.workflow
|
||||
|
||||
import androidx.work.ListenableWorker
|
||||
|
||||
interface WorkerClasses {
|
||||
val nsClientSourceWorker: Class<out ListenableWorker>
|
||||
val nsProfileWorker: Class<out ListenableWorker>
|
||||
val foodWorker: Class<out ListenableWorker>
|
||||
// val nsProfileWorker: Class<out ListenableWorker>
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
<!-- PumpType-->
|
||||
<string name="def_extended_note">* Само конкретни стойности! Диапазони не се поддържат за базал/болус при виртуална помпа.</string>
|
||||
<!-- PumpPluginBase -->
|
||||
<string name="pump_driver_changed" comment="26 characters max for translation">Драйверът на помпата е променен.</string>
|
||||
<!-- DecimalFormatter-->
|
||||
<string name="format_insulin_units1">%1$.1fЕ</string>
|
||||
<string name="format_insulin_units">%1$.2fЕ</string>
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
<string name="metadata_label_format">Filformat</string>
|
||||
<string name="metadata_label_created_at">Opprettet den</string>
|
||||
<string name="metadata_label_aaps_version">AAPS versjon</string>
|
||||
<string name="metadata_label_aaps_flavour">Bygge variant</string>
|
||||
<string name="metadata_label_aaps_flavour">Byggvariant</string>
|
||||
<string name="metadata_label_device_name">Eksporterer enhetens pasientnavn</string>
|
||||
<string name="metadata_label_device_model">Eksportere enhetsmodell</string>
|
||||
<string name="metadata_label_encryption">Fil kryptering</string>
|
||||
<string name="metadata_label_encryption">Filkryptering</string>
|
||||
<string name="metadata_format_new">Nytt krypteringsformat</string>
|
||||
<string name="metadata_format_debug">Nytt feilsøkingsformat (ukryptert)</string>
|
||||
<string name="metadata_format_other">Ukjent eksportformat</string>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue