Merge remote-tracking branch 'Nightscout/dev' into Autotune/TuneWeekDaysClean

This commit is contained in:
Philoul 2023-02-26 17:35:57 +01:00
commit 3b6a3605a2
1049 changed files with 26413 additions and 12742 deletions

View file

@ -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

View file

@ -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>

View file

@ -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
======================

View file

@ -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

View file

@ -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">

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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")
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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')

View file

@ -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 -->

View file

@ -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,

View file

@ -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)
}
}

View file

@ -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
}
}

View file

@ -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)
}
}

View file

@ -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

View file

@ -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 }
}

View file

@ -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

View file

@ -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"

View file

@ -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?) {

View file

@ -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 }
}

View file

@ -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()

View file

@ -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)
}
}

View file

@ -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()

View file

@ -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
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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">EMailAdresse</string>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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 gliukos 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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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)

View file

@ -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)

View file

@ -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)
}
}

View file

@ -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")

View file

@ -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(

View file

@ -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
View file

@ -0,0 +1 @@
adb connect 127.0.0.1:58526

View file

@ -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
*/

View file

@ -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

View file

@ -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)

View file

@ -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
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}
}

View file

@ -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
}
}

View file

@ -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) {

View file

@ -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 {

View file

@ -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>

View file

@ -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)
}
}

View file

@ -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>

View file

@ -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
}
}

View file

@ -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

View file

@ -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()
}
}

View file

@ -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)
}

View file

@ -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>

View file

@ -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)
}

View file

@ -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
}

View file

@ -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().

View file

@ -48,6 +48,7 @@ interface ProcessedDeviceStatusData {
var clock = 0L
var battery = 0
var isCharging: Boolean? = null
}
val uploaderMap: HashMap<String, Uploader>

View file

@ -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()
}

View file

@ -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
*/

View file

@ -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
}

View file

@ -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)
}

View file

@ -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"

View file

@ -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>
}

View file

@ -3,5 +3,6 @@ package info.nightscout.interfaces.source
import info.nightscout.database.entities.GlucoseValue
interface NSClientSource {
fun isEnabled(): Boolean
fun detectSource(glucoseValue: GlucoseValue)
}

View file

@ -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
}

View file

@ -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()
}

View file

@ -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()
}

View file

@ -0,0 +1,3 @@
package info.nightscout.interfaces.sync
interface DataSyncSelectorV3 : DataSyncSelector

View file

@ -0,0 +1,3 @@
package info.nightscout.interfaces.sync
interface DataSyncSelectorXdrip : DataSyncSelector

View file

@ -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
}

View file

@ -0,0 +1,3 @@
package info.nightscout.interfaces.sync
interface Tidepool : Sync

View file

@ -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)

View file

@ -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("")
}
}

View file

@ -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)
}
}
}

View file

@ -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
}

View file

@ -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>
}

View file

@ -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>

View file

@ -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