diff --git a/.gitignore b/.gitignore
index 57b17320cc3..401f82742fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,4 @@ wear/pumpcontrol/*
*.preferences_pb
/buildSrc/.kotlin
.claude/settings.local.json
-/CLAUDE.md
+.claude/CLAUDE_COMMANDS.md
diff --git a/_docs/icons/ic_none.svg b/_docs/icons/ic_none.svg
index 8c8ef23e3d2..30f64ebe610 100644
--- a/_docs/icons/ic_none.svg
+++ b/_docs/icons/ic_none.svg
@@ -1,13 +1,15 @@
-
diff --git a/app/src/benchmark/kotlin/app/aaps/utils/LeakCanaryConfig.kt b/app/src/benchmark/kotlin/app/aaps/utils/LeakCanaryConfig.kt
new file mode 100644
index 00000000000..488c7631ceb
--- /dev/null
+++ b/app/src/benchmark/kotlin/app/aaps/utils/LeakCanaryConfig.kt
@@ -0,0 +1,11 @@
+package app.aaps.utils
+
+import app.aaps.core.interfaces.utils.fabric.FabricPrivacy
+
+@Suppress("UNUSED_PARAMETER")
+fun configureLeakCanary(
+ isEnabled: Boolean = false,
+ fabricPrivacy: FabricPrivacy? = null
+) {
+ // no-op for benchmark variant
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index da29c11f5e5..f69fc78c976 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -37,7 +37,8 @@
android:restoreAnyVersion="true"
android:roundIcon="${appIconRound}"
android:supportsRtl="true"
- android:theme="@style/AppTheme.Launcher">
+ android:theme="@style/AppTheme.Launcher"
+ android:networkSecurityConfig="@xml/network_security_config">
Сортировать элементы
ЕдиницыОшибка авторизации
- Катетер помпы
+ КанюляИдентификация не задана в режиме разработчикаУдалить выбранные элементы
diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml
index f6278ed1656..507cf41df53 100644
--- a/app/src/main/res/values-vi-rVN/strings.xml
+++ b/app/src/main/res/values-vi-rVN/strings.xml
@@ -1,26 +1,26 @@
- %1$s Tùy chọn
+ Tùy Chọn %1$sThoátĐộ lệchLưuWearGiới thiệu
- Khi bật tính năng Autosense, hãy nhớ nhập đầy đủ tất cả lượng carb đã ăn. Nếu không, sự lệch carb sẽ bị nhận diện sai thành thay đổi độ nhạy insulin!!
+ Khi dùng Autosense, cần nhập đủ lượng carb đã ăn. Nếu không, hệ thống sẽ hiểu sai lệch carb thành thay đổi độ nhạy insulinKHÔNG HỢP LỆTăng dần âm lượng cho cảnh báo và thông báoCảnh báo cục bộ
- Cảnh báo khi thiếu dữ liệu BG
+ Cảnh báo khi mất dữ liệu ĐHCảnh báo khi bơm mất kết nốiNgưỡng mất kết nối bơm [phút]
- Cảnh báo khi cần carb
+ Cảnh báo khi cần bổ sung carbMở điều hướngĐóng điều hướngXóa mụcSắp xếp các mụcĐơn vịXác thực không thành công
- Cannula
+ Kim luồnChưa thiết lập nhận dạng ở chế độ phát triểnXóa mục đã chọn
diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml
new file mode 100644
index 00000000000..6da0e74aee8
--- /dev/null
+++ b/app/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,7 @@
+
+
+
+ localhost
+ 127.0.0.1
+
+
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
index 1a244ae5ed1..d20423b908e 100644
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/src/main/kotlin/Versions.kt
@@ -4,7 +4,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
@Suppress("ConstPropertyName")
object Versions {
- const val appVersion = "3.4.0.0"
+ const val appVersion = "3.4.1.0"
const val versionCode = 1500
const val compileSdk = 36
diff --git a/buildSrc/src/main/kotlin/android-app-dependencies.gradle.kts b/buildSrc/src/main/kotlin/android-app-dependencies.gradle.kts
index f8619831472..04121028f77 100644
--- a/buildSrc/src/main/kotlin/android-app-dependencies.gradle.kts
+++ b/buildSrc/src/main/kotlin/android-app-dependencies.gradle.kts
@@ -42,6 +42,10 @@ android {
targetCompatibility = Versions.javaVersion
}
+ kotlinOptions {
+ freeCompilerArgs = freeCompilerArgs + "-opt-in=kotlin.time.ExperimentalTime"
+ }
+
lint {
checkReleaseBuilds = false
disable += "MissingTranslation"
diff --git a/buildSrc/src/main/kotlin/android-module-dependencies.gradle.kts b/buildSrc/src/main/kotlin/android-module-dependencies.gradle.kts
index c95e2635364..941f23f6497 100644
--- a/buildSrc/src/main/kotlin/android-module-dependencies.gradle.kts
+++ b/buildSrc/src/main/kotlin/android-module-dependencies.gradle.kts
@@ -35,6 +35,10 @@ android {
targetCompatibility = Versions.javaVersion
}
+ kotlinOptions {
+ freeCompilerArgs = freeCompilerArgs + "-opt-in=kotlin.time.ExperimentalTime"
+ }
+
lint {
checkReleaseBuilds = false
disable += "MissingTranslation"
diff --git a/core/data/src/main/kotlin/app/aaps/core/data/configuration/Constants.kt b/core/data/src/main/kotlin/app/aaps/core/data/configuration/Constants.kt
index d524ad7426f..34564988f39 100644
--- a/core/data/src/main/kotlin/app/aaps/core/data/configuration/Constants.kt
+++ b/core/data/src/main/kotlin/app/aaps/core/data/configuration/Constants.kt
@@ -11,7 +11,7 @@ object Constants {
const val notificationID = 556677
// OpenAPS algorithm
- const val ALLOW_SMB_WITH_HIGH_TT = 100
+ const val NORMAL_TARGET_MGDL = 99 // 5.5 mmol/l = 99.1 mg/dL; use 99 to ensure consistent behavior across mg/dL and mmol/l units
// SMS COMMUNICATOR
const val remoteBolusMinDistance = 15 * 60 * 1000L
diff --git a/core/data/src/main/kotlin/app/aaps/core/data/model/RM.kt b/core/data/src/main/kotlin/app/aaps/core/data/model/RM.kt
index ada5eb92293..6b0822374aa 100644
--- a/core/data/src/main/kotlin/app/aaps/core/data/model/RM.kt
+++ b/core/data/src/main/kotlin/app/aaps/core/data/model/RM.kt
@@ -63,6 +63,7 @@ data class RM(
fun isClosedLoopOrLgs() = this == CLOSED_LOOP || this == CLOSED_LOOP_LGS
fun isLoopRunning() = this == OPEN_LOOP || this == CLOSED_LOOP || this == CLOSED_LOOP_LGS
fun isSuspended() = this == DISCONNECTED_PUMP || this == SUSPENDED_BY_PUMP || this == SUSPENDED_BY_USER || this == SUSPENDED_BY_DST || this == SUPER_BOLUS
+ fun isPumpSuspended() = this == DISCONNECTED_PUMP || this == SUSPENDED_BY_PUMP
// DISABLED_LOOP is added to "mustBeTemporary" to be properly rendered in NS
fun mustBeTemporary() = this == DISCONNECTED_PUMP || this == SUSPENDED_BY_PUMP || this == SUSPENDED_BY_USER || this == SUSPENDED_BY_DST || this == SUPER_BOLUS || this == DISABLED_LOOP
diff --git a/core/data/src/main/kotlin/app/aaps/core/data/pump/defs/PumpType.kt b/core/data/src/main/kotlin/app/aaps/core/data/pump/defs/PumpType.kt
index 2de1a2c3f2b..81d1d68283c 100644
--- a/core/data/src/main/kotlin/app/aaps/core/data/pump/defs/PumpType.kt
+++ b/core/data/src/main/kotlin/app/aaps/core/data/pump/defs/PumpType.kt
@@ -7,7 +7,7 @@ package app.aaps.core.data.pump.defs
enum class PumpType(
val description: String,
private val manufacturer: ManufacturerType? = null,
- private val model: String = "NONE",
+ val model: String = "NONE",
private val bolusSize: Double = 0.0,
private val specialBolusSize: DoseStepSize? = null,
private val extendedBolusSettings: DoseSettings? = null,
diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BlePreCheck.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BlePreCheck.kt
index 93fccd2825c..8f5500f6b23 100644
--- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BlePreCheck.kt
+++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BlePreCheck.kt
@@ -4,5 +4,6 @@ import androidx.appcompat.app.AppCompatActivity
interface BlePreCheck {
- fun prerequisitesCheck(activity: AppCompatActivity): Boolean
+ fun prerequisitesCheck(activity: AppCompatActivity, additionalPermissions: List? = null): Boolean
+
}
\ No newline at end of file
diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BolusProgressData.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BolusProgressData.kt
index b6c796a2fb4..30d590b5660 100644
--- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BolusProgressData.kt
+++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/pump/BolusProgressData.kt
@@ -20,6 +20,7 @@ object BolusProgressData {
bolusEnded = false
stopPressed = false
status = ""
+ wearStatus = ""
percent = 0
}
@@ -48,6 +49,7 @@ object BolusProgressData {
* Last received status update
*/
var status = ""
+ var wearStatus = ""
var percent = 0
var bolusEnded = false
diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/events/EventOverviewBolusProgress.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/events/EventOverviewBolusProgress.kt
index 3e33b7f45f7..a86339558fa 100644
--- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/events/EventOverviewBolusProgress.kt
+++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/rx/events/EventOverviewBolusProgress.kt
@@ -8,12 +8,13 @@ import kotlin.math.min
/**
* Custom status message and percent
*/
-class EventOverviewBolusProgress(status: String, val id: Long? = null, percent: Int? = null) : Event() {
+class EventOverviewBolusProgress(status: String, val id: Long? = null, percent: Int? = null, wearStatus: String? = null) : Event() {
init {
if (id == BolusProgressData.id || id == null) {
BolusProgressData.status = status
percent?.let { BolusProgressData.percent = it }
+ BolusProgressData.wearStatus = wearStatus ?: status
}
}
@@ -22,9 +23,10 @@ class EventOverviewBolusProgress(status: String, val id: Long? = null, percent:
*/
constructor(rh: ResourceHelper, delivered: Double, id: Long? = null) :
this(
- rh.gs(R.string.bolus_delivering, delivered),
+ status = rh.gs(R.string.bolus_delivering, delivered),
id = id,
- percent = min((delivered / BolusProgressData.insulin * 100).toInt(), 100)
+ percent = min((delivered / BolusProgressData.insulin * 100).toInt(), 100),
+ wearStatus = rh.gs(R.string.bolus_delivered_so_far, delivered, BolusProgressData.insulin)
)
/**
@@ -37,6 +39,9 @@ class EventOverviewBolusProgress(status: String, val id: Long? = null, percent:
if (percent == 100) rh.gs(R.string.bolus_delivered_successfully, BolusProgressData.insulin)
else rh.gs(R.string.bolus_delivering, BolusProgressData.insulin * percent / 100.0),
id = id,
- percent = min(percent, 100)
- )
+ percent = min(percent, 100),
+ wearStatus =
+ if (percent == 100) rh.gs(R.string.bolus_delivered_successfully, BolusProgressData.insulin)
+ else rh.gs(R.string.bolus_delivered_so_far, BolusProgressData.insulin * percent / 100.0, BolusProgressData.insulin)
+ )
}
\ No newline at end of file
diff --git a/core/interfaces/src/main/res/values-cs-rCZ/strings.xml b/core/interfaces/src/main/res/values-cs-rCZ/strings.xml
index 7807bd88acc..a6df4ee3fda 100644
--- a/core/interfaces/src/main/res/values-cs-rCZ/strings.xml
+++ b/core/interfaces/src/main/res/values-cs-rCZ/strings.xml
@@ -2,6 +2,7 @@
Podávání %1$.2fU
+ %1$.2fU / %2$.2fU podánoBolus %1$.2fU byl úspěšně aplikovánZměněn ovladač pumpy.
diff --git a/core/interfaces/src/main/res/values-es-rES/strings.xml b/core/interfaces/src/main/res/values-es-rES/strings.xml
index 558b55ce9bc..14c06339da9 100644
--- a/core/interfaces/src/main/res/values-es-rES/strings.xml
+++ b/core/interfaces/src/main/res/values-es-rES/strings.xml
@@ -2,6 +2,7 @@
Entregando %1$.2fU
+ %1$.2fU / %2$.2fU entregadoBolo %1$.2fU entregado con éxitoControlador de bomba cambiado
diff --git a/core/interfaces/src/main/res/values-it-rIT/strings.xml b/core/interfaces/src/main/res/values-it-rIT/strings.xml
index a2b67247e65..4b98976f7ba 100644
--- a/core/interfaces/src/main/res/values-it-rIT/strings.xml
+++ b/core/interfaces/src/main/res/values-it-rIT/strings.xml
@@ -2,6 +2,7 @@
Erogazione di %1$.2fU
+ %1$.2f U / %2$.2f U erogateBolo di %1$.2fU erogato con successoDriver micro cambiato.
diff --git a/core/interfaces/src/main/res/values-nb-rNO/strings.xml b/core/interfaces/src/main/res/values-nb-rNO/strings.xml
index dd8c6a90af5..7aad400fdb0 100644
--- a/core/interfaces/src/main/res/values-nb-rNO/strings.xml
+++ b/core/interfaces/src/main/res/values-nb-rNO/strings.xml
@@ -2,6 +2,7 @@
Leverer %1$.2f E
+ %1$.2f E / %2$.2f E levertBolus på %1$.2f E ble levertPumpedriver er endret.
diff --git a/core/interfaces/src/main/res/values-nl-rNL/strings.xml b/core/interfaces/src/main/res/values-nl-rNL/strings.xml
index d3a3e3e7b5f..edbf0b2ce51 100644
--- a/core/interfaces/src/main/res/values-nl-rNL/strings.xml
+++ b/core/interfaces/src/main/res/values-nl-rNL/strings.xml
@@ -2,6 +2,7 @@
Toedienen van %1$.2fE
+ %1$.2f E / %2$.2f E toegediendBolus van %1$.2fE succesvol toegediendPomp stuurprogramma gewijzigd.
@@ -12,6 +13,18 @@
%1$.1fu geleden%1$.1f dagen geleden%1$.0f dagen geleden
+
+ %1$s dag %2$s uur geleden
+ %1$s dagen %2$s uur geleden
+
+
+ %1$s uur geleden
+ %1$s uur geleden
+
+
+ een moment geleden
+ %1$s minuten geleden
+ seconden geledenover %1$.0f dagenbinnen %1$.0f dagen
diff --git a/core/interfaces/src/main/res/values-pl-rPL/strings.xml b/core/interfaces/src/main/res/values-pl-rPL/strings.xml
index b377814aad3..139012ff9d8 100644
--- a/core/interfaces/src/main/res/values-pl-rPL/strings.xml
+++ b/core/interfaces/src/main/res/values-pl-rPL/strings.xml
@@ -1,12 +1,36 @@
+ Dostarczam %1$.2fU
+ Bolus %1$.2fU dostarczony prawidłowoZmieniono ster. pompy.
+ %1$dmin temu
+ %1$ds temu%1$d minut temu
+ %1$.1fh temu%1$.1f dni temu%1$.0f dni temu
+
+ %1$s dzień %2$s godziny temu
+ %1$s dni %2$s godziny temu
+ %1$s dni %2$s godziny temu
+ %1$s dni %2$s godziny temu
+
+
+ %1$s godzinę temu
+ %1$s godziny temu
+ %1$s godzin temu
+ %1$s godzin temu
+
+
+ chwilę temu
+ %1$s minuty temu
+ %1$s minut temu
+ %1$s minut temu
+
+ sekundy temuza %1$.0f dniza %1$.0f dnih
@@ -32,6 +56,7 @@
Łączenie przez %1$d sNawiązywanie połączeniaPołączono
+ ZautoryzowanoRozłączanieOczekiwanie na rozłączenie
@@ -65,4 +90,8 @@
Domyślna tarcza zegarka, w tym zewnętrzne podglądy dla obserwujących. Możesz kliknąć na przycisk EKSPORT TARCZY aby wygenerować szablonDomyślna TarczaWięcej tarcz zegarka
+ %1$.2f U/h @%2$s %3$d/%4$d\'
+ %1$.2f%% @%2$s %3$d/%4$d\'
+ E %1$.2f U/h @%2$s %3$d/%4$d min
+ Na zawsze
diff --git a/core/interfaces/src/main/res/values-ru-rRU/strings.xml b/core/interfaces/src/main/res/values-ru-rRU/strings.xml
index ff8835540e1..c627c40fc98 100644
--- a/core/interfaces/src/main/res/values-ru-rRU/strings.xml
+++ b/core/interfaces/src/main/res/values-ru-rRU/strings.xml
@@ -2,14 +2,15 @@
Подается %1$.2fед
+ Введено %1$.2fед / %2$.2fедБолюс %1$.2fед. введен успешноДрайвер помпы изменен.
- %1$d мин. назад
+ %1$d мин назад%1$d сек назад%1$d минут назад
- %1$.1fч. назад
+ %1$.1fч назад%1$s дн назад%1$s дн назад
@@ -55,9 +56,9 @@
Связь установлена за %1$d секПодтверждение связи
- соединение установлено
+ ПодключеноАвторизовано
- разъединение
+ РазъединениеОжидание разъединенияСоздано: %1$s
@@ -91,7 +92,7 @@
Циферблат по умолчаниюЕще циферблаты%1$.2f ед/ч @%2$s %3$d/%4$d\'
- %1$.2f ед/ч @%2$s %3$d/%4$d\'
+ %1$.2f % @%2$s %3$d/%4$d\'E %1$.2f ед/ч @%2$s %3$d/%4$d минНавсегда
diff --git a/core/interfaces/src/main/res/values-sk-rSK/strings.xml b/core/interfaces/src/main/res/values-sk-rSK/strings.xml
index 4452b164e52..15060751e7d 100644
--- a/core/interfaces/src/main/res/values-sk-rSK/strings.xml
+++ b/core/interfaces/src/main/res/values-sk-rSK/strings.xml
@@ -1,8 +1,9 @@
- Podávanie %1$.2fJI
- Bolus %1$.2fJI podaný úspešne
+ Podávanie %1$.2fU
+ %1$.2fU / %2$.2fU podaných
+ Bolus %1$.2fU podaný úspešneOvládač pumpy zmenený.
@@ -90,8 +91,8 @@
Predvolený ciferník vrátane externých zobrazení pre sledovateľov, môžete kliknúť na tlačidlo EXPORTOVAŤ CIFERNÍK ak chcete vygenerovať šablónuPredvolený ciferníkĎalšie ciferníky
- %1$.2f JI/h @%2$s %3$d/%4$d
+ %1$.2f U/h @%2$s %3$d/%4$d%1$.2f%% @%2$s %3$d/%4$d
- E %1$.2f JI/h @%2$s %3$d/%4$d min
+ E %1$.2f U/h @%2$s %3$d/%4$d minNavždy
diff --git a/core/interfaces/src/main/res/values-vi-rVN/strings.xml b/core/interfaces/src/main/res/values-vi-rVN/strings.xml
index 96d43dcdd5d..e72cad1e0c7 100644
--- a/core/interfaces/src/main/res/values-vi-rVN/strings.xml
+++ b/core/interfaces/src/main/res/values-vi-rVN/strings.xml
@@ -2,6 +2,7 @@
Đang tiêm %1$.2f U
+ Đã truyền %1$.2fU trên %2$.2fUĐã tiêm Bolus thành công %1$.2f UThay trình điều khiển Bơm.
@@ -61,14 +62,14 @@
Hiển thị IOBHiển thị chi tiết IOBHiển thị COB
- Hiển thị Delta
- Hiển thị chi tiết Delta
+ Hiển thị độ lệch
+ Hiển thị chi tiết độ lệchHiển thị AvgDeltaHiển thị mục tiêu tạm thờiHiển thị mức ống chứaHiển thị pin điện thoạiHiển thị mức pin Rig
- Hiển thị liều basal
+ Hiển thị liều nềnHiển thị trạng thái vòng lặpHiển thị đường huyếtHiển thị BGI
diff --git a/core/interfaces/src/main/res/values-zh-rTW/strings.xml b/core/interfaces/src/main/res/values-zh-rTW/strings.xml
index 062ebc3796b..61716ba879e 100644
--- a/core/interfaces/src/main/res/values-zh-rTW/strings.xml
+++ b/core/interfaces/src/main/res/values-zh-rTW/strings.xml
@@ -2,6 +2,7 @@
正在注射 %1$.2fU
+ %1$.2fU / %2$.2fU 已輸送注射 %1$.2fU 已成功完成幫浦驅動程式已更改。
diff --git a/core/interfaces/src/main/res/values/strings.xml b/core/interfaces/src/main/res/values/strings.xml
index 486268e11dd..379ca57538e 100644
--- a/core/interfaces/src/main/res/values/strings.xml
+++ b/core/interfaces/src/main/res/values/strings.xml
@@ -2,6 +2,7 @@
Delivering %1$.2fU
+ %1$.2fU / %2$.2fU deliveredBolus %1$.2fU delivered successfully
diff --git a/core/keys/src/main/kotlin/app/aaps/core/keys/BooleanKey.kt b/core/keys/src/main/kotlin/app/aaps/core/keys/BooleanKey.kt
index ba1d1ff6607..fece627f4a2 100644
--- a/core/keys/src/main/kotlin/app/aaps/core/keys/BooleanKey.kt
+++ b/core/keys/src/main/kotlin/app/aaps/core/keys/BooleanKey.kt
@@ -120,4 +120,13 @@ enum class BooleanKey(
SiteRotationManagePump("site_rotation_manage_pump", defaultValue = false),
SiteRotationManageCgm("site_rotation_manage_cgm", defaultValue = false),
+ // Export destination settings
+ ExportAllCloudEnabled("export_all_cloud_enabled", defaultValue = false),
+ ExportLogEmailEnabled("export_log_email_enabled", defaultValue = true),
+ ExportLogCloudEnabled("export_log_cloud_enabled", defaultValue = false),
+ ExportSettingsLocalEnabled("export_settings_local_enabled", defaultValue = true),
+ ExportSettingsCloudEnabled("export_settings_cloud_enabled", defaultValue = false),
+ ExportCsvLocalEnabled("export_csv_local_enabled", defaultValue = true),
+ ExportCsvCloudEnabled("export_csv_cloud_enabled", defaultValue = false),
+
}
\ No newline at end of file
diff --git a/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt b/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt
index 89a881088cf..62f46309c81 100644
--- a/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt
+++ b/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt
@@ -51,6 +51,11 @@ enum class StringKey(
NsClientWifiSsids("ns_wifi_ssids", "", dependency = BooleanKey.NsClientUseWifi),
NsClientAccessToken("nsclient_token", "", isPassword = true),
+ // Google Drive settings
+ GoogleDriveStorageType("google_drive_storage_type", "local"),
+ GoogleDriveFolderId("google_drive_folder_id", ""),
+ GoogleDriveRefreshToken("google_drive_refresh_token", "", isPassword = true),
+
PumpCommonBolusStorage("pump_sync_storage_bolus", ""),
PumpCommonTbrStorage("pump_sync_storage_tbr", ""),
}
\ No newline at end of file
diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt
index 2a7460f56a1..08c8dc5af26 100644
--- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt
+++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt
@@ -1,5 +1,6 @@
package app.aaps.core.objects.extensions
+import app.aaps.core.data.configuration.Constants
import app.aaps.core.data.model.BS
import app.aaps.core.data.model.EB
import app.aaps.core.data.model.TB
@@ -84,7 +85,7 @@ fun EB.iobCalc(
val result = IobTotal(time)
val realDuration = getPassedDurationToTimeInMinutes(time)
var sensitivityRatio = lastAutosensResult.ratio
- val normalTarget = 100.0
+ val normalTarget = Constants.NORMAL_TARGET_MGDL.toDouble()
if (exerciseMode && isTempTarget && profile.getTargetMgdl() >= normalTarget + 5) {
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt
index a96be727b04..e9c71dfea84 100644
--- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt
+++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt
@@ -1,5 +1,6 @@
package app.aaps.core.objects.extensions
+import app.aaps.core.data.configuration.Constants
import app.aaps.core.data.model.BS
import app.aaps.core.data.model.TB
import app.aaps.core.data.time.T
@@ -111,7 +112,7 @@ fun TB.iobCalc(
val realDuration = getPassedDurationToTimeInMinutes(time)
var netBasalAmount = 0.0
var sensitivityRatio = lastAutosensResult.ratio
- val normalTarget = 100.0
+ val normalTarget = Constants.NORMAL_TARGET_MGDL.toDouble()
if (exerciseMode && isTempTarget && profile.getTargetMgdl() >= normalTarget + 5) {
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
diff --git a/core/objects/src/main/res/drawable/ic_none.xml b/core/objects/src/main/res/drawable/ic_none.xml
index 7bfd47e2359..1067ff74ccc 100644
--- a/core/objects/src/main/res/drawable/ic_none.xml
+++ b/core/objects/src/main/res/drawable/ic_none.xml
@@ -1,7 +1,5 @@
-
-
-
+
diff --git a/core/ui/src/main/kotlin/app/aaps/core/ui/toast/ToastUtils.kt b/core/ui/src/main/kotlin/app/aaps/core/ui/toast/ToastUtils.kt
index c0bd135b48d..e041e633079 100644
--- a/core/ui/src/main/kotlin/app/aaps/core/ui/toast/ToastUtils.kt
+++ b/core/ui/src/main/kotlin/app/aaps/core/ui/toast/ToastUtils.kt
@@ -38,6 +38,10 @@ object ToastUtils {
graphicalToast(ctx, ctx?.getString(id), R.drawable.ic_toast_info, true)
}
+ fun longInfoToast(ctx: Context?, string: String?) {
+ graphicalToast(ctx, string, R.drawable.ic_toast_info, false)
+ }
+
fun okToast(ctx: Context?, string: String?, isShort: Boolean = true) {
graphicalToast(ctx, string, R.drawable.ic_toast_check, isShort)
}
diff --git a/core/ui/src/main/res/drawable/ic_directory.xml b/core/ui/src/main/res/drawable/ic_directory.xml
index 17ca703adb5..ed024e7343c 100644
--- a/core/ui/src/main/res/drawable/ic_directory.xml
+++ b/core/ui/src/main/res/drawable/ic_directory.xml
@@ -1,5 +1,5 @@
-
+
-
+
diff --git a/core/ui/src/main/res/values-nb-rNO/strings.xml b/core/ui/src/main/res/values-nb-rNO/strings.xml
index 7860395e002..a951011e1e8 100644
--- a/core/ui/src/main/res/values-nb-rNO/strings.xml
+++ b/core/ui/src/main/res/values-nb-rNO/strings.xml
@@ -157,7 +157,7 @@
LoginLogg utPrime/fylling
- Rotasjon av stedsområder
+ Rotasjon av stedInsulinAvbryt midlertidig målLukket Loop
diff --git a/core/ui/src/main/res/values-nl-rNL/strings.xml b/core/ui/src/main/res/values-nl-rNL/strings.xml
index a6e98c7072e..66bed9d55fc 100644
--- a/core/ui/src/main/res/values-nl-rNL/strings.xml
+++ b/core/ui/src/main/res/values-nl-rNL/strings.xml
@@ -89,6 +89,7 @@
AlarmExporteer instellingenLoop deactiveren
+ Loop uitgeschakeldHervat loopOnderbreek loopDuur [min]
@@ -102,6 +103,7 @@
Naam:TijdWiFi SSID
+ Laden…NotitiesVerwijderNieuwe toevoegen
@@ -115,8 +117,10 @@
TijdsduurgPomp onderbreken
+ Pomp is actiefNiet ingesteldLoop pauzeren
+ Loop onderbroken voor zomer/wintertijd (DST)TrendpijlAutosensnodig
@@ -151,12 +155,17 @@
Basaal IOBOngeldigAanmelden
+ UitloggenPrime/Vul
+ Site rotatieInsulineStop tijdelijk doelClosed loopOpen loopStop bij laag
+ Pomp niet verbonden
+ Pomp is onderbroken
+ Modus teruggezetDIAKH-ratioISF
@@ -215,6 +224,8 @@
Bewegen : %1$sInfuus wisselCGM Sens. ingebracht
+ Pomp sites
+ CGM sitesCGM Sens. StartCGM Sensor stoppenHulphond waarschuwing
@@ -230,6 +241,7 @@
OpenAPS OfflinePomp bat. wisselTijdelijk streefdoel
+ Actieve modusTijdelijk streefdoelTijdelijk streefdoel annulerenBolus wizard
@@ -247,6 +259,39 @@
LoopNSOpnemen
+ Borst rechts
+ Borst links
+ Rechter bovenarm
+ Linker bovenarm
+ Rechter bovenarm achterzijde
+ Linker bovenarm achterzijde
+ Rechterbovenkant buik buitenzijde
+ Linker bovenkant buik buitenzijde
+ Rechter onderkant buik buitenzijde
+ Linker onderkant buik buitenzijde
+ Rechter bovenkant buik voorzijde
+ Linker bovenkant buik voorzijde
+ Rechter onderkant buik voorzijde
+ Linker onderkant buik voorzijde
+ Rechterbil
+ Linkerbil
+ Buitenzijde bovenbeen hoog, rechts
+ Buitenzijde bovenbeen hoog, links
+ Buitenzijde bovenbeen laag, rechts
+ Buitenzijde bovenbeen laag, links
+ Voorzijde bovenbeen hoog, rechts
+ Voorzijde bovenbeen hoog, links
+ Voorzijde bovenbeen laag, rechts
+ Voorzijde bovenbeen laag, links
+ Omhoog
+ Omhoog rechts
+ Rechts
+ Omlaag rechts
+ Omlaag
+ Omlaag links
+ Links
+ Omhoog links
+ MiddenConnectie verlopen
@@ -292,6 +337,8 @@
LGS LOOP MODUSOPEN LOOP MODUSLOOP UITGESCHAKELD
+ LOOP GEACTIVEERD
+ POMP ACTIEFVERBIND OPNIEWVERBINDING VERBREKENHERVATTEN
@@ -304,7 +351,9 @@
ANNULEER VERLENGDE BOLUSSTOP TIJDELIJK DOELCAREPORTAL
+ SENSOR LOCATIEINFUUSPLEK WIJZIGING
+ SITE LOCATIERESERVOIRWISSELKALIBRERENVUL BOLUS
@@ -367,6 +416,9 @@
LOOP VERANDERDLOOP VERWIJDERDOVERIGE
+ BEDRIJFSMODE
+ BEDRIJFSMODE VERWIJDERD
+ BEDRIJFSMODE GEWIJZIGDProfiel laag doelProfiel hoog doel
@@ -591,4 +643,5 @@
Basaal: %1$.2f%% (%2$.2f E/h) Duur: %3$d min ]]>Basaal: %1$.2f E/h (%2$.2f%%) Duur: %3$d min ]]>
+ "AAPS speelt geluid"
diff --git a/core/ui/src/main/res/values-pl-rPL/strings.xml b/core/ui/src/main/res/values-pl-rPL/strings.xml
index a6d05fc04ce..b27cdfd50d6 100644
--- a/core/ui/src/main/res/values-pl-rPL/strings.xml
+++ b/core/ui/src/main/res/values-pl-rPL/strings.xml
@@ -89,6 +89,7 @@
AlarmEksport ustawieńWyłącz pętle
+ Pętla wyłączonaWznów pętlęWstrzymaj pętleCzas trwania [min]
@@ -102,6 +103,7 @@
Nazwa:CzasWiFi SSID
+ Ładowanie…NotatkiUsuńDodaj nowy
@@ -115,8 +117,10 @@
Czas trwaniagPompa wstrzymana
+ Pompa uruchomionaNie skonfigurowanoPętla wstrzymana
+ Pętla zawieszona przez zmianę czasu (na letni lub zimowy)Strzałka trenduAuto senswym
@@ -151,12 +155,17 @@
IOB z bazyNIEPRAWIDŁOWYZaloguj się
+ Wyloguj sięRozpocznij/Wypełnij
+ Zmiana miejscaInsulinaZatrzymaj cel tymczasowyZamknięta pętlaOtwarta pętlaZawieszenie przy niskiej glikemii
+ Pompa odłączona
+ Pompa wstrzymana
+ Tryb przywróconyDIAICISF
@@ -215,6 +224,8 @@
Ćwiczenie: %1$sZmiana wkłuciaZałożenie sensora CGM
+ Miejsca pompy/wkłucia
+ Miejsca SensoraUruchomienie sensora CGMZatrzymanie sensora CGMAlarm D.A.D.
@@ -230,6 +241,7 @@
OpenAPS Rozłączony (Offline)Zmiana baterii pompyCel tymczasowy (TT)
+ Tryb pracyWartość celu tymczasowegoOdrzuć Cel tymczasowyKalkulator bolusa
@@ -247,6 +259,39 @@
PętlaNSWpis
+ Prawa strona klatki
+ Lewa strona klatki
+ Górny bok prawego ramienia
+ Górny bok lewego ramienia
+ Górny tył prawego ramienia
+ Górny tył lewego ramienia
+ Górny prawy bok brzucha
+ Górny lewy bok brzucha
+ Dolny prawy bok brzucha
+ Dolny lewy bok brzucha
+ Górny prawy przód brzucha
+ Górny lewy przód brzucha
+ Dolny prawy przód brzucha
+ Dolny lewy przód brzucha
+ Prawy pośladek
+ Lewy pośladek
+ Górny bok prawego uda
+ Górny bok lewego uda
+ Dolny bok prawego uda
+ Dolny bok lewego uda
+ Górny przód prawego uda
+ Górny przód lewego uda
+ Dolny przód prawego uda
+ Dolny przód lewego uda
+ Góra
+ Góra - Prawo
+ Prawo
+ Dół - Prawo
+ Dół
+ Dół - Lewo
+ Lewo
+ Góra - Lewo
+ ŚrodekPrzekroczono limit czasu połączenia
@@ -292,6 +337,8 @@
TRYB ZAWIESZENIA PRZY NISKIEJ GLIKEMI (LGS)TRYB OTWARTEJ PĘTLIPĘTLA WYŁĄCZONA
+ PĘTLA WZNOWIONA
+ POMPA DZIAŁAPOŁĄCZ PONOWNIEROZŁĄCZWZNÓW
@@ -304,7 +351,9 @@
ANULUJ ROZSZERZONY BOLUSANULUJ CEL TYMCZASOWYPORTALOPIEKI
+ MIEJSCE SENSORAZMIANA MIEJSCA WKŁUCIA
+ MIEJSCE WKŁUCIAZMIANA ZBIORNIKAKALIBRACJABOLUS NA WYPEŁNIENIE
@@ -367,6 +416,9 @@
PĘTLA ZMIENIONAPĘTLA USUNIĘTAINNE
+ TRYB DZIAŁANIA
+ USUNIĘTO TRYB DZIAŁANIA
+ ZAKTUALIZOWANO TRYB DZIAŁANIADolna granica celu profiluGórna granica celu profilu
@@ -407,6 +459,12 @@
%1$.0f%%BazaBaza %
+ Wrażliwość
+ ISF dla Kalkulatora i Absorpcji węglowodanów: %1$.1f
+ Wartość Autosens: %.0f%%
+ AS: %.0f%%
+ Autosens w algorytmie: %.0f%%
+ Alg: %.0f%%plikużytkownik
@@ -591,4 +649,5 @@
Dawka: %1$.2f%% (%2$.2f U/h) Czas: %3$d min ]]>Dawka: %1$.2f U/h (%2$.2f%%) Czas: %3$d min ]]>
+ "AAPS odtwarza dźwięk"
diff --git a/core/ui/src/main/res/values-sk-rSK/strings.xml b/core/ui/src/main/res/values-sk-rSK/strings.xml
index 214cc79fd0e..3c336c09099 100644
--- a/core/ui/src/main/res/values-sk-rSK/strings.xml
+++ b/core/ui/src/main/res/values-sk-rSK/strings.xml
@@ -9,12 +9,12 @@
Celkový IOB:DCPumpa nedostupná
- JI
- %1$.2f JI/h
+ U
+ %1$.2f U/hPumpa nie je inicializovaná, profil nenastavený!Chyba pri aktualizovaní bazálneho profiluNenačítaný žiadny platný bazál z pumpy
- IOB obmedzený na %1$.1f JI: %2$s
+ IOB obmedzený na %1$.1f U: %2$sUZAVRETÝ OKRUH DEAKTIVOVANÝ OBMEDZENÍMTyp udalostiZnova načítať
@@ -50,10 +50,10 @@
PozastavenéCDD celkomStaré dáta
- Podávanie %1$.2f J inzulínu
+ Podávanie %1$.2f U inzulínuČakám na pumpuAAPS spustený
- %1$+.2f JI
+ %1$+.2f U%1$d g%1$.2f h%1$d min
@@ -175,12 +175,12 @@
Aktívny inzulín (IOB)CIELE:VÝSLEDOK OAPS:
- %1$.2f JI ( %2$.2f JI/h )
- %1$.2f JI/h (%2$.2fE) @%3$s
- %1$.2f JI/h @%2$s
+ %1$.2f U ( %2$.2f U/h )
+ %1$.2f U/h (%2$.2fE) @%3$s
+ %1$.2f U/h @%2$s%1$.0f%% @%2$s
- E %1$.2f JI/h @%2$s %3$s/%4$s min
- %1$.2f JI/h %2$s/%3$s\'
+ E %1$.2f U/h @%2$s %3$s/%4$s min
+ %1$.2f U/h %2$s/%3$s\'Exportovať nastaveniaPovolenie na zisťovanie polohy nebolo udelené. Povoľte v nastaveniach systému Android.
@@ -192,9 +192,9 @@
Bazálne hodnoty nie sú zarovnané na celé hodiny: %1$sHodnota bazálu nahradená minimálnou možnou: %1$sHodnota bazálu nahradená maximálnou možnou: %1$s
- /JI
- JI/h
- g/JI
+ /U
+ U/h
+ g/USpustiť profil %1$d%% na %2$d min
@@ -435,7 +435,7 @@
»%1$s« %2$.2f je mimo pevne nastavených limitovHodnota bazálu
- BOLUS %1$.2f JI
+ BOLUS %1$.2f USACHARIDY %1$d gPREDĹŽENÝ BOLUS %1$.2f U %2$d minNačítavanie udalostí
@@ -446,10 +446,10 @@
NAČÍTAŤ CDDNASTAVIŤ PROFILNASTAVIŤ POUŽ. NASTAVENIA
- SMB BOLUS %1$.2f JI
+ SMB BOLUS %1$.2f USPUSTIŤ PUMPUZASTAVIŤ PUMPU
- DOČAS. BAZÁL %1$.2f JI/h %2$d min
+ DOČAS. BAZÁL %1$.2f U/h %2$d minDOČAS. BAZÁL %1$d%% %2$d minINSIGHT NASTAVIŤ TBR CEZ OZNÁMENIENAČÍTASTAV %1$s
@@ -482,7 +482,7 @@
!!!!! Detekovaná pomalá absorbcia sacharidov: %2$d%% času. Prekontrolujte kalkuláciu. COB môže byť úplne iné, môže byť podaného viac inzulínu!!!!!]]>Podaj túto časť z výsledku kalkulácie [%]Časový limit starej glykémie [min]
- Použité obmedzenie bolusu: %1$.2f JI na %2$.2f JI
+ Použité obmedzenie bolusu: %1$.2f U na %2$.2f UBolus bude iba zaznamenaný (nie pumpou vydaný)Spustiť výstrahu, keď je čas na jedloŽiadna akcia nevybraná, nič sa neudeje
@@ -493,14 +493,14 @@
Neznáme COB! Chýbajú glykémie, alebo bola práve reštartovaná aplikácia?Sacharidy mimo povolený rozsah!Kalk (IC: %1$.1f, ISF: %2$.1f)
- Sacharidy: %1$.2fJI
- COB: %1$.0fg %2$.2fJI
- Gly: %1$.2fJI
- IOB: %1$.2fJI
- Superbolus: %1$.2fJI
- 15min trend: %1$.2fJI
- Percentá: %1$.2fJI x %2$d%% ≈ %3$.2fJI
- Inzulín mimo povolený rozsah!\nNie je možné podať %1$.2fJI
+ Sacharidy: %1$.2fU
+ COB: %1$.0fg %2$.2fU
+ Gly: %1$.2fU
+ IOB: %1$.2fU
+ Superbolus: %1$.2fU
+ 15min trend: %1$.2fU
+ Percentá: %1$.2fU x %2$d%% ≈ %3$.2fU
+ Inzulín mimo povolený rozsah!\nNie je možné podať %1$.2fUDC: %1$s%1$s do %2$sPumpa nedostupná!
@@ -529,7 +529,7 @@
OdpojenéPripájanieKliknuté pripojiť k pumpe
- %1$.0f / %2$d JI
+ %1$.0f / %2$d UJednotiek za deňIkona pumpyZobraziť profil
@@ -548,11 +548,11 @@
Inicializácia ...%1$d s
- Max bazál obmedzený na %1$.2f JI/h: %2$s
+ Max bazál obmedzený na %1$.2f U/h: %2$slimit pumpyBazál obmedzený na %1$d%%: %2$spožadovaná kladná hodnota
- Bolus obmedzený na %1$.1f JI: %2$s
+ Bolus obmedzený na %1$.1f U: %2$sPotvrdenieSpráva
@@ -642,12 +642,12 @@
SoNe
- %1$.1f JI
- %1$.2f JI
- Hodnota: %1$.2f%% (%2$.2f JI/h) Trvanie: %3$d min
- Hodnota: %1$.2f JI/h (%2$.2f%%) Trvanie: %3$d min
- Hodnota: %1$.2f%% (%2$.2f JI/h) Trvanie: %3$d min ]]>
- Hodnota: %1$.2f JI/h (%2$.2f%%) Trvanie: %3$d min ]]>
+ %1$.1f U
+ %1$.2f U
+ Hodnota: %1$.2f%% (%2$.2f U/h) Trvanie: %3$d min
+ Hodnota: %1$.2f U/h (%2$.2f%%) Trvanie: %3$d min
+ Hodnota: %1$.2f%% (%2$.2f U/h) Trvanie: %3$d min ]]>
+ Hodnota: %1$.2f U/h (%2$.2f%%) Trvanie: %3$d min ]]>"AAPS prehráva zvuk"
diff --git a/core/ui/src/main/res/values-vi-rVN/protection.xml b/core/ui/src/main/res/values-vi-rVN/protection.xml
index bb9e1b106f1..06ec333884e 100644
--- a/core/ui/src/main/res/values-vi-rVN/protection.xml
+++ b/core/ui/src/main/res/values-vi-rVN/protection.xml
@@ -11,14 +11,14 @@
Mã PIN ứng dụngMật khẩu liều BolusMã PIN liều Bolus
- Thời gian lưu giữ mật khẩu và mã PIN [giây]
+ Thời gian lưu mật khẩu và mã PIN [giây]Thời gian trước khi phải nhập mật khẩu hoặc mã PINSinh trắc họcMật khẩu tùy chọnMã PIN tùy chọnKhông bảo mậtPhương án dự phòng không an toàn
- Để bảo mật sinh trắc học hoạt động hiệu quả, cần phải đặt mật khẩu chính làm phương án dự phòng.\n\nVui lòng đặt mật khẩu chính!
+ Để dùng sinh trắc học, bạn cần thiết lập mật khẩu chính làm phương án dự phòng.\n\n Cài đặt mật khẩu chính ngay!Mật khẩu đã được đặt!Mật khẩu dùng cho Xuất dữ liệu đã được xóa!Mã PIN đã được đặt!
diff --git a/core/ui/src/main/res/values-vi-rVN/strings.xml b/core/ui/src/main/res/values-vi-rVN/strings.xml
index 2b6d4425182..bf30c32223b 100644
--- a/core/ui/src/main/res/values-vi-rVN/strings.xml
+++ b/core/ui/src/main/res/values-vi-rVN/strings.xml
@@ -1,9 +1,9 @@
- Làm tươi
+ Làm mớiLỗi
- Đã cập nhật cấu hình Basal trong bơm
+ Đã cập nhật Hồ sơ liều nền trong bơmDữ liệu đầu vào không hợp lệĐã áp dụng giới hạn!Total IOB:
@@ -11,8 +11,8 @@
Không thể kết nối với bơmU%1$.2f U/h
- Bơm chưa được khởi tạo, cấu hình (profile) chưa được thiết lập!
- Không thể cập nhật cấu hình basal
+ Bơm chưa được khởi tạo, Hồ sơ chưa được thiết lập!
+ Không thể cập nhật Hồ sơ liều nềnKhông đọc được liều basal hợp lệ từ bơmGiới hạn IOB: %1$.1f U – Lý do: %2$s.VÒNG LẶP BỊ TẮT DO GIỚI HẠN AN TOÀN
@@ -21,11 +21,11 @@
mg/dlmmol/lLưu
- Nhắc lại
- Virtual Pump
+ Nhắc sau
+ Bơm mô phỏngGiới hạnSuperbolus
- Pump đã tạm dừng
+ Bơm đã tạm dừngVàNgười dùngKết quả
@@ -44,14 +44,14 @@
Im lặngThành côngCài đặt nâng cao
- Tiêm liều Bolus mở rộng thất bại
+ Tiêm liều Bolus kéo dài thất bạiChế độ APS
- Liều Bolus mở rộng
+ Liều Bolus kéo dàiĐã tạm dừng
- TDD Total
+ Tổng TDDDữ liệu cũĐang tiêm %1$.2f U Insulin
- Đang chờ phản hồi từ Pump
+ Đang chờ phản hồi từ BơmAAPS đã khởi động%1$+.2f U%1$d g
@@ -61,8 +61,8 @@
Vui lòng chờ…Dừng lạiCarbs
- Cấu hình không hợp lệ!
- KHÔNG CÓ PROFILE
+ Hồ sơ không hợp lệ!
+ KHÔNG CÓ HỒ SƠ]]>NgàyĐơn vị
@@ -74,7 +74,7 @@
Thời gian hoạt động của InsulinTỷ lệ Insulin/Carb (I:C)Độ nhạy Insulin (ISF)
- Tỷ lệ liều Basal
+ Tỷ lệ liều nềnMục tiêu đường huyếtg%
@@ -82,7 +82,7 @@
Giám sát BTTắt Bluetooth của điện thoại trong một giây nếu không thể kết nối với bơm. Điều này có thể hữu ích trên một số điện thoại khi ngăn xếp Bluetooth bị treo.ĐỒNG Ý
- Đã cập nhật thời gian bơm insulin
+ Đã cập nhật thời gian bơmThoátXóa bản ghi nàyVòng lặp bị vô hiệu hóa
@@ -94,7 +94,7 @@
Tạm dừng vòng lặpThời lượng [phút]Thông báo
- Chưa tải cấu hình nào từ NS
+ Chưa tải Hồ sơ nào từ NStồn tạikhông tồn tạiĐường huyết
@@ -117,7 +117,7 @@
Thời lượnggBơm đã tạm dừng
- Pump đang chạy
+ Bơm đang chạyChưa được thiết lậpVòng lặp đã tạm dừngVòng lặp bị tạm dừng do thay đổi múi giờ (DST)
@@ -140,14 +140,14 @@
TIR]]>XÓA
- Kích hoạt cấu hình
+ Kích hoạt Hồ sơđặt lại
- Thiếu ProfileSwitch. Vui lòng thực hiện chuyển cấu hình (profile switch) hoặc nhấn ‘Kích hoạt cấu hình’ (Activate Profile) trong LocalProfile.
- Cấu hình
+ Thiếu chuyển đổi hồ sơ. Vui lòng thực hiện chuyển đổi hồ sơ hoặc nhấn “Kích hoạt hồ sơ” trong Hồ sơ cục bộ.
+ Hồ sơChọn để xóaBạn có chắc chắn muốn xóa %1$d mục khôngĐiều trị
- Tạo cấu hình mới từ cấu hình này không?
+ Tạo Hồ sơ mới từ Hồ sơ này không?Cài đặt WizardXu hướng 15 phútCOB
@@ -157,22 +157,22 @@
Đăng nhậpĐăng xuấtPrime/Fill
- Chuyển vị trí tiêm
+ Chuyển vị tríInsulinDừng mục tiêu tạm thờiVòng lặp kínVòng lặp mởTạm ngừng khi đường huyết thấp
- Pump đã ngắt kết nối
- Pump đã tạm ngưng
+ Bơm đã ngắt kết nối
+ Bơm đã tạm ngưngChế độ đã được khôi phụcDIAICISF
- Hủy liều basal tạm thời thất bại
- Hủy liều bolus mở rộng thất bại
+ Hủy liều nền tạm thời thất bại
+ Hủy liều bolus kéo dài thất bạiTải trạng thái bơm lên NS hoặc Tidepool
- Insulin đang hoạt động (IOB)
+ Insulin còn hoạt động (IOB)MỤC TIÊU:KẾT QUẢ OAPS:%1$.2f U ( %2$.2f U/h )
@@ -189,23 +189,23 @@
Mật khẩu không khớpMã PIN không khớp
- Giá trị liều basal không khớp với giờ: %1$s
- Giá trị basal đã được thay bằng giá trị tối thiểu được hỗ trợ: %1$s
- Giá trị basal đã được thay bằng giá trị tối đa được hỗ trợ: %1$s
+ Giá trị liều nền không khớp với giờ: %1$s
+ Giá trị liều nền đã được thay bằng giá trị tối thiểu được hỗ trợ: %1$s
+ Giá trị liều nền đã được thay bằng giá trị tối đa được hỗ trợ: %1$s/UU/hg/U
- Bắt đầu cấu hình %1$d%% trong %2$d phút
+ Bắt đầu Hồ sơ %1$d%% trong %2$d phút
- Huỷ liều basal tạm
- Cho basal tạm thời tiếp tục
+ Huỷ liều liều nền tạm thời
+ Cho liều nền tạm thời tiếp tụcTỷ lệThời lượngLý doKhông có thay đổi nào được yêu cầu
- Cấu hình không hợp lệ: %1$s
+ Hồ sơ không hợp lệ: %1$s%1$d phút
@@ -224,24 +224,24 @@
Bài tập luyện : %1$sThay vị trí kim truyềnGắn cảm biến CGM
- Các vị trí tiêm
- Các vị trí CGM
+ Vị trí tiêm
+ Vị trí CGMKích hoạt cảm biến CGMDừng cảm biến CGMCảnh báo D.A.DThay ống chứa insulin
- Chuyển cấu hình
+ Chuyển Hồ sơBolus bữa ăn nhẹBolus cho bữa ănBolus hiệu chỉnhBolus kết hợp
- Bắt đầu basal tạm thời
- Kết thúc Basal tạm thời
+ Bắt đầu liều nền tạm thời
+ Kết thúc liều nền tạm thờiĐiều chỉnh CarbsOpenAPS Offline
- Thay pin Pump
+ Thay pin BơmMục tiêu Tạm thời
- Chế độ hoạt động
+ Chế độ đang chạyGiá trị mục tiêu tạm thờiHuỷ mục tiêu tạm thờiTính toán Bolus
@@ -314,7 +314,7 @@
Trọng lượngKết quả có thể sai lệch nếu tính cả bolus dùng để mồi/đổ đầy ống!Dữ liệu cũ, vui lòng nhấn \'RELOAD\'
- Tổng liều basal
+ Tổng liều nền cơ bảnTBB * 2Nhận diện thời gian
@@ -322,17 +322,17 @@
BOLUSTÍNH TOÁN BOLUSGỌI Ý BOLUS
- BOLUS MỞ RỘNG
+ LIỀU BOLUS KÉO DÀISUPERBOLUS TBRCARBSCARBS MỞ RỘNGTEMP BASALTEMP TARGET
- CẤU HÌNH MỚI
- NHÂN BẢN CẤU HÌNH
- LƯU CẤU HÌNH
- CHUYỂN CẤU HÌNH
- ĐÃ NHÂN BẢN CHUYỂN CẤU HÌNH
+ HỒ SƠ MỚI
+ NHÂN BẢN HỒ SƠ
+ LƯU TRỮ HỒ SƠ
+ CHUYỂN HỒ SƠ
+ ĐÃ NHÂN BẢN CHUYỂN HỒ SƠCHẾ ĐỘ VÒNG KÍNCHẾ ĐỘ VÒNG KÍN LGSVÒNG LẶP MỞ
@@ -343,12 +343,12 @@
NGẮT KẾT NỐITIẾP TỤCTẠM DỪNG
- CHO PHÉP PHẦN CỨNG PUMP
+ CHO PHÉP PHẦN CỨNG BƠMXÓA KHÓA GHÉP NỐI
- CHO PHÉP BASAL TẠM THỜI
- HỦY TEMP BASAL
+ CHO PHÉP LIỀU NỀN TẠM THỜI
+ HỦY LIỀU NỀN TẠMHỦY LIỀU BOLUS
- HỦY BOLUS MỞ RỘNG
+ HỦY LIỀU BOLUS KÉO DÀICANCEL TEMP TARGETCAREPORTALVỊ TRÍ CẢM BIẾN
@@ -359,7 +359,7 @@
BOLUS MỒIĐIỀU TRỊCẬP NHẬT CAREPORTAL TỪ NS
- CẬP NHẬT CẤU HÌNH TỪ NS
+ LÀM MỚI CHUYỂN HỒ SƠ TỪ NSCẬP NHẬT ĐIỀU TRỊ TỪ NSCẬP NHẬT TEMP TARGET TỪ NSĐÃ XÓA AUTOMATION
@@ -367,12 +367,12 @@
ĐÃ XÓA CAREPORTALĐÃ XÓA BOLUSĐÃ XÓA CARBS
- ĐÃ XÓA TEMP BASAL
- ĐÃ XÓA BOLUS MỞ RỘNG
+ ĐÃ XÓA LIỀU NỀN TẠM
+ ĐÃ XÓA LIỀU BOLUS KÉO DÀIBỮA ĂNĐÃ XÓA BỮA ĂN
- ĐÃ XÓA CẤU HÌNH
- ĐÃ XÓA CHUYỂN CẤU HÌNH
+ ĐÃ XÓA HỒ SƠ
+ ĐÃ XÓA CHUYỂN HỒ SƠSỰ KIỆN KHỞI ĐỘNG LẠI ĐÃ XÓAĐÃ XÓA ĐIỀU TRỊĐÃ XÓA TEMP TARGET
@@ -420,45 +420,45 @@
ĐÃ XÓA CHẾ ĐỘ THỂ DỤCĐÃ CẬP NHẬT CHẾ ĐỘ THỂ DỤC
- Cấu hình Mục tiêu Thấp
- Cấu hình Mục tiêu Cao
+ Hồ sơ Mục tiêu Thấp
+ Hồ sơ Mục tiêu CaoGiá trị thấp của mục tiêu tạm thờiGiá trị cao của mục tiêu tạm thờiGiá trị mục tiêu tạm thời
- Cấu hình giá trị DIA
- Giá trị độ nhạy insulin trong cấu hình
- Giá trị basal tối đa trong cấu hình
- Giá trị basal hiện tại
- Giá trị tỷ lệ carb trong cấu hình
+ Hồ sơ giá trị DIA
+ Giá trị độ nhạy insulin trong Hồ sơ
+ Giá trị liều nền tối đa trong Hồ sơ
+ Giá trị liều nền hiện tại
+ Giá trị tỷ lệ carb trong Hồ sơ%1$.2f bị giới hạn ở %2$.2f»%1$s« nằm ngoài giới hạn an toàn»%1$s« %2$.2f nằm ngoài giới hạn an toàn
- Giá trị liều Basal
+ Giá trị liều liều nềnBOLUS %1$.2f UCARBS %1$d g
- BOLUS MỞ RỘNG %1$.2f U trong %2$d phút
+ LIỀU BOLUS KÉO DÀI %1$.2f U trong %2$d phútTẢI SỰ KIỆNXOÁ CẢNH BÁOHUỶ KÍCH HOẠTCẬP NHẬT THỜI GIANTẢI LỊCH SỬ %1$dTẢI TDDs
- THIẾT LẬP CẤU HÌNH
+ THIẾT LẬP HỒ SƠCÀI ĐẶT NGƯỜI DÙNGSMB BOLUS %1$.2f U
- KHỞI ĐỘNG PUMP
- DỪNG PUMP
- LIỀU BASAL TẠM THỜI %1$.2f U/h %2$d min
- LIỀU BASAL TẠM THỜI %1$d%% %2$d min
+ KHỞI ĐỘNG BƠM
+ DỪNG BƠM
+ LIỀU NỀN TẠM THỜI %1$.2f U/h %2$d min
+ LIỀU NỀN TẠM THỜI %1$d%% %2$d minINSIGHT: TBR VƯỢT QUÁ GIỚI HẠNTRẠNG THÁI %1$sKết nối. Trạng thái đã hết hạn.
- Kết nối. Liều Basal Basal đã quá hạn.
+ Giữ kết nối. Liều nền đã hết hạn.SMS%1$.0f%%Liều Basal
- Liều Basal %
+ Liều nền %Độ nhạyISF dùng cho tính toán và hấp thụ carb: %1$.1fGiá trị Autosens: %.0f%%
@@ -470,7 +470,7 @@
AutotuneTune days :
- Chọn cấu hình để điều chỉnh
+ Chọn Hồ sơ để điều chỉnhHiển thị cảnh báo qua thông báo hệ thốngCảnh báo khẩn cấp
@@ -489,7 +489,7 @@
Carb = 0. Không có hành động nào được thực hiện!Không cần insulin!Chưa có BG gần đây để tính toán!
- Chưa có cấu hình nào hoạt động!
+ Chưa có Hồ sơ nào hoạt động!COB không xác định! Thiếu dữ liệu BG hoặc ứng dụng vừa khởi động lại?Vi phạm giới hạn carb!Calc (IC: %1$.1f, ISF: %2$.1f)
@@ -519,28 +519,28 @@
Mở khóa cài đặtPin
- Ngăn chứa insulin
+ Bình chứa insulinKết nối lần cuốiLiều bolus gần nhất
- Tỷ lệ liều basal
- Liều basal tạm thời
- Liều Bolus mở rộng
+ Tỷ lệ liều nền cơ bản
+ Liều nền tạm thời
+ Liều Bolus kéo dàiSố sê-riNgắt kết nốiĐang kết nối
- Đã nhấn kết nối với pump
+ Đã nhấn kết nối với Bơm%1$.0f / %2$d UĐơn vị hàng ngày
- Biểu tượng pump
- Xem cấu hình
- Lịch sử pump
+ Biểu tượng Bơm
+ Xem Hồ sơ
+ Lịch sử bơmThống kêThay trình điều khiển bơm.Thiết bị đã thay đổiBolus thành công
- Lỗi khi tiêm liều basal tạm thời
+ Lỗi khi tiêm liều nền tạm thờiChưa đặt
- Pump đang bận
+ Bơm đang bậnLỗi kết nối bơmĐang đọc lịch sử bơmĐã xóa bỏ mật khẩu!
@@ -548,8 +548,8 @@
Đang khởi tạo...%1$d s
- Giới hạn tỷ lệ basal tối đa ở %1$.2f U/h do %2$s
- giới hạn pump
+ Giới hạn tỷ lệ nền tối đa ở %1$.2f U/h do %2$s
+ giới hạn BơmGiới hạn tỷ lệ phần trăm tối đa %1$d%% do %2$sphải nhập giá trị dươngGiới hạn bolus ở %1$.1f U do %2$s
@@ -583,12 +583,12 @@
Đã đạt giới hạn cho phép%1$dh %2$dm
- Event time
+ Thời điểmỨng dụng yêu cầu quyền BluetoothYêu cầu người dùng
- Pump đã ghép nối
+ Bơm đã ghép nốiThiết bị không hỗ trợ Bluetooth.Không hỗ trợ Bluetooth hoặc thiết bị chưa được ghép nối.
@@ -600,7 +600,7 @@
Thiếu quyền nhắn tin SMS
- Đừng tắt ứng dụng này!
+ Đừng tắt ứng dụng!Đã vô hiệu hóa tải lên nhật ký sự cố!\n\nDocumentation:\nhttps://wiki.aaps.app\n\nFacebook:\nhttps://www.facebook.com/groups/AndroidAPSUsers
diff --git a/core/validators/src/main/kotlin/app/aaps/core/validators/preferences/AdaptiveListIntPreference.kt b/core/validators/src/main/kotlin/app/aaps/core/validators/preferences/AdaptiveListIntPreference.kt
index 2b85cfb5688..78edd64cb51 100644
--- a/core/validators/src/main/kotlin/app/aaps/core/validators/preferences/AdaptiveListIntPreference.kt
+++ b/core/validators/src/main/kotlin/app/aaps/core/validators/preferences/AdaptiveListIntPreference.kt
@@ -30,6 +30,27 @@ open class AdaptiveListIntPreference(
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
intKey?.let { key = it.key }
+
+ // Migrate old Int values to String for ListPreference compatibility
+ // AdaptiveListIntPreference extends ListPreference which stores values as String,
+ // but old code may have stored IntKey values as actual Integers.
+ // This causes ClassCastException when ListPreference tries to read the value.
+ intKey?.let { prefKey ->
+ val sp = android.preference.PreferenceManager.getDefaultSharedPreferences(ctx)
+ try {
+ val oldValue = sp.getInt(prefKey.key, -1)
+ if (oldValue != -1) {
+ // Migrate: remove Int value, write as String
+ sp.edit()
+ .remove(prefKey.key)
+ .putString(prefKey.key, oldValue.toString())
+ .apply()
+ }
+ } catch (e: ClassCastException) {
+ // Already a String, no migration needed
+ }
+ }
+
title?.let { this.title = context.getString(it) }
dialogMessage?.let { this.dialogMessage = context.getString(it) }
dialogTitle?.let { this.dialogTitle = context.getString(it) }
diff --git a/core/validators/src/main/res/values-vi-rVN/validator.xml b/core/validators/src/main/res/values-vi-rVN/validator.xml
index a2df29e6bef..6cbe68d6782 100644
--- a/core/validators/src/main/res/values-vi-rVN/validator.xml
+++ b/core/validators/src/main/res/values-vi-rVN/validator.xml
@@ -1,7 +1,7 @@
Chỉ được phép nhập các chữ số.
- Chỉ được phép nhập các chữ số trong khoảng %1$s - %2$s.
+ Chỉ chấp nhận số trong khoảng %1$s - %2$s.Trường này không được chứa ký tự đặc biệt nàoChỉ được phép nhập các chữ cái chuẩnTrường này không được để trống
diff --git a/database/impl/src/main/kotlin/app/aaps/database/serialisation/SealedClassHelper.kt b/database/impl/src/main/kotlin/app/aaps/database/serialisation/SealedClassHelper.kt
index c76245a625b..014d369b696 100644
--- a/database/impl/src/main/kotlin/app/aaps/database/serialisation/SealedClassHelper.kt
+++ b/database/impl/src/main/kotlin/app/aaps/database/serialisation/SealedClassHelper.kt
@@ -29,7 +29,14 @@ object SealedClassHelper {
jsonReader.beginObject()
val nextName = jsonReader.nextName()
val innerClass = kClass.sealedSubclasses.firstOrNull { it.simpleName == nextName }
- ?: throw Exception("$nextName is not a child of the sealed class ${kClass.qualifiedName}")
+ if (innerClass == null) {
+ // Skip the unknown value and return UNKNOWN if available
+ jsonReader.skipValue()
+ jsonReader.endObject()
+ @Suppress("UNCHECKED_CAST")
+ val unknownInstance = kClass.sealedSubclasses.firstOrNull { it.simpleName == "UNKNOWN" }?.objectInstance as T?
+ return unknownInstance
+ }
val x = gson.fromJson(jsonReader, innerClass.javaObjectType)
jsonReader.endObject()
// if there a static object, actually return that
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7a7711270c6..df388538f16 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -163,7 +163,7 @@ com-github-kenglxn-qrgen-android = { group = "com.github.kenglxn.QRGen", name =
com-github-rtchagas-pingplacepicker = { group = "com.github.rtchagas", name = "pingplacepicker", version = "3.0.1" }
io-socket-client = { group = "io.socket", name = "socket.io-client", version = "2.1.2" }
io-kotlintest-runner-junit5 = { group = "io.kotlintest", name = "kotlintest-runner-junit5", version = "3.4.2" }
-com-polidea-rxandroidble3 = { group = "com.polidea.rxandroidble3", name = "rxandroidble", version = "1.19.0" }
+com-polidea-rxandroidble3 = { group = "com.polidea.rxandroidble3", name = "rxandroidble", version = "1.19.1" }
com-jakewharton-rx3-replaying-share = { group = "com.jakewharton.rx3", name = "replaying-share", version = "3.0.0" }
commons-codec = { group = "commons-codec", name = "commons-codec", version = "1.20.0" }
com-github-guepardoapps-kulid = { group = "com.github.guepardoapps", name = "kulid", version = "2.0.0.0" }
diff --git a/implementation/src/main/kotlin/app/aaps/implementation/pump/BlePreCheckImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/pump/BlePreCheckImpl.kt
index 88b43b58cba..a28603bc8e4 100644
--- a/implementation/src/main/kotlin/app/aaps/implementation/pump/BlePreCheckImpl.kt
+++ b/implementation/src/main/kotlin/app/aaps/implementation/pump/BlePreCheckImpl.kt
@@ -7,6 +7,8 @@ import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.interfaces.pump.BlePreCheck
import app.aaps.core.interfaces.resources.ResourceHelper
import app.aaps.core.ui.dialogs.OKDialog
@@ -17,15 +19,18 @@ import javax.inject.Singleton
@Singleton
class BlePreCheckImpl @Inject constructor(
private val context: Context,
- private val rh: ResourceHelper
+ private val rh: ResourceHelper,
+ private val aapsLogger: AAPSLogger
) : BlePreCheck {
companion object {
private const val PERMISSION_REQUEST_BLUETOOTH = 30242 // arbitrary.
+
}
- override fun prerequisitesCheck(activity: AppCompatActivity): Boolean {
+
+ override fun prerequisitesCheck(activity: AppCompatActivity, additionalPermissions: List?): Boolean {
if (!activity.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
OKDialog.show(activity, rh.gs(app.aaps.core.ui.R.string.message), rh.gs(app.aaps.core.ui.R.string.ble_not_supported))
return false
@@ -37,6 +42,10 @@ class BlePreCheckImpl @Inject constructor(
return false
}
+ if (!checkAdditionalPermissions(additionalPermissions, activity)) {
+ return false;
+ }
+
val bluetoothAdapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
// Ensures Bluetooth is available on the device and it is enabled.
bluetoothAdapter?.safeEnable(3000)
@@ -47,4 +56,35 @@ class BlePreCheckImpl @Inject constructor(
}
return true
}
+
+
+ private fun checkAdditionalPermissions(additionalPermissions: List?, activity: AppCompatActivity): Boolean {
+
+ if (additionalPermissions==null || additionalPermissions.size==0) {
+ aapsLogger.debug(LTag.PUMP, "No additional permissions found !")
+ return true
+ }
+
+ aapsLogger.info(LTag.PUMP, "Additional permissions check (${additionalPermissions.size}): ${additionalPermissions}")
+
+ val nonPermittedItems = mutableListOf()
+
+ for (permission in additionalPermissions) {
+ if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
+ nonPermittedItems.add(permission)
+ }
+ }
+
+ aapsLogger.info(LTag.PUMP, "Non permitted items: ${nonPermittedItems}")
+
+ if (nonPermittedItems.size > 0) {
+ ActivityCompat.requestPermissions(activity, nonPermittedItems.toTypedArray(), PERMISSION_REQUEST_BLUETOOTH)
+ return false
+ }
+
+ return true
+ }
+
+
+
}
\ No newline at end of file
diff --git a/implementation/src/main/res/values-nl-rNL/strings.xml b/implementation/src/main/res/values-nl-rNL/strings.xml
index 5aace5f4cb0..2d64d227d16 100644
--- a/implementation/src/main/res/values-nl-rNL/strings.xml
+++ b/implementation/src/main/res/values-nl-rNL/strings.xml
@@ -17,4 +17,12 @@
TIR \'s nachtsKoolhydraten
+ Laatste connectie: %1$d min geleden
+ Alarm: %1$s
+ Laatste bolus: %1$s E @ %2$s
+ Tijdelijk: %1$s
+ Verlengd: %1$s
+ Reservoir: %1$dE
+ Batt: %1$d%%
+ Pomp niet geïnitialiseerd
diff --git a/implementation/src/main/res/values-pl-rPL/strings.xml b/implementation/src/main/res/values-pl-rPL/strings.xml
index a717523520f..3d794813d58 100644
--- a/implementation/src/main/res/values-pl-rPL/strings.xml
+++ b/implementation/src/main/res/values-pl-rPL/strings.xml
@@ -17,4 +17,12 @@
Nocny TIRWęglowodany
+ Ost. Poł.: %1$d m. temu
+ Alarm: %1$s
+ Ost. Bolus: %1$sU @ %2$s
+ Tymcz.: %1$s
+ Ext: %1$s
+ Zbior.: %1$dU
+ Bat.: %1$d%%
+ Pompa nie zainicjal.
diff --git a/implementation/src/main/res/values-sk-rSK/strings.xml b/implementation/src/main/res/values-sk-rSK/strings.xml
index 1b205c97d8b..e64c700bc89 100644
--- a/implementation/src/main/res/values-sk-rSK/strings.xml
+++ b/implementation/src/main/res/values-sk-rSK/strings.xml
@@ -19,10 +19,10 @@
Posledné Spoj: pred %1$d minUpozornenie: %1$s
- Posledný bolus: %1$sJI @ %2$s
+ Posledný bolus: %1$sU @ %2$sDoč. bazál: %1$sExt: %1$s
- Zásobník: %1$dJI
+ Zásobník: %1$dUBat: %1$d%%Pumpa nie je inicializovaná
diff --git a/implementation/src/main/res/values-vi-rVN/strings.xml b/implementation/src/main/res/values-vi-rVN/strings.xml
index 5d056c52233..3f650642529 100644
--- a/implementation/src/main/res/values-vi-rVN/strings.xml
+++ b/implementation/src/main/res/values-vi-rVN/strings.xml
@@ -1,7 +1,7 @@
- Lệnh đang được thực thi ngay bây giờ
- Giá trị basal thấp hơn mức tối thiểu. Cấu hình chưa được thiết lập!
+ Đang xử lý lệch
+ Giá trị liều nền thấp hơn mức tối thiểu. Hồ sơ chưa được thiết lập!Quá thấpThấp
@@ -17,7 +17,7 @@
TIR ban đêmCarbs
- LastConn: %1$d min ago
+ Kết nối gần nhất: %1$d phút trướcCảnh báo: %1$sLastBolus: %1$sU @ %2$sTemp: %1$s
diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/DetermineBasalAutoISF.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/DetermineBasalAutoISF.kt
index 81160a7cbe8..e145fa15fb1 100644
--- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/DetermineBasalAutoISF.kt
+++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/DetermineBasalAutoISF.kt
@@ -1,5 +1,6 @@
package app.aaps.plugins.aps.openAPSAutoISF
+import app.aaps.core.data.configuration.Constants
import app.aaps.core.interfaces.aps.APSResult
import app.aaps.core.interfaces.aps.AutosensResult
import app.aaps.core.interfaces.aps.CurrentTemp
@@ -219,7 +220,7 @@ class DetermineBasalAutoISF @Inject constructor(
// var origin_sens = ""
var exercise_ratio = 1.0
val high_temptarget_raises_sensitivity = profile.exercise_mode || profile.high_temptarget_raises_sensitivity
- val normalTarget = 100 // evaluate high/low temptarget against 100, not scheduled target (which might change)
+ val normalTarget = Constants.NORMAL_TARGET_MGDL // evaluate high/low temptarget against normal target, not scheduled target (which might change)
// when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%), 80 mg/dL with low_temptarget_lowers_sensitivity would give 1.5x basal, but is limited to autosens_max (1.2x by default)
val halfBasalTarget = profile.half_basal_exercise_target
diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPlugin.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPlugin.kt
index 374b8d3b272..101907c904f 100644
--- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPlugin.kt
+++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPlugin.kt
@@ -144,7 +144,7 @@ open class OpenAPSAutoISFPlugin @Inject constructor(
val iobThresholdPercent; get() = preferences.get(IntKey.ApsAutoIsfIobThPercent)
private val exerciseMode; get() = SMBDefaults.exercise_mode
private val highTemptargetRaisesSensitivity; get() = preferences.get(BooleanKey.ApsAutoIsfHighTtRaisesSens)
- val normalTarget = 100
+ val normalTarget = Constants.NORMAL_TARGET_MGDL
private val minutesClass; get() = if (preferences.get(IntKey.ApsMaxSmbFrequency) == 1) 6L else 30L // ga-zelle: later get correct 1 min CGM flag from glucoseStatus ? ... or from apsResults?
override fun onStart() {
diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSSMB/DetermineBasalSMB.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSSMB/DetermineBasalSMB.kt
index c5373b4cecf..351a10003c7 100644
--- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSSMB/DetermineBasalSMB.kt
+++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/openAPSSMB/DetermineBasalSMB.kt
@@ -68,7 +68,7 @@ class DetermineBasalSMB @Inject constructor(
if (!microBolusAllowed) {
consoleError.add("SMB disabled (!microBolusAllowed)")
return false
- } else if (!profile.allowSMB_with_high_temptarget && profile.temptargetSet && target_bg > Constants.ALLOW_SMB_WITH_HIGH_TT) {
+ } else if (!profile.allowSMB_with_high_temptarget && profile.temptargetSet && target_bg > Constants.NORMAL_TARGET_MGDL) {
consoleError.add("SMB disabled due to high temptarget of $target_bg")
return false
}
@@ -220,7 +220,7 @@ class DetermineBasalSMB @Inject constructor(
var sensitivityRatio: Double
val high_temptarget_raises_sensitivity = profile.exercise_mode || profile.high_temptarget_raises_sensitivity
- val normalTarget = 100 // evaluate high/low temptarget against 100, not scheduled target (which might change)
+ val normalTarget = Constants.NORMAL_TARGET_MGDL // evaluate high/low temptarget against normal target, not scheduled target (which might change)
// when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%), 80 mg/dL with low_temptarget_lowers_sensitivity would give 1.5x basal, but is limited to autosens_max (1.2x by default)
val halfBasalTarget = profile.half_basal_exercise_target
diff --git a/plugins/aps/src/main/res/values-ru-rRU/strings.xml b/plugins/aps/src/main/res/values-ru-rRU/strings.xml
index 9831c6b2fff..fe5d2b258e8 100644
--- a/plugins/aps/src/main/res/values-ru-rRU/strings.xml
+++ b/plugins/aps/src/main/res/values-ru-rRU/strings.xml
@@ -68,7 +68,7 @@
Всегда включать супер микро болюс SMBВключать SMB всегда, вне зависимости от активных углеводов, ВЦ или болюсов. Возможно только на источниках СК с хорошей фильтрацией данныхВключать супер микро болюс SMB после углеводов
- Включать SMB на 6ч после приема пищи, даже при отсутствии активных углеводов. Возможно только на источниках СК с продвинутой фильтрацией данных
+ Включать SMB на 6ч после приема пищи, даже при отсутствии активных углеводов. Возможно только на источниках ГК с улучшенной фильтрацией данныхВключать супер микро болюсы при активных углеводах COBВключить супер микро болюс SMB, когда имеются активные углеводы COB.Включить супер микро болюсы SMB с временными целями
diff --git a/plugins/aps/src/main/res/values-sk-rSK/strings.xml b/plugins/aps/src/main/res/values-sk-rSK/strings.xml
index 676519638be..f13b54b2ae0 100644
--- a/plugins/aps/src/main/res/values-sk-rSK/strings.xml
+++ b/plugins/aps/src/main/res/values-sk-rSK/strings.xml
@@ -44,10 +44,10 @@
Dáta detekcie citlivostiLadenie skriptuPouži automatickú detekciu citlivosti
- Max. JI/h, ktoré je možné nastaviť pre dočas. bazál
+ Max. U/h, ktoré je možné nastaviť pre dočas. bazálTáto hodnota je nazývaná v kontexte OpenAPS ako \"max basal\"
- Maximálny bazálny IOB, ktorý OpenAPS môže podať [JI]
- Táto hodnota je nazývaná v kontexte OpenAPS ako max IOB, je to maximálne množstvo inzulínu v [JI], ktoré APS môže naraz podať.
+ Maximálny bazálny IOB, ktorý OpenAPS môže podať [U]
+ Táto hodnota je nazývaná v kontexte OpenAPS ako max IOB, je to maximálne množstvo inzulínu v [U], ktoré APS môže naraz podať.Štandardná hodnota: zapnuté\nToto je používané, aby automatická detekcia citlivosti mohla okrem cieľovej hodnoty glykémie, upravovať aj citlivosť, prevody a bazály.Autosense takisto upravuje cieľovú glykémiuŠtandardná hodnota: 3.0 (AMA), alebo 8.0 (SMB) mg/dl/5min. Táto hodnota definuje minimálnu časť vstrebaných sacharidov za každých 5min. Táto hodnota ovplyvňuje výpočet COB.
@@ -59,7 +59,7 @@
Zmysluplné, pokiaľ dáta z xDrip+ obsahujú veľký šum.Max násobiteľ denného najvyššieho bazáluMax násobiteľ súčasného bazálu
- Maximálne celkové IOB, ktoré OpenAPS nemôže prekročiť [JI]
+ Maximálne celkové IOB, ktoré OpenAPS nemôže prekročiť [U]Táto hodnota je v kontexte OpenAPS nazývaná Max IOB.\nOpenAPS nikdy nepridá inzulín, pokiaľ je súčasné IOB väčšie, ako táto hodnotaPovoliť UAMPovoliť SMB
@@ -91,7 +91,7 @@
Povoliť dynamickú citlivosťUpravte algoritmus pre použitie dynamickej citlivosti namiesto hodnoty z profilu
- IOB obmedzený na %1$.1f JI: %2$s
+ IOB obmedzený na %1$.1f U: %2$smaximálna hodnota v nastaveniachpevný limit
@@ -143,8 +143,8 @@
Profil :Posledné spustenie :Upozornenie :
- Vybraný profil má %1$d hodnôt IC. Autotune bude používať %2$.2f g/JI
- Vybraný profil má %1$d hodnôt ISF. Autotune bude používať %2$.1f %3$s/JI
+ Vybraný profil má %1$d hodnôt IC. Autotune bude používať %2$.2f g/U
+ Vybraný profil má %1$d hodnôt ISF. Autotune bude používať %2$.1f %3$s/UChyba vstupných dát, skúste znova spustiť Autotune, alebo znížte počet dníChyba vo vstupných dátach, zvýšte počet dníAutotune spustený, prosím buďte trpezliví
diff --git a/plugins/aps/src/main/res/values-vi-rVN/strings.xml b/plugins/aps/src/main/res/values-vi-rVN/strings.xml
index 182b3540334..19614fb87d1 100644
--- a/plugins/aps/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/aps/src/main/res/values-vi-rVN/strings.xml
@@ -1,8 +1,8 @@
- Kích hoạt hệ số nhạy cảm insulin dựa trên tổng liều hằng ngày (TDD) để điều chỉnh liều basal và mục tiêu đường huyết
- Sử dụng TDD 24 giờ gần nhất hoặc TDD trung bình 7 ngày để tính độ nhạy insulin, từ đó tăng hoặc giảm tốc độ basal, đồng thời điều chỉnh mục tiêu đường huyết nếu các tùy chọn này được bật, tương tự như cách Autosens hoạt động. Khuyến nghị nên bắt đầu với tùy chọn này ở trạng thái tắt
+ Kích hoạt hệ số nhạy cảm insulin dựa trên tổng liều hằng ngày (TDD) để điều chỉnh liều liều nền và mục tiêu đường huyết
+ Sử dụng TDD 24 giờ gần nhất hoặc TDD trung bình 7 ngày để tính độ nhạy insulin, từ đó tăng hoặc giảm tốc độ liều nền, đồng thời điều chỉnh mục tiêu đường huyết nếu các tùy chọn này được bật, tương tự như cách Autosens hoạt động. Khuyến nghị nên bắt đầu với tùy chọn này ở trạng thái tắtHệ số điều chỉnh DynamicISF (%)Hệ số điều chỉnh cho DynamicISF. Đặt lớn hơn 100% để có liều hiệu chỉnh mạnh hơn, và nhỏ hơn 100% để có liều hiệu chỉnh nhẹ hơn.Mục tiêu tạm thời cao làm tăng độ nhạy
@@ -12,7 +12,7 @@
OpenAPS SMBDynamic ISFAuto ISF
- Tần suất SMB sẽ được bơm (tính bằng phút)
+ Tần suất SMB sẽ được bơm (phút)Kháng insulin làm giảm mục tiêuKhi phát hiện kháng insulin, hãy hạ thấp mức đường huyết mục tiêuĐộ nhạy tăng mục tiêu
@@ -35,35 +35,35 @@
Lần chạy gần nhấtTham số đầu vàoTrạng thái đường huyết
- Current temp
+ Liều tạm thời hiện tạiDữ liệu IOB
- Cấu hình
+ Hồ sơDữ liệu bữa ănYêu cầuGiới hạnDữ liệu AutosensGỡ lỗi scriptSử dụng tính năng Autosens
- Liều Basal tạm thời tối đa (U/giờ)
- Giá trị này được gọi là basal tối đa trong OpenAPS
- Lượng IOB basal tối đa mà OpenAPS có thể cung cấp [U]
+ Liều nền tạm thời tối đa (U/giờ)
+ Giá trị này được gọi là liều nền tối đa trong OpenAPS
+ Lượng IOB liều nền tối đa mà OpenAPS có thể cung cấp [U]Giá trị này trong OpenAPS được gọi là Max IOB.\n Đây là lượng insulin tối đa [U] mà APS có thể đưa vào cùng một lúc.
- Mặc định: true.\n Tùy chọn này cho phép Autosens điều chỉnh mục tiêu đường huyết (BG), ngoài việc điều chỉnh ISF và basal.
+ Mặc định: true.\n Tùy chọn này cho phép Autosens điều chỉnh mục tiêu đường huyết (BG), ngoài việc điều chỉnh ISF và liều nền.Autosens cũng điều chỉnh cả mục tiêu
- Mặc định: 3 (AMA) hoặc 8 (SMB). Đây là thiết lập cho tác động mặc định của hấp thụ carb trong 5 phút. Giá trị mặc định tương ứng với 3 mg/dl/5 phút. Tham số này ảnh hưởng đến tốc độ giảm COB, cũng như lượng carb hấp thụ được giả định khi tính toán đường huyết dự đoán trong tương lai, trong trường hợp đường huyết giảm nhanh hơn dự kiến hoặc tăng ít hơn dự kiến.
- Mặc định: 3. Đây là một giới hạn an toàn quan trọng của OpenAPS. Nó giới hạn liều basal tối đa của bạn bằng 3 lần liều basal lớn nhất của bạn (áp dụng cho người này). Thông thường bạn không cần thay đổi, nhưng bạn nên biết rằng đây là những gì được nói đến khi nhắc đến ‘3x max daily; 4x current’ cho giới hạn an toàn.
- Giá trị mặc định: 4. Đây là nửa còn lại của các giới hạn an toàn chính của OpenAPS, và là nửa còn lại của ‘3x max daily; 4x current’ trong các giới hạn an toàn. Điều này có nghĩa là liều basal của bạn, bất kể liều basal tối đa được thiết lập trên bơm, không thể cao hơn con số này nhân với mức basal hiện tại. Điều này nhằm ngăn người dùng rơi vào tình huống nguy hiểm khi thiết lập liều basal tối đa quá cao trước khi hiểu cách thuật toán hoạt động. Giá trị mặc định là 4x; hầu hết người dùng sẽ không cần điều chỉnh, và thay vào đó có thể cần điều chỉnh các cài đặt khác nếu cảm thấy “đang chạm” vào giới hạn an toàn này.
+ Mặc định: 3 (AMA) hoặc 8 (SMB). Đây là thiết lập cho tác động mặc định của hấp thụ carb trong 5 phút. Giá trị mặc định tương ứng với 3 mg/dl/5 phút. Tham số này ảnh hưởng đến tốc độ giảm COB, cũng như lượng carb hấp thụ được giả định khi tính toán đường huyết dự đoán trong dự kiến, trong trường hợp đường huyết giảm nhanh hơn dự kiến hoặc tăng ít hơn dự kiến.
+ Mặc định: 3. Đây là một giới hạn an toàn quan trọng của OpenAPS. Nó giới hạn liều liều nền tối đa của bạn bằng 3 lần liều liều nền lớn nhất của bạn (áp dụng cho người này). Thông thường bạn không cần thay đổi, nhưng bạn nên biết rằng đây là những gì được nói đến khi nhắc đến ‘3x max daily; 4x current’ cho giới hạn an toàn.
+ Giá trị mặc định: 4. Đây là nửa còn lại của các giới hạn an toàn chính của OpenAPS, và là nửa còn lại của ‘3x max daily; 4x current’ trong các giới hạn an toàn. Điều này có nghĩa là liều liều nền của bạn, bất kể liều liều nền tối đa được thiết lập trên bơm, không thể cao hơn con số này nhân với mức liều nền hiện tại. Điều này nhằm ngăn người dùng rơi vào tình huống nguy hiểm khi thiết lập liều liều nền tối đa quá cao trước khi hiểu cách thuật toán hoạt động. Giá trị mặc định là 4x; hầu hết người dùng sẽ không cần điều chỉnh, và thay vào đó có thể cần điều chỉnh các cài đặt khác nếu cảm thấy “đang chạm” vào giới hạn an toàn này.Giá trị mặc định: 2\nBolus snooze được kích hoạt sau khi bạn thực hiện một bolus bữa ăn, để vòng lặp không điều chỉnh bằng các temp thấp khi bạn vừa ăn. Ví dụ ở đây và giá trị mặc định là 2; nghĩa là với DIA 3 giờ, bolus snooze sẽ được loại bỏ dần trong 1,5 giờ (3DIA/2).Chú ý!\nThông thường bạn không cần thay đổi các giá trị bên dưới. Vui lòng BẤM VÀO ĐÂY và ĐỌC kỹ nội dung, đảm bảo bạn HIỂU trước khi thay đổi bất kỳ giá trị nào.Luôn dùng delta trung bình ngắn thay cho delta đơn giảnHữu ích khi dữ liệu từ các nguồn chưa lọc, như xDrip+, bị nhiễu.Hệ số an toàn tối đa trong ngày
- Hệ số an toàn của basal hiện tại
+ Hệ số an toàn của liều nền hiện tạiTổng IOB tối đa mà OpenAPS không được vượt quá [U]Giá trị này trong OpenAPS được gọi là Max IOB. \nOpenAPS sẽ không đưa thêm insulin nếu IOB hiện tại lớn hơn giá trị nàyKích hoạt UAMKích hoạt SMB
- Sử dụng Super Micro Boluses (SMB) thay cho basal tạm thời để có tác dụng nhanh hơn
+ Sử dụng Super Micro Boluses (SMB) thay cho liều nền tạm thời để có tác dụng nhanh hơnPhát hiện bữa ăn không khai báoLuôn bật SMBBật SMB mọi lúc, không phụ thuộc vào COB, mục tiêu tạm thời hoặc bolus. Chỉ khả dụng khi sử dụng nguồn BG có bộ lọc dữ liệu nâng cao
@@ -75,31 +75,31 @@
Bật SMB khi có mục tiêu tạm thời đang hoạt động (sắp ăn, tập thể dục)Bật SMB với mục tiêu tạm thời caoBật SMB khi có mục tiêu tạm thời cao đang hoạt động (tập thể dục, trên 100 mg/dl hoặc 5,5 mmol/l)
- Số phút basal tối đa để giới hạn cho SMB
+ Số phút liều nền tối đa để giới hạn cho SMBSố phút tối đa SMB cho UAM
- Số phút basal tối đa để giới hạn SMB cho UAM
+ Số phút liều nền tối đa để giới hạn SMB cho UAMLượng carb tối thiểu cần thiết để đưa ra gợi ýSố gram carbs tối thiểu để hiển thị cảnh báo gợi ý carbs. Gợi ý carbs dưới mức này sẽ không kích hoạt thông báo.Đường huyết dưới mức này sẽ tạm dừng việc tiêm insulin. Mức mặc định sử dụng mô hình mục tiêu chuẩn. Người dùng có thể đặt giá trị trong khoảng 60 mg/dL (3,3 mmol/L) đến 100 mg/dL (5,5 mmol/L). Các giá trị dưới 65 mg/dL (3,6 mmol/L) sẽ sử dụng mô hình mặc địnhBG dưới ngưỡng này sẽ tạm dừng do hạ đường huyết
- Tăng basal tối đa vì thiết lập nhỏ hơn basal tối đa trong Cấu hình
- Hệ số nhân basal tối đa
- Hệ số nhân basal tối đa theo ngày
- SMB đã bị tắt trong phần Cài đặt
- UAM đã bị tắt trong phần Cài đặt
- Autosens đã bị tắt trong phần Cài đặt
+ Tăng liều nền tối đa vì thiết lập nhỏ hơn liều nền tối đa trong Hồ sơ
+ hệ số nhân liều nền tối đa
+ hệ số nhân liều nền tối đa theo ngày
+ SMB đã bị tắt trong phần Tùy chọn
+ UAM đã bị tắt trong Tùy chọn
+ Autosens đã bị tắt trong phần Tùy chọnBật độ nhạy động (dynamic sensitivity)
- Điều chỉnh thuật toán để dùng độ nhạy insulin động thay cho giá trị Cấu hình
+ Điều chỉnh thuật toán để dùng độ nhạy insulin động thay cho giá trị hồ sơGiới hạn IOB ở mức %1$.1f U do %2$s
- Giá trị tối đa trong phần Cài đặt
+ giá trị tối đa trong phần Tùy chọngiới hạn cứngĐỉnh (Peak)Chạy ngay bây giờMột liều bolus đã được bơm trong vòng 3 phút trước, bỏ qua SMB
- Pump chưa được khởi tạo!
+ Bơm chưa được khởi tạo!LOOPBật hoặc tắt chức năng thực thi để kích hoạt vòng lặp.KHÔNG CÓ APS ĐƯỢC CHỌN HOẶC CUNG CẤP KẾT QUẢ
@@ -108,43 +108,43 @@
Bỏ qua 30 phútĐề xuất lượng carbCó đề xuất mới
- Basal được cài đặt đúng
+ Liều nền được cài đặt đúngLần chạy gần nhấtAPSYêu cầuĐã áp dụng giới hạn an toàn
- Thời gian yêu cầu basal tạm thời
- Thời gian thực hiện basal tạm thời
- Basal tạm thời được cài đặt bởi bơm
- Thời gian yêu cầu SMB
- Thời gian thực hiện SMB
+ Yêu cầu liều nền tạm thời lúc
+ Thực hiện liều nền tạm thời lúc
+ Liều nền tạm thời bởi bơm
+ Yêu cầu SMB lúc
+ Thực hiện SMB lúcSMB được cài đặt bởi bơmThay đổi yêu cầu tối thiểu [%]Open Loop sẽ chỉ hiển thị yêu cầu thay đổi mới nếu thay đổi lớn hơn giá trị này theo %. Giá trị mặc định là 20%Chuyển sang SMB. Không đủ dữ liệu TDD.
- Chuyển sang độ nhạy insulin theo Cấu hình. Không đủ dữ liệu. Lý do: %1$s
+ Chuyển sang Hồ sơ độ nhạy insulin. Không đủ dữ liệu. Lý do: %1$s
- Hướng dẫn hỗ trợ điều chỉnh Cấu hình(ISF, tỉ lệ carb và liều basal)
+ Hướng dẫn hỗ trợ điều chỉnh Hồ sơ (ISF, tỷ lệ carb và liều nền)ATCài đặt Autotune
- Tự động chuyển Cấu hình
- Nếu bật, Autotune sẽ tự động cập nhật và áp dụng Cấu hình đầu vào sau khi tính toán theo quy tắc tự động.
- Phân loại UAM như basal
- Chỉ bật khi bạn luôn nhập đúng toàn bộ carb đã ăn. Khi đó, Autotune sẽ dùng các mức tăng đột ngột để đề xuất điều chỉnh basal.
+ Tự động chuyển Hồ sơ
+ Nếu bật, Autotune sẽ tự động cập nhật và áp dụng Hồ sơ đầu vào sau khi tính toán theo quy tắc tự động.
+ Phân loại UAM như liều nền
+ Chỉ bật khi bạn luôn nhập đúng toàn bộ carb đã ăn. Khi đó, Autotune sẽ dùng các mức tăng đột ngột để đề xuất điều chỉnh liều nền.Điều chỉnh đường cong insulinChỉ bật nếu bạn sử dụng ‘free peak’. Tùy chọn này sẽ điều chỉnh thời gian đỉnh và thời gian hoạt động của insulinSố ngày dữ liệuÁp dụng kết quả trung bình trong IC/ISF theo nhịp sinh học
- Autotune sẽ không điều chỉnh các biến đổi theo nhịp sinh học (circadian). Tùy chọn này chỉ áp dụng việc hiệu chỉnh trung bình của IC và ISF vào Cấu hình nhịp sinh học của bạn
+ Autotune sẽ không điều chỉnh các biến đổi theo nhịp sinh học (circadian). Tùy chọn này chỉ áp dụng việc hiệu chỉnh trung bình của IC và ISF vào hồ sơ nhịp sinh học của bạnGhi nhiều thông tin nhật ký hơn để hỗ trợ gỡ lỗiChỉ bật khi được nhà phát triển yêu cầu để gửi thêm thông tin nhật ký, hỗ trợ gỡ lỗi plugin AutotuneSố ngày dữ liệu mặc định được Autotune xử lý (tối đa 30)Đã tinh chỉnh
- Cấu hình :
+ Hồ sơ:Lần chạy gần nhất :Cảnh báo :
- Cấu hình đã chọn có %1$d giá trị IC. Autotune sẽ sử dụng %2$.2f g/U
- Cấu hình đã chọn có %1$d giá trị ISF. Autotune sẽ sử dụng %2$.1f %3$s/U
+ Hồ sơ đã chọn có %1$d giá trị IC. Autotune sẽ sử dụng %2$.2f g/U
+ Hồ sơ đã chọn có %1$d giá trị ISF. Autotune sẽ sử dụng %2$.1f %3$s/UDữ liệu đầu vào lỗi, hãy thử chạy lại Autotune hoặc giảm số ngàyDữ liệu đầu vào lỗi, hãy tăng số ngàyĐang bắt đầu tính toán Autotune, vui lòng chờ
@@ -155,20 +155,20 @@
%ThiếuChạy Autotune
- Kiểm tra Cấu hình đầu vào
- So sánh các Cấu hình
- Sao chép sang Cấu hình cục bộ
- Cập nhật Cấu hình đầu vào
- Hoàn nguyên Cấu hình đầu vào
- Tạo Cấu hình cục bộ mới từ Cấu hình Autotune này?
- Cập nhật Cấu hình %1$s bằng Cấu hình Autotune?
- Hoàn nguyên Cấu hình %1$s về Cấu hình Đầu vào không?
- Cấu hình không hợp lệ
+ Kiểm tra Hồ sơ đầu vào
+ So sánh các Hồ sơ
+ Sao chép sang Hồ sơ cục bộ
+ Cập nhật Hồ sơ đầu vào
+ Hoàn nguyên Hồ sơ đầu vào
+ Tạo hồ sơ cục bộ mới từ Hồ sơ Autotune này?
+ Cập nhật Hồ sơ %1$s bằng Hồ sơ Autotune?
+ Hoàn nguyên Hồ sơ %1$s về Hồ sơ Đầu vào không?
+ Hồ sơ không hợp lệKhông khả dụng
- Pump đã ngắt kết nối
+ Bơm đã ngắt kết nối
- Mục tiêu tập luyện với 50% basal
- Đặt thành một số, ví dụ 160, có nghĩa là khi mục tiêu tạm thời (temp target) là 160 mg/dL và tùy chọn \'High temptarget raises sensitivity=true\' được bật, Aaps sẽ chạy 50%% basal ở mức này (120 = 75%%; 140 = 60%%).
+ Mục tiêu tập luyện với 50% liều nền
+ Đặt thành một số, ví dụ 160, có nghĩa là khi mục tiêu tạm thời (temp target) là 160 mg/dL và tùy chọn \'High temptarget raises sensitivity=true\' được bật, Aaps sẽ chạy 50%% liều nền ở mức này (120 = 75%%; 140 = 60%%).Cài đặt AutoISFAutoISF cho phép điều chỉnh Hệ số độ nhạy insulin (ISF) trong nhiều tình huống thay đổi đường huyết. \n\nNó cũng có thể điều chỉnh cài đặt phân phối SMBCài đặt phân phối SMB
diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPluginTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPluginTest.kt
index 24e0633071c..bee4ddc8deb 100644
--- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPluginTest.kt
+++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/openAPSAutoISF/OpenAPSAutoISFPluginTest.kt
@@ -1,6 +1,7 @@
package app.aaps.plugins.aps.openAPSAutoISF
import app.aaps.core.data.aps.SMBDefaults
+import app.aaps.core.data.configuration.Constants
import app.aaps.core.interfaces.aps.GlucoseStatusAutoIsf
import app.aaps.core.interfaces.aps.OapsProfileAutoIsf
import app.aaps.core.interfaces.bgQualityCheck.BgQualityCheck
@@ -69,7 +70,7 @@ class OpenAPSAutoISFPluginTest : TestBaseWithProfile() {
var ttSet = false
var exerciseMode = false
val targetBg = 120.0
- val normalTarget = 100
+ val normalTarget = Constants.NORMAL_TARGET_MGDL
assertThat(openAPSAutoISFPlugin.withinISFlimits(1.7, autoIsfMin, autoIsfMax, sens, originSens, ttSet, exerciseMode, targetBg, normalTarget)).isEqualTo(1.2) // upper limit
assertThat(openAPSAutoISFPlugin.withinISFlimits(0.5, autoIsfMin, autoIsfMax, sens, originSens, ttSet, exerciseMode, targetBg, normalTarget)).isEqualTo(0.7) // lower limit
sens = 1.5 // from Autosens
diff --git a/plugins/automation/src/main/res/values-nl-rNL/strings.xml b/plugins/automation/src/main/res/values-nl-rNL/strings.xml
index 67f7658d332..7cc82144409 100644
--- a/plugins/automation/src/main/res/values-nl-rNL/strings.xml
+++ b/plugins/automation/src/main/res/values-nl-rNL/strings.xml
@@ -78,6 +78,7 @@
BG verschilBG verschil [%1$s]Huidige locatie
+ Kies van kaartLocatieGlucose [%1$s]:Streefdoel [%1$s]:
@@ -140,4 +141,9 @@
Aantal stappen per %1$s minuten %2$s %3$.0fMetingsduur
+ SMB in-/uitschakelen
+ Wijzig SMB naar %1$s
+ Nieuwe SMB modus:
+ AAN
+ UIT
diff --git a/plugins/automation/src/main/res/values-pl-rPL/strings.xml b/plugins/automation/src/main/res/values-pl-rPL/strings.xml
index 9cfcc3a55aa..cfb7f1c3aaf 100644
--- a/plugins/automation/src/main/res/values-pl-rPL/strings.xml
+++ b/plugins/automation/src/main/res/values-pl-rPL/strings.xml
@@ -78,6 +78,7 @@
Różnica poziomu cukruRóżnica poziomu cukru [%1$s]Obecna lokalizacja
+ Wybierz z mapyLokalizacjaPoziom [%1$s]:Cel [%1$s]:
@@ -136,5 +137,13 @@
Błąd podczas ostatniego uruchomienia AutotuneWykryto Autotune w toku, anulowano próbę kolejnego uruchomienia
+ Liczba kroków
+ Liczba kroków na %1$s minut %2$s %3$.0f
+ Czas trwania pomiaru
+ Włącz/wyłącz SMB
+ Zmień SMB na %1$s
+ Nowy tryb SMB:
+ WŁ
+ WYŁ
diff --git a/plugins/automation/src/main/res/values-sk-rSK/strings.xml b/plugins/automation/src/main/res/values-sk-rSK/strings.xml
index fc631899aec..c2f610af630 100644
--- a/plugins/automation/src/main/res/values-sk-rSK/strings.xml
+++ b/plugins/automation/src/main/res/values-sk-rSK/strings.xml
@@ -102,7 +102,7 @@
Stav zásobníka %1$s %2$.0fVek batérie v pumpeÚroveň nabitia batérie v pumpe %1$s %2$.0f
- IOB [JI]:
+ IOB [U]:Vzdial. [m]:Čas zotavovaniaKaždých
diff --git a/plugins/automation/src/main/res/values-vi-rVN/strings.xml b/plugins/automation/src/main/res/values-vi-rVN/strings.xml
index 6cc7af62240..286043fc12a 100644
--- a/plugins/automation/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/automation/src/main/res/values-vi-rVN/strings.xml
@@ -17,14 +17,14 @@
Không tạm dừngTạm dừng vòng lặp %1$d phútThông báo: %1$s
- Chuyển Cấu hình sang
- Chuyển Cấu hình sang %1$s
+ Chuyển Hồ sơ sang
+ Chuyển Hồ sơ sang %1$sKết nối gần nhất đến bơmLần kết nối gần nhất với bơm [phút trước]Lần kết nối gần nhất với bơm %1$s %2$s phút trướcĐã thiết lập
- Tỷ lệ phần trăm Cấu hình
- Bắt đầu Cấu hình %1$d%%
+ Tỷ lệ phần trăm Hồ sơ
+ Bắt đầu Hồ sơ %1$d%%Tỷ lệ [%]:Gửi SMS: %1$sGửi SMS đến tất cả các số
@@ -42,7 +42,7 @@
Mục tiêu tạm thời không tồn tạiMục tiêu tạm thời %1$s %2$.0f %3$sMục tiêu tạm thời %1$s %2$.1f %3$s
- Cấu hình pct %1$s %2$d
+ Hồ sơ pct %1$s %2$dIOB %1$s %2$.1fHoặcHoặc loại trừ
@@ -75,8 +75,8 @@
Autosens %1$s %2$s %%Autosens %%3$s %1$s %2$s
- BG difference
- BG difference [%1$s]
+ Chênh lệch đường huyết
+ Chênh lệch đường huyết [%1$s]Vị trí hiện tạiChọn từ bản đồVị trí
@@ -96,12 +96,12 @@
Pod đã kích hoạtThời gian insulinInsulin đã dùng %1$s được %2$.1f giờ
- Pump battery age
- Pump battery age %1$s %2$.1f hour
+ Pin của Bơm
+ Pin của bơm đã dùng %1$s %2$.1f giờReservoir levelReservoir level %1$s %2$.0f
- Pump battery level
- Mức pin của pump %1$s %2$.0f
+ Mức pin của Bơm
+ Mức pin của Bơm %1$s %2$.0fIOB [U]:Dist [m]:Thời gian định kỳ
@@ -130,10 +130,10 @@
Đến giờ tiêm bolus! \nHãy chạy Bolus wizard và thực hiện tính toán lại.Lỗi khi cài đặt báo thức sắp tới
- Autotune profile %1$s
+ Hồ sơ Autotune %1$sChạy Autotune
- Autotune đã chạy mà không có chuyển đổi Cấu hình
- Autotune đã chạy và Cấu hình được tự động chuyển đổi
+ Autotune đã chạy mà không có chuyển đổi Hồ sơ
+ Autotune đã chạy và Hồ sơ được tự động chuyển đổiLỗi trong lần chạy Autotune gần nhấtPhát hiện một lần chạy Autotune khác, tiến trình đã bị hủy
diff --git a/plugins/configuration/build.gradle.kts b/plugins/configuration/build.gradle.kts
index c4b9f5e474b..aa342a3ab37 100644
--- a/plugins/configuration/build.gradle.kts
+++ b/plugins/configuration/build.gradle.kts
@@ -31,6 +31,12 @@ dependencies {
api(libs.androidx.work.runtime)
// Maintenance
api(libs.androidx.gridlayout)
+
+ // HTTP client for Google Drive API
+ implementation(libs.com.squareup.okhttp3.okhttp)
+
+ // Chrome Custom Tabs for OAuth flow
+ api(libs.androidx.browser)
ksp(libs.com.google.dagger.compiler)
ksp(libs.com.google.dagger.android.processor)
diff --git a/plugins/configuration/src/main/AndroidManifest.xml b/plugins/configuration/src/main/AndroidManifest.xml
index 745b5a7b1a2..0bd949c2557 100644
--- a/plugins/configuration/src/main/AndroidManifest.xml
+++ b/plugins/configuration/src/main/AndroidManifest.xml
@@ -17,6 +17,10 @@
android:name=".maintenance.activities.PrefImportListActivity"
android:exported="false"
android:theme="@style/AppTheme" />
+
uri?.let {
+ // Check if user selected a subdirectory instead of root AAPS directory
+ val lastPathSegment = uri.lastPathSegment ?: ""
+
+ // Extract directory name from the path
+ // First remove the storage prefix (e.g., "primary:")
+ val pathAfterColon = when {
+ lastPathSegment.contains(":") -> lastPathSegment.substringAfterLast(":")
+ else -> lastPathSegment
+ }
+ // Then get just the last directory name (e.g., "AAPS/preferences" -> "preferences")
+ val directoryName = pathAfterColon.substringAfterLast("/", pathAfterColon)
+
+ // Warn if user selected a subdirectory instead of root AAPS directory
+ // These subdirectories are managed by the app
+ val managedSubdirectories = listOf("preferences", "extra", "exports", "temp")
+ if (managedSubdirectories.any { it.equals(directoryName, ignoreCase = true) }) {
+ WarningDialog.showWarning(
+ this,
+ rh.gs(R.string.warning_wrong_directory_selected),
+ rh.gs(R.string.warning_wrong_directory_message, directoryName),
+ android.R.string.ok
+ )
+ return@registerForActivityResult
+ }
+
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
preferences.put(StringKey.AapsDirectoryUri, uri.toString())
rxBus.send(EventAAPSDirectorySelected(uri.path ?: "UNKNOWN"))
@@ -107,6 +135,15 @@ open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() {
super.attachBaseContext(LocaleHelper.wrap(newBase))
}
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+
+ // Handle cloud import result
+ if (requestCode == CloudConstants.CLOUD_IMPORT_REQUEST_CODE && resultCode == RESULT_OK) {
+ importExportPrefs.doImportSharedPreferences(this)
+ }
+ }
+
// Used for SetupWizardActivity
open fun updateButtons() {}
}
\ No newline at end of file
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/di/CloudStorageModule.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/di/CloudStorageModule.kt
new file mode 100644
index 00000000000..d4384d78000
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/di/CloudStorageModule.kt
@@ -0,0 +1,40 @@
+package app.aaps.plugins.configuration.di
+
+import app.aaps.plugins.configuration.maintenance.cloud.CloudStorageProvider
+import app.aaps.plugins.configuration.maintenance.cloud.providers.googledrive.GoogleDriveProvider
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+
+/**
+ * Dagger module for cloud storage providers.
+ *
+ * This module uses multi-binding to automatically collect all CloudStorageProvider
+ * implementations. Adding a new cloud provider is as simple as:
+ * 1. Create a class implementing CloudStorageProvider
+ * 2. Add a new @Binds @IntoSet method here
+ *
+ * Runtime Provider Selection:
+ * - All providers registered here are injected into CloudStorageManager as a Set
+ * - CloudStorageManager stores them in a map keyed by storageType
+ * - User selects which provider to use via SharedPreferences (PREF_CLOUD_STORAGE_TYPE)
+ * - CloudStorageManager.getActiveProvider() returns the provider based on user's selection
+ * - This allows runtime switching without code changes
+ *
+ * The CloudStorageManager will automatically receive all registered providers
+ * without needing to know about specific implementations at compile time.
+ */
+@Module
+abstract class CloudStorageModule {
+
+ /**
+ * Bind GoogleDriveProvider into the set of cloud storage providers.
+ */
+ @Binds
+ @IntoSet
+ abstract fun bindGoogleDriveProvider(provider: GoogleDriveProvider): CloudStorageProvider
+
+ // Future providers can be added here:
+ // @Binds @IntoSet abstract fun bindDropboxProvider(provider: DropboxProvider): CloudStorageProvider
+ // @Binds @IntoSet abstract fun bindOneDriveProvider(provider: OneDriveProvider): CloudStorageProvider
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/di/ConfigurationModule.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/di/ConfigurationModule.kt
index 10c0086e9c2..63190440361 100644
--- a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/di/ConfigurationModule.kt
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/di/ConfigurationModule.kt
@@ -13,6 +13,7 @@ import app.aaps.plugins.configuration.configBuilder.RunningConfigurationImpl
import app.aaps.plugins.configuration.maintenance.FileListProviderImpl
import app.aaps.plugins.configuration.maintenance.ImportExportPrefsImpl
import app.aaps.plugins.configuration.maintenance.MaintenanceFragment
+import app.aaps.plugins.configuration.maintenance.activities.CloudPrefImportListActivity
import app.aaps.plugins.configuration.maintenance.activities.CustomWatchfaceImportListActivity
import app.aaps.plugins.configuration.maintenance.activities.LogSettingActivity
import app.aaps.plugins.configuration.maintenance.activities.PrefImportListActivity
@@ -25,7 +26,8 @@ import dagger.android.ContributesAndroidInjector
@Module(
includes = [
ConfigurationModule.Bindings::class,
- SetupWizardModule::class
+ SetupWizardModule::class,
+ CloudStorageModule::class
]
)
abstract class ConfigurationModule {
@@ -37,6 +39,7 @@ abstract class ConfigurationModule {
@ContributesAndroidInjector abstract fun contributesCsvExportWorker(): ImportExportPrefsImpl.CsvExportWorker
@ContributesAndroidInjector abstract fun contributesApsResultExportWorker(): ImportExportPrefsImpl.ApsResultExportWorker
@ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity
+ @ContributesAndroidInjector abstract fun contributesCloudPrefImportListActivity(): CloudPrefImportListActivity
@ContributesAndroidInjector abstract fun contributesCustomWatchfaceImportListActivity(): CustomWatchfaceImportListActivity
@ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat
@ContributesAndroidInjector abstract fun prefImportListProviderInjector(): FileListProvider
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/ImportExportPrefsImpl.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/ImportExportPrefsImpl.kt
index d35b75a8e82..e7679177f67 100644
--- a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/ImportExportPrefsImpl.kt
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/ImportExportPrefsImpl.kt
@@ -13,7 +13,9 @@ import androidx.core.content.ContextCompat
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.lifecycleScope
import androidx.work.ExistingWorkPolicy
+import kotlinx.coroutines.launch
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkerParameters
@@ -67,6 +69,13 @@ import app.aaps.plugins.configuration.maintenance.data.PrefsFormat
import app.aaps.plugins.configuration.maintenance.data.PrefsStatusImpl
import app.aaps.plugins.configuration.maintenance.dialogs.PrefImportSummaryDialog
import app.aaps.plugins.configuration.maintenance.formats.EncryptedPrefsFormat
+import app.aaps.plugins.configuration.maintenance.cloud.CloudConstants
+import app.aaps.plugins.configuration.maintenance.cloud.CloudStorageManager
+import app.aaps.plugins.configuration.maintenance.cloud.StorageTypes
+import app.aaps.plugins.configuration.maintenance.cloud.ExportOptionsDialog
+import app.aaps.plugins.configuration.maintenance.cloud.ImportSourceDialog
+import app.aaps.plugins.configuration.maintenance.PrefsMetadataKeyImpl
+import app.aaps.plugins.configuration.maintenance.activities.CloudPrefImportListActivity
import app.aaps.shared.impl.weardata.ZipWatchfaceFormat
import dagger.Reusable
import io.reactivex.rxjava3.disposables.CompositeDisposable
@@ -77,6 +86,10 @@ import java.io.FileNotFoundException
import java.io.IOException
import javax.inject.Inject
+// Added for dialog callback explicit types
+import android.content.DialogInterface
+import androidx.appcompat.app.AlertDialog
+
/**
* Created by mike on 03.07.2016.
*/
@@ -100,9 +113,18 @@ class ImportExportPrefsImpl @Inject constructor(
private val context: Context,
private val dataWorkerStorage: DataWorkerStorage,
private val activePlugin: ActivePlugin,
- private val configBuilder: ConfigBuilder
+ private val configBuilder: ConfigBuilder,
+ private val cloudStorageManager: CloudStorageManager,
+ private val exportOptionsDialog: ExportOptionsDialog,
+ private val importSourceDialog: ImportSourceDialog
) : ImportExportPrefs {
+ companion object {
+ var cloudPrefsFiles: List = emptyList()
+ var cloudNextPageToken: String? = null
+ var cloudTotalFilesCount: Int = 0 // Total count of settings files
+ }
+
override var selectedImportFile: PrefsFile? = null
override fun prefsFileExists(): Boolean = prefFileList.listPreferenceFiles().isNotEmpty()
@@ -231,6 +253,34 @@ class ImportExportPrefsImpl @Inject constructor(
)
}
+ // Added: Confirmation dialog for non-filename targets (e.g., Google Drive) that can force password prompt
+ private fun askToConfirmExport(activity: FragmentActivity, targetDisplayName: String, forcePrompt: Boolean = false, then: ((password: String) -> Unit)) {
+ if (!assureMasterPasswordSet(activity, app.aaps.core.ui.R.string.nav_export)) return
+
+ if (!forcePrompt) {
+ val (password, isExpired, isAboutToExpire) = exportPasswordDataStore.getPasswordFromDataStore(context)
+ if (password.isNotEmpty() && !(isExpired || isAboutToExpire)) {
+ then(password)
+ return
+ }
+ }
+ exportPasswordDataStore.clearPasswordDataStore(context)
+
+ TwoMessagesAlertDialog.showAlert(
+ activity,
+ rh.gs(app.aaps.core.ui.R.string.nav_export),
+ rh.gs(R.string.export_to) + " " + targetDisplayName + " ?",
+ rh.gs(R.string.password_preferences_encrypt_prompt),
+ {
+ askForMasterPassIfNeeded(activity, R.string.preferences_export_canceled) { pwd ->
+ then(exportPasswordDataStore.putPasswordToDataStore(context, pwd))
+ }
+ },
+ null,
+ R.drawable.ic_header_export
+ )
+ }
+
private fun askToConfirmImport(activity: FragmentActivity, fileToImport: PrefsFile, then: ((password: String) -> Unit)) {
if (!assureMasterPasswordSet(activity, R.string.import_setting)) return
TwoMessagesAlertDialog.showAlert(
@@ -300,40 +350,363 @@ class ImportExportPrefsImpl @Inject constructor(
}
private fun exportSharedPreferences(activity: FragmentActivity) {
+ // Check export destination preference for user settings
+ val localEnabled = exportOptionsDialog.isSettingsLocalEnabled()
+ val cloudEnabled = exportOptionsDialog.isSettingsCloudEnabled()
+ val isCloudActive = cloudStorageManager.isCloudStorageActive()
+
+ // Determine export destinations
+ val exportToLocal = localEnabled
+ val exportToCloud = cloudEnabled && isCloudActive
+
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT exportToLocal=$exportToLocal, exportToCloud=$exportToCloud")
+
+ if (exportToLocal && exportToCloud) {
+ // Export to both: local first, then cloud
+ exportToBoth(activity)
+ return
+ }
+
+ if (exportToCloud) {
+ exportToCloud(activity)
+ return
+ }
+
+ // Local export requires AAPS base directory
+ val directoryUri = preferences.getIfExists(StringKey.AapsDirectoryUri)
+ if (directoryUri.isNullOrEmpty()) {
+ ToastUtils.errorToast(activity, rh.gs(R.string.error_accessing_filesystem_select_aaps_directory_properly))
+ return
+ }
+ exportToLocal(activity)
+ }
+
+ /**
+ * Export to both local and cloud storage
+ * First export to local, then to cloud
+ */
+ private fun exportToBoth(activity: FragmentActivity) {
+ // Check local directory first
+ val directoryUri = preferences.getIfExists(StringKey.AapsDirectoryUri)
+ if (directoryUri.isNullOrEmpty()) {
+ ToastUtils.errorToast(activity, rh.gs(R.string.error_accessing_filesystem_select_aaps_directory_properly))
+ return
+ }
+
+ prefFileList.ensureExportDirExists()
+ val newFile = prefFileList.newPreferenceFile()
+
+ if (newFile == null) {
+ ToastUtils.errorToast(activity, rh.gs(R.string.exported_failed))
+ return
+ }
+
+ // Ask password once, then export to both destinations
+ askToConfirmExport(activity, newFile) { password ->
+ // Export to local first
+ doExportToLocal(activity, newFile, password)
+ // Then export to cloud
+ doExportToCloud(activity, password)
+ }
+ }
+
+ private fun exportToLocal(activity: FragmentActivity) {
prefFileList.ensureExportDirExists()
- val newFile = prefFileList.newPreferenceFile() ?: return
+ val newFile = prefFileList.newPreferenceFile()
+
+ if (newFile == null) {
+ ToastUtils.errorToast(activity, rh.gs(R.string.exported_failed))
+ return
+ }
askToConfirmExport(activity, newFile) { password ->
- // Save preferences
- val exportResultMessage = if (savePreferences(newFile, password))
- rh.gs(R.string.exported)
- else
- rh.gs(R.string.exported_failed)
+ doExportToLocal(activity, newFile, password)
+ }
+ }
+
+ /**
+ * Perform local export without password prompt
+ */
+ private fun doExportToLocal(activity: FragmentActivity, newFile: DocumentFile, password: String) {
+ val exportResultMessage = if (savePreferences(newFile, password))
+ rh.gs(R.string.exported)
+ else
+ rh.gs(R.string.exported_failed)
+
+ ToastUtils.okToast(activity, exportResultMessage)
+
+ disposable += persistenceLayer.insertPumpTherapyEventIfNewByTimestamp(
+ therapyEvent = TE.asSettingsExport(error = exportResultMessage),
+ timestamp = dateUtil.now(),
+ action = Action.EXPORT_SETTINGS,
+ source = Sources.Automation,
+ note = "Manual Local: $exportResultMessage",
+ listValues = listOf()
+ ).subscribe()
+ }
+
+ private fun exportToCloud(activity: FragmentActivity) {
+ activity.lifecycleScope.launch {
+ // Pre-check cloud connection before asking for password
+ val provider = cloudStorageManager.getActiveProvider()
+ if (provider == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_NO_PROVIDER")
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_connection_failed))
+ return@launch
+ }
+
+ if (!provider.testConnection()) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_CONN_FAIL")
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_connection_failed))
+ return@launch
+ }
- // Send toast alert to overview
- ToastUtils.okToast(activity, exportResultMessage)
+ // Create temp file for password prompt display
+ val tempDir = prefFileList.ensureTempDirExists()
+ if (tempDir == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_NO_TEMP_DIR")
+ ToastUtils.errorToast(activity, rh.gs(R.string.exported_failed))
+ return@launch
+ }
- // Register this event
- disposable += persistenceLayer.insertPumpTherapyEventIfNewByTimestamp(
- therapyEvent = TE.asSettingsExport(error = exportResultMessage),
- timestamp = dateUtil.now(),
- action = Action.EXPORT_SETTINGS, // Signal export was done....
- source = Sources.Automation,
- note = "Manual: $exportResultMessage",
- listValues = listOf()
- ).subscribe()
+ val timeLocal = org.joda.time.LocalDateTime.now().toString(org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
+ val exportFileName = "${timeLocal}_${config.FLAVOR}.json"
+ val tempDoc = tempDir.createFile("application/json", exportFileName)
+ if (tempDoc == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_CREATE_TEMP_FAIL")
+ ToastUtils.errorToast(activity, rh.gs(R.string.exported_failed))
+ return@launch
+ }
+
+ askToConfirmExport(activity, tempDoc) { password ->
+ // Delete the temp file created for prompt, doExportToCloud will create its own
+ tempDoc.delete()
+ doExportToCloud(activity, password)
+ }
}
}
+
+ /**
+ * Perform cloud export without password prompt
+ */
+ private fun doExportToCloud(activity: FragmentActivity, password: String) {
+ activity.lifecycleScope.launch {
+ try {
+ val provider = cloudStorageManager.getActiveProvider()
+ if (provider == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_NO_PROVIDER")
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_connection_failed))
+ return@launch
+ }
+
+ if (!provider.testConnection()) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_CONN_FAIL")
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_connection_failed))
+ return@launch
+ }
- override fun exportSharedPreferencesNonInteractive(context: Context, password: String): Boolean {
- prefFileList.ensureExportDirExists()
- val newFile = prefFileList.newPreferenceFile() ?: return false
+ val tempDir = prefFileList.ensureTempDirExists()
+ if (tempDir == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_NO_TEMP_DIR")
+ ToastUtils.errorToast(activity, rh.gs(R.string.export_to_cloud_failed))
+ return@launch
+ }
+
+ val timeLocal = org.joda.time.LocalDateTime.now().toString(org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
+ val exportFileName = "${timeLocal}_${config.FLAVOR}.json"
+ val tempDoc = tempDir.createFile("application/json", exportFileName)
+ if (tempDoc == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_CREATE_TEMP_FAIL")
+ ToastUtils.errorToast(activity, rh.gs(R.string.export_to_cloud_failed))
+ return@launch
+ }
+
+ val saved = savePreferences(tempDoc, password)
+ if (!saved) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_SAVE_PREFS_FAIL")
+ ToastUtils.errorToast(activity, rh.gs(R.string.export_to_cloud_failed))
+ tempDoc.delete()
+ return@launch
+ }
+
+ val bytes = activity.contentResolver.openInputStream(tempDoc.uri)?.use { it.readBytes() }
+ if (bytes == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_READ_TEMP_FAIL")
+ ToastUtils.errorToast(activity, rh.gs(R.string.export_to_cloud_failed))
+ tempDoc.delete()
+ return@launch
+ }
+
+ provider.getOrCreateFolderPath(CloudConstants.CLOUD_PATH_SETTINGS)?.let {
+ provider.setSelectedFolderId(it)
+ }
- // Registering export settings event already done by automation
- return savePreferences(newFile, password)
+ ToastUtils.longInfoToast(context, rh.gs(R.string.uploading_to_cloud))
+
+ var uploadedFileId = provider.uploadFileToPath(
+ exportFileName, bytes, "application/json", CloudConstants.CLOUD_PATH_SETTINGS
+ )
+ if (uploadedFileId == null) {
+ uploadedFileId = provider.uploadFile(exportFileName, bytes, "application/json")
+ }
+
+ val exportResultMessage = if (uploadedFileId != null) {
+ rh.gs(R.string.exported_to_cloud) + "\n" + rh.gs(R.string.cloud_directory_path, CloudConstants.CLOUD_PATH_SETTINGS)
+ } else {
+ rh.gs(R.string.export_to_cloud_failed)
+ }
+
+ ToastUtils.infoToast(activity, exportResultMessage)
+
+ disposable += persistenceLayer.insertPumpTherapyEventIfNewByTimestamp(
+ therapyEvent = TE.asSettingsExport(error = exportResultMessage),
+ timestamp = dateUtil.now(),
+ action = Action.EXPORT_SETTINGS,
+ source = Sources.Automation,
+ note = "Manual Cloud: $exportResultMessage",
+ listValues = listOf()
+ ).subscribe()
+
+ tempDoc.delete()
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} EXPORT_EXCEPTION", e)
+ ToastUtils.errorToast(activity, rh.gs(R.string.export_to_cloud_failed))
+ }
+ }
+ }
+
+ override fun exportSharedPreferencesNonInteractive(context: Context, password: String): Boolean {
+ // Check export destination preferences (same logic as manual export)
+ val localEnabled = exportOptionsDialog.isSettingsLocalEnabled()
+ val cloudEnabled = exportOptionsDialog.isSettingsCloudEnabled()
+ val isCloudActive = cloudStorageManager.isCloudStorageActive()
+
+ val exportToLocal = localEnabled
+ val exportToCloud = cloudEnabled && isCloudActive
+
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT exportToLocal=$exportToLocal, exportToCloud=$exportToCloud")
+
+ // Export to local if enabled
+ var localResult = true
+ if (exportToLocal) {
+ prefFileList.ensureExportDirExists()
+ val newFile = prefFileList.newPreferenceFile()
+ if (newFile != null) {
+ localResult = savePreferences(newFile, password)
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_LOCAL result=$localResult")
+ } else {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_LOCAL_NO_FILE")
+ localResult = false
+ }
+ }
+
+ // Export to cloud if enabled
+ if (exportToCloud) {
+ kotlinx.coroutines.GlobalScope.launch(Dispatchers.IO) {
+ try {
+ val provider = cloudStorageManager.getActiveProvider()
+ if (provider == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_NO_PROVIDER")
+ return@launch
+ }
+
+ if (!provider.testConnection()) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_CONN_FAIL")
+ return@launch
+ }
+
+ val tempDir = prefFileList.ensureTempDirExists()
+ if (tempDir == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_NO_TEMP_DIR")
+ return@launch
+ }
+
+ val timeLocal = org.joda.time.LocalDateTime.now().toString(org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
+ val fileName = "${timeLocal}_${config.FLAVOR}.json"
+ val tempDoc = tempDir.createFile("application/json", fileName)
+ if (tempDoc == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_CREATE_TEMP_FAIL")
+ return@launch
+ }
+
+ val saved = savePreferences(tempDoc, password)
+ if (!saved) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_SAVE_TEMP_FAIL")
+ tempDoc.delete()
+ return@launch
+ }
+
+ val fileContent = tempDoc.uri.let { uri ->
+ context.contentResolver.openInputStream(uri)?.use { it.readBytes() }
+ }
+
+ tempDoc.delete()
+
+ if (fileContent != null) {
+ // Use uploadFileToPath for consistent folder structure
+ var uploadedFileId = provider.uploadFileToPath(
+ fileName, fileContent, "application/json", CloudConstants.CLOUD_PATH_SETTINGS
+ )
+ if (uploadedFileId == null) {
+ uploadedFileId = provider.uploadFile(fileName, fileContent, "application/json")
+ }
+
+ if (uploadedFileId != null) {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_CLOUD_OK fileName=$fileName fileId=$uploadedFileId")
+ } else {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_CLOUD_FAIL")
+ }
+ } else {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_READ_FILE_FAIL")
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} NONINTERACTIVE_EXPORT_EXCEPTION", e)
+ }
+ }
+ }
+
+ // Return true if at least one export method succeeded or was started
+ return if (exportToLocal && exportToCloud) {
+ localResult // Cloud is async, return local result
+ } else if (exportToCloud) {
+ true // Cloud export started (async)
+ } else {
+ localResult // Only local export
+ }
}
override fun importSharedPreferences(activity: FragmentActivity) {
+ // Check if both local and cloud are enabled - show selection dialog
+ if (importSourceDialog.shouldShowSourceSelection()) {
+ importSourceDialog.showImportSourceDialog(activity) { source ->
+ when (source) {
+ ImportSourceDialog.ImportSource.LOCAL -> importFromLocal(activity)
+ ImportSourceDialog.ImportSource.CLOUD -> importFromCloud(activity)
+ }
+ }
+ return
+ }
+
+ // Only one source enabled - use it directly
+ val singleSource = importSourceDialog.getSingleEnabledSource()
+ when (singleSource) {
+ ImportSourceDialog.ImportSource.CLOUD -> {
+ importFromCloud(activity)
+ return
+ }
+ ImportSourceDialog.ImportSource.LOCAL, null -> {
+ importFromLocal(activity)
+ }
+ }
+ }
+
+ private fun importFromLocal(activity: FragmentActivity) {
+ // Local import requires AAPS base directory
+ val directoryUri = preferences.getIfExists(StringKey.AapsDirectoryUri)
+ if (directoryUri.isNullOrEmpty()) {
+ ToastUtils.errorToast(activity, rh.gs(R.string.error_accessing_filesystem_select_aaps_directory_properly))
+ return
+ }
try {
if (activity is DaggerAppCompatActivityWithResult)
@@ -346,6 +719,112 @@ class ImportExportPrefsImpl @Inject constructor(
}
}
+ private fun importFromCloud(activity: FragmentActivity) {
+ // Show loading indicator
+ val progressDialog = AlertDialog.Builder(activity)
+ .setTitle(rh.gs(R.string.import_from_cloud))
+ .setMessage(rh.gs(R.string.loading_from_cloud))
+ .setCancelable(false)
+ .create()
+ progressDialog.show()
+
+ activity.lifecycleScope.launch {
+ try {
+ val provider = cloudStorageManager.getActiveProvider()
+ if (provider == null) {
+ progressDialog.dismiss()
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_connection_failed))
+ return@launch
+ }
+
+ if (!provider.testConnection()) {
+ progressDialog.dismiss()
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_connection_failed))
+ return@launch
+ }
+ // Auto-locate to fixed settings folder as list source, fall back to selected/root if failed
+ val settingsFolderId = provider.getOrCreateFolderPath(CloudConstants.CLOUD_PATH_SETTINGS)
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} IMPORT_CLOUD getOrCreateFolderPath(${CloudConstants.CLOUD_PATH_SETTINGS}) returned: $settingsFolderId")
+ if (!settingsFolderId.isNullOrEmpty()) {
+ provider.setSelectedFolderId(settingsFolderId)
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} IMPORT_CLOUD setSelectedFolderId: $settingsFolderId")
+ } else {
+ aapsLogger.warn(LTag.CORE, "${CloudConstants.LOG_PREFIX} IMPORT_CLOUD getOrCreateFolderPath returned null/empty, will use default folder")
+ }
+
+ ToastUtils.infoToast(activity, rh.gs(R.string.cloud_directory_path, CloudConstants.CLOUD_PATH_SETTINGS))
+
+ // Count total files first using the provider interface
+ cloudTotalFilesCount = provider.countSettingsFiles()
+
+ val page = provider.listSettingsFiles(pageSize = CloudConstants.DEFAULT_PAGE_SIZE, pageToken = null)
+ val files = page.files
+ cloudNextPageToken = page.nextPageToken
+ if (files.isEmpty()) {
+ progressDialog.dismiss()
+ ToastUtils.warnToast(activity, rh.gs(R.string.no_settings_files_found))
+ return@launch
+ }
+
+ // Filter files matching yyyy-MM-dd_HHmmss*.json pattern
+ val namePattern = Regex("^\\d{4}-\\d{2}-\\d{2}_\\d{6}.*\\.json$", RegexOption.IGNORE_CASE)
+ val matchingFiles = files.filter { f -> namePattern.containsMatchIn(f.name) }
+
+ // Download all files and parse metadata, just like local files
+ val prefsFiles = mutableListOf()
+ var processedFiles = 0
+ for (file in matchingFiles) {
+ try {
+ // Update progress
+ progressDialog.setMessage(rh.gs(R.string.loading_file_progress, file.name, processedFiles + 1, matchingFiles.size))
+
+ val bytes = provider.downloadFile(file.id)
+ if (bytes != null) {
+ val content = String(bytes, Charsets.UTF_8)
+ // Parse file metadata
+ val metadata = encryptedPrefsFormat.loadMetadata(content)
+ val prefsFile = PrefsFile(file.name, content, metadata)
+ prefsFiles.add(prefsFile)
+ }
+ } catch (e: Exception) {
+ aapsLogger.warn(LTag.CORE, "Failed to load metadata for ${file.name}", e)
+ // If metadata parsing fails, still add the file but without metadata
+ try {
+ val bytes = provider.downloadFile(file.id)
+ if (bytes != null) {
+ val content = String(bytes, Charsets.UTF_8)
+ val prefsFile = PrefsFile(file.name, content, emptyMap())
+ prefsFiles.add(prefsFile)
+ }
+ } catch (e2: Exception) {
+ aapsLogger.error(LTag.CORE, "Failed to download ${file.name}", e2)
+ }
+ }
+ processedFiles++
+ }
+
+ progressDialog.dismiss()
+
+ if (prefsFiles.isEmpty()) {
+ ToastUtils.warnToast(activity, rh.gs(R.string.no_settings_files_found))
+ return@launch
+ }
+
+ // Use CloudPrefImportListActivity to display file details
+ cloudPrefsFiles = prefsFiles // Store file list temporarily
+ val intent = Intent(activity, CloudPrefImportListActivity::class.java)
+ if (activity is DaggerAppCompatActivityWithResult) {
+ activity.startActivityForResult(intent, CloudConstants.CLOUD_IMPORT_REQUEST_CODE)
+ }
+
+ } catch (e: Exception) {
+ progressDialog.dismiss()
+ aapsLogger.error(LTag.CORE, "Cloud import init failed", e)
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_folder_error))
+ }
+ }
+ }
+
override fun importCustomWatchface(fragment: Fragment) {
fragment.activity?.let { importCustomWatchface(it) }
}
@@ -403,6 +882,10 @@ class ImportExportPrefsImpl @Inject constructor(
sp.putString(key, value)
}
}
+
+ // All settings including Google Drive settings and export destination preferences
+ // are now imported from backup file. If tokens are invalid, user can re-authorize.
+
activePlugin.afterImport()
restartAppAfterImport(activity)
} else {
@@ -445,11 +928,13 @@ class ImportExportPrefsImpl @Inject constructor(
}
override fun exportUserEntriesCsv(activity: FragmentActivity) {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT exportUserEntriesCsv called, enqueuing WorkManager")
WorkManager.getInstance(activity).enqueueUniqueWork(
"export",
ExistingWorkPolicy.APPEND_OR_REPLACE,
OneTimeWorkRequest.Builder(CsvExportWorker::class.java).build()
)
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT WorkManager enqueued")
}
class CsvExportWorker(
@@ -462,14 +947,41 @@ class ImportExportPrefsImpl @Inject constructor(
@Inject lateinit var userEntryPresentationHelper: UserEntryPresentationHelper
@Inject lateinit var storage: Storage
@Inject lateinit var persistenceLayer: PersistenceLayer
+ @Inject lateinit var cloudStorageManager: CloudStorageManager
+ @Inject lateinit var exportOptionsDialog: ExportOptionsDialog
override suspend fun doWorkAndLog(): Result {
- val entries = persistenceLayer.getUserEntryFilteredDataFromTime(MidnightTime.calc() - T.days(90).msecs()).blockingGet()
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT doWorkAndLog started")
+
+ val entries: List = try {
+ persistenceLayer.getUserEntryFilteredDataFromTime(MidnightTime.calc() - T.days(90).msecs()).blockingGet()
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "CSV_EXPORT Error reading user entries from database", e)
+ ToastUtils.longErrorToast(context, rh.gs(R.string.csv_upload_error) + ": Database read error")
+ return Result.failure(workDataOf("Error" to "Database read error: ${e.message}"))
+ }
+
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT entries count=${entries.size}")
+
+ val isCsvCloudEnabled = exportOptionsDialog.isCsvCloudEnabled()
+ val isCloudActive = cloudStorageManager.isCloudStorageActive()
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT isCsvCloudEnabled=$isCsvCloudEnabled, isCloudActive=$isCloudActive")
+
+ if (isCsvCloudEnabled && isCloudActive) {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT calling exportToCloud")
+ return exportToCloud(entries)
+ } else {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT calling exportToLocal")
+ return exportToLocal(entries)
+ }
+ }
+
+ private suspend fun exportToLocal(userEntries: List): Result {
prefFileList.ensureExportDirExists()
val newFile = prefFileList.newExportCsvFile() ?: return Result.failure()
var ret = Result.success()
try {
- saveCsv(newFile, entries)
+ saveCsv(newFile, userEntries)
ToastUtils.okToast(context, rh.gs(R.string.ue_exported))
} catch (e: FileNotFoundException) {
ToastUtils.errorToast(context, rh.gs(R.string.filenotfound) + " " + newFile)
@@ -482,6 +994,58 @@ class ImportExportPrefsImpl @Inject constructor(
}
return ret
}
+
+ private suspend fun exportToCloud(userEntries: List): Result {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD started with ${userEntries.size} entries")
+ try {
+ val provider = cloudStorageManager.getActiveProvider()
+ if (provider == null) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD no active provider")
+ ToastUtils.longErrorToast(context, rh.gs(R.string.csv_upload_failed))
+ return Result.failure(workDataOf("Error" to "No active cloud provider"))
+ }
+
+ val contents = userEntryPresentationHelper.userEntriesToCsv(userEntries)
+ val fileName = "UserEntries_${org.joda.time.LocalDateTime.now().toString(org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd_HHmmss"))}.csv"
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD fileName=$fileName, contents length=${contents.length}")
+
+ // First locate selected folder to fixed path
+ val folderId = provider.getOrCreateFolderPath(CloudConstants.CLOUD_PATH_USER_ENTRIES)
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD folderId=$folderId")
+ folderId?.let { provider.setSelectedFolderId(it) }
+
+ ToastUtils.longInfoToast(context, rh.gs(R.string.uploading_to_cloud))
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD uploading...")
+
+ var uploadedFileId = provider.uploadFileToPath(
+ fileName,
+ contents.toByteArray(Charsets.UTF_8),
+ "text/csv",
+ CloudConstants.CLOUD_PATH_USER_ENTRIES
+ )
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD uploadFileToPath result=$uploadedFileId")
+
+ if (uploadedFileId == null) {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD trying fallback uploadFile")
+ uploadedFileId = provider.uploadFile(fileName, contents.toByteArray(Charsets.UTF_8), "text/csv")
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD fallback uploadFile result=$uploadedFileId")
+ }
+
+ if (uploadedFileId != null) {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD SUCCESS")
+ ToastUtils.okToast(context, rh.gs(R.string.csv_uploaded_to_cloud) + "\n" + rh.gs(R.string.cloud_directory_path, CloudConstants.CLOUD_PATH_USER_ENTRIES), isShort = false)
+ return Result.success()
+ } else {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD FAILED - uploadedFileId is null")
+ ToastUtils.longErrorToast(context, rh.gs(R.string.csv_upload_failed))
+ return Result.failure(workDataOf("Error" to "Cloud upload failed"))
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "${CloudConstants.LOG_PREFIX} CSV_EXPORT_CLOUD EXCEPTION", e)
+ ToastUtils.longErrorToast(context, rh.gs(R.string.csv_upload_error))
+ return Result.failure(workDataOf("Error" to "Exception: ${e.message}"))
+ }
+ }
private fun saveCsv(file: DocumentFile, userEntries: List) {
try {
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenanceFragment.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenanceFragment.kt
index 6bed0a4669e..b9febfaf17a 100644
--- a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenanceFragment.kt
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenanceFragment.kt
@@ -38,6 +38,10 @@ import app.aaps.plugins.configuration.R
import app.aaps.plugins.configuration.activities.DaggerAppCompatActivityWithResult
import app.aaps.plugins.configuration.databinding.MaintenanceFragmentBinding
import app.aaps.plugins.configuration.maintenance.activities.LogSettingActivity
+import app.aaps.plugins.configuration.maintenance.cloud.CloudStorageManager
+import app.aaps.plugins.configuration.maintenance.cloud.CloudDirectoryDialog
+import app.aaps.plugins.configuration.maintenance.cloud.ExportOptionsDialog
+import app.aaps.plugins.configuration.maintenance.cloud.events.EventCloudStorageStatusChanged
import dagger.android.support.DaggerFragment
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
@@ -64,6 +68,9 @@ class MaintenanceFragment : DaggerFragment() {
@Inject lateinit var uiInteraction: UiInteraction
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var fileListProvider: FileListProvider
+ @Inject lateinit var cloudStorageManager: CloudStorageManager
+ @Inject lateinit var cloudDirectoryDialog: CloudDirectoryDialog
+ @Inject lateinit var exportOptionsDialog: ExportOptionsDialog
private val disposable = CompositeDisposable()
private var inMenu = false
@@ -172,13 +179,54 @@ class MaintenanceFragment : DaggerFragment() {
importExportPrefs.importSharedPreferences(activity as FragmentActivity)
}
}
+ // Local directory: only used for selecting AAPS base folder
binding.directory.setOnClickListener {
- maintenancePlugin.selectAapsDirectory(requireActivity() as DaggerAppCompatActivityWithResult)
+ (requireActivity() as? DaggerAppCompatActivityWithResult)?.let { act ->
+ maintenancePlugin.selectAapsDirectory(act)
+ }
+ }
+ // Cloud directory: choose not to use or Google Drive
+ binding.cloudDirectory.setOnClickListener {
+ (requireActivity() as? DaggerAppCompatActivityWithResult)?.let { act ->
+ cloudDirectoryDialog.showCloudDirectoryDialog(
+ act,
+ onLocalSelected = { /* Choose not to use cloud: set storage type to local, no action */ },
+ onCloudSelected = { /* Authorization and folder selection handled in dialog */ },
+ onStorageChanged = {
+ updateStorageErrorState()
+ updateDynamicButtonText()
+ updateExportOptionsButtonState()
+ }
+ )
+ }
+ }
+
+ // Cloud directory error icon click - show toast with error info
+ binding.cloudDirectoryErrorIcon.setOnClickListener {
+ app.aaps.core.ui.toast.ToastUtils.warnToast(requireContext(), rh.gs(R.string.cloud_token_expired_or_invalid))
+ }
+
+ // Export destination: configure destination for various export functions
+ binding.exportOptions.setOnClickListener {
+ val hasCloudDirectory = cloudStorageManager.isCloudStorageActive()
+ if (!hasCloudDirectory) {
+ // Show message if cloud directory is not set up
+ app.aaps.core.ui.toast.ToastUtils.warnToast(requireContext(), rh.gs(R.string.setup_cloud_directory_first))
+ return@setOnClickListener
+ }
+ (requireActivity() as? DaggerAppCompatActivityWithResult)?.let { act ->
+ exportOptionsDialog.showExportOptionsDialog(act) {
+ // Settings changed callback - update button text
+ updateDynamicButtonText()
+ }
+ }
}
binding.navLogsettings.setOnClickListener { startActivity(Intent(activity, LogSettingActivity::class.java)) }
binding.exportCsv.setOnClickListener {
+ aapsLogger.info(LTag.CORE, "CSV_EXPORT exportCsv button clicked")
activity?.let { activity ->
OKDialog.showConfirmation(activity, rh.gs(app.aaps.core.ui.R.string.ue_export_to_csv) + "?") {
+ aapsLogger.info(LTag.CORE, "CSV_EXPORT user confirmed, calling exportUserEntriesCsv")
uel.log(Action.EXPORT_CSV, Sources.Maintenance)
importExportPrefs.exportUserEntriesCsv(activity)
}
@@ -190,7 +238,33 @@ class MaintenanceFragment : DaggerFragment() {
override fun onResume() {
super.onResume()
- if (inMenu) queryProtection() else updateProtectedUi()
+ // Check and restore cloud settings (prevent settings loss after app update)
+ checkAndRestoreCloudSettings()
+
+ // Subscribe to cloud storage status changes to update UI immediately
+ disposable += rxBus
+ .toObservable(EventCloudStorageStatusChanged::class.java)
+ .observeOn(aapsSchedulers.main)
+ .subscribe({ updateStorageErrorState() }, fabricPrivacy::logException)
+
+ if (inMenu) queryProtection() else {
+ updateProtectedUi()
+ updateStorageErrorState()
+ updateDynamicButtonText()
+ updateExportOptionsButtonState()
+ }
+ }
+
+ /**
+ * Check and restore cloud storage settings
+ */
+ private fun checkAndRestoreCloudSettings() {
+ try {
+ // Trigger auto-restore logic
+ cloudStorageManager.getActiveStorageType()
+ } catch (e: Exception) {
+ aapsLogger.warn(LTag.CORE, "Failed to check cloud storage settings", e)
+ }
}
@Synchronized
@@ -204,6 +278,79 @@ class MaintenanceFragment : DaggerFragment() {
val isLocked = protectionCheck.isLocked(PREFERENCES)
binding.mainLayout.visibility = isLocked.not().toVisibility()
binding.unlock.visibility = isLocked.toVisibility()
+
+ // Update storage error state when UI becomes available
+ if (!isLocked) {
+ updateStorageErrorState()
+ updateDynamicButtonText()
+ }
+ }
+
+ private fun updateStorageErrorState() {
+ // Local directory - no error icon needed (local storage doesn't have connection errors)
+ binding.directoryErrorIcon.visibility = View.GONE
+
+ // Cloud directory error - show when cloud is active but token is invalid/expired
+ val isCloudActive = cloudStorageManager.isCloudStorageActive()
+ val provider = cloudStorageManager.getActiveProvider()
+ val hasValidCredentials = provider?.hasValidCredentials() ?: false
+ val hasCloudConnectionError = provider?.hasConnectionError() ?: false
+
+ // Show error icon if cloud is active but credentials are invalid or there's a connection error
+ val showCloudError = isCloudActive && (!hasValidCredentials || hasCloudConnectionError)
+ binding.cloudDirectoryErrorIcon.visibility = if (showCloudError) View.VISIBLE else View.GONE
+ }
+
+ /**
+ * Update export options button state based on cloud directory selection
+ */
+ private fun updateExportOptionsButtonState() {
+ val hasCloudDirectory = cloudStorageManager.isCloudStorageActive()
+ binding.exportOptions.alpha = if (hasCloudDirectory) 1.0f else 0.5f
+ }
+
+ /**
+ * Update dynamic button text based on export destination settings
+ */
+ private fun updateDynamicButtonText() {
+ val isAllCloud = exportOptionsDialog.isAllCloudEnabled()
+ val isCloudActive = cloudStorageManager.isCloudStorageActive()
+
+ // Log button text
+ val isLogCloud = isAllCloud || exportOptionsDialog.isLogCloudEnabled()
+ binding.logSend.text = rh.gs(
+ if (isLogCloud) R.string.send_logs_to_cloud else R.string.send_all_logs
+ )
+
+ // CSV button text
+ val isCsvCloud = isAllCloud || exportOptionsDialog.isCsvCloudEnabled()
+ binding.exportCsv.text = rh.gs(
+ if (isCsvCloud) R.string.export_csv_to_cloud else R.string.export_csv_to_local
+ )
+
+ // Settings export/import destinations
+ val isSettingsLocal = exportOptionsDialog.isSettingsLocalEnabled()
+ val isSettingsCloud = exportOptionsDialog.isSettingsCloudEnabled()
+ val bothEnabled = isSettingsLocal && isSettingsCloud && isCloudActive
+ val cloudOnly = isSettingsCloud && isCloudActive && !isSettingsLocal
+
+ // Export button text
+ binding.navExport.text = rh.gs(
+ when {
+ bothEnabled -> R.string.export_settings_both
+ cloudOnly -> R.string.export_settings_cloud
+ else -> R.string.export_settings_local
+ }
+ )
+
+ // Import button text
+ binding.navImport.text = rh.gs(
+ when {
+ bothEnabled -> R.string.import_settings_both
+ cloudOnly -> R.string.import_settings_cloud
+ else -> R.string.import_settings_local
+ }
+ )
}
private fun queryProtection() {
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenancePlugin.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenancePlugin.kt
index c8398cbc848..19f23c003ea 100644
--- a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenancePlugin.kt
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/MaintenancePlugin.kt
@@ -31,6 +31,13 @@ import app.aaps.core.validators.preferences.AdaptiveStringPreference
import app.aaps.core.validators.preferences.AdaptiveSwitchPreference
import app.aaps.plugins.configuration.R
import app.aaps.plugins.configuration.activities.DaggerAppCompatActivityWithResult
+import app.aaps.plugins.configuration.maintenance.cloud.CloudConstants
+import app.aaps.plugins.configuration.maintenance.cloud.CloudStorageManager
+import app.aaps.plugins.configuration.maintenance.cloud.StorageTypes
+import app.aaps.plugins.configuration.maintenance.cloud.ExportOptionsDialog
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.File
@@ -53,7 +60,9 @@ class MaintenancePlugin @Inject constructor(
private val config: Config,
private val fileListProvider: FileListProvider,
private val loggerUtils: LoggerUtils,
- private val uel: UserEntryLogger
+ private val uel: UserEntryLogger,
+ private val cloudStorageManager: CloudStorageManager,
+ private val exportOptionsDialog: ExportOptionsDialog
) : PluginBase(
PluginDescription()
.mainType(PluginType.GENERAL)
@@ -69,16 +78,25 @@ class MaintenancePlugin @Inject constructor(
) {
fun sendLogs() {
- val recipient = preferences.get(StringKey.MaintenanceEmail)
val amount = preferences.get(IntKey.MaintenanceLogsAmount)
val logs = getLogFiles(amount)
val zipFile = fileListProvider.ensureTempDirExists()?.createFile("application/zip", constructName()) ?: return
aapsLogger.debug("zipFile: ${zipFile.name}")
val zip = zipLogs(zipFile, logs)
- val attachmentUri = zip.uri
- val emailIntent: Intent = this.sendMail(attachmentUri, recipient, "Log Export")
- aapsLogger.debug("sending emailIntent")
- context.startActivity(emailIntent)
+
+ // Check export destination preference (master switch or individual setting)
+ if ((exportOptionsDialog.isLogCloudEnabled()) &&
+ cloudStorageManager.isCloudStorageActive()) {
+ // Send to Cloud Drive
+ sendLogsToCloudDrive(zip)
+ } else {
+ // Send via email (default behavior)
+ val recipient = preferences.get(StringKey.MaintenanceEmail)
+ val attachmentUri = zip.uri
+ val emailIntent: Intent = this.sendMail(attachmentUri, recipient, "Log Export")
+ aapsLogger.debug("sending emailIntent")
+ context.startActivity(emailIntent)
+ }
}
fun deleteLogs(keep: Int) {
@@ -235,6 +253,79 @@ class MaintenancePlugin @Inject constructor(
return emailIntent
}
+ private fun sendLogsToCloudDrive(zipFile: DocumentFile) {
+ try {
+ aapsLogger.debug("Sending logs to cloud storage")
+
+ // Read zip file contents
+ val inputStream = context.contentResolver.openInputStream(zipFile.uri)
+ val bytes = inputStream?.use { it.readBytes() }
+
+ if (bytes != null) {
+ // Upload to cloud storage
+ CoroutineScope(Dispatchers.IO).launch {
+ try {
+ val provider = cloudStorageManager.getActiveProvider()
+ if (provider == null) {
+ aapsLogger.error("No active cloud provider")
+ fallbackToEmailLogs(zipFile)
+ return@launch
+ }
+
+ // First set selected folder, then try path upload
+ provider.getOrCreateFolderPath(CloudConstants.CLOUD_PATH_LOGS)?.let {
+ provider.setSelectedFolderId(it)
+ }
+
+ ToastUtils.longInfoToast(context, rh.gs(R.string.uploading_to_cloud))
+
+ var uploadedFileId = provider.uploadFileToPath(
+ zipFile.name ?: "logs.zip",
+ bytes,
+ "application/zip",
+ CloudConstants.CLOUD_PATH_LOGS
+ )
+ if (uploadedFileId == null) {
+ uploadedFileId = provider.uploadFile(zipFile.name ?: "logs.zip", bytes, "application/zip")
+ }
+
+ if (uploadedFileId != null) {
+ aapsLogger.debug("Logs successfully uploaded to cloud storage: $uploadedFileId")
+ ToastUtils.infoToast(context, rh.gs(R.string.logs_uploaded_to_cloud) + "\n" + rh.gs(R.string.cloud_directory_path, CloudConstants.CLOUD_PATH_LOGS))
+ } else {
+ aapsLogger.error("Failed to upload logs to cloud storage")
+ ToastUtils.errorToast(context, rh.gs(R.string.logs_upload_failed))
+
+ // Fallback to email
+ fallbackToEmailLogs(zipFile)
+ }
+ } catch (e: Exception) {
+ aapsLogger.error("Error uploading logs to cloud storage", e)
+ ToastUtils.errorToast(context, rh.gs(R.string.logs_upload_error))
+
+ // Fallback to email
+ fallbackToEmailLogs(zipFile)
+ }
+ }
+ } else {
+ aapsLogger.error("Failed to read zip file contents")
+ fallbackToEmailLogs(zipFile)
+ }
+ } catch (e: Exception) {
+ aapsLogger.error("Error preparing logs for cloud upload", e)
+ fallbackToEmailLogs(zipFile)
+ }
+ }
+
+ private fun fallbackToEmailLogs(zipFile: DocumentFile) {
+ aapsLogger.debug("Falling back to email for log sending")
+ val recipient = preferences.get(StringKey.MaintenanceEmail)
+ val attachmentUri = zipFile.uri
+ val emailIntent: Intent = this.sendMail(attachmentUri, recipient, "Log Export")
+ aapsLogger.debug("sending emailIntent")
+ context.startActivity(emailIntent)
+ }
+
fun selectAapsDirectory(activity: DaggerAppCompatActivityWithResult) {
try {
uel.log(Action.SELECT_DIRECTORY, Sources.Maintenance)
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/activities/CloudPrefImportListActivity.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/activities/CloudPrefImportListActivity.kt
new file mode 100644
index 00000000000..8053d936c09
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/activities/CloudPrefImportListActivity.kt
@@ -0,0 +1,210 @@
+package app.aaps.plugins.configuration.maintenance.activities
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import app.aaps.core.interfaces.maintenance.FileListProvider
+import app.aaps.core.interfaces.maintenance.ImportExportPrefs
+import app.aaps.core.interfaces.maintenance.PrefsFile
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.core.ui.activities.TranslatedDaggerAppCompatActivity
+import app.aaps.plugins.configuration.R
+import app.aaps.plugins.configuration.databinding.MaintenanceImportListActivityBinding
+import app.aaps.plugins.configuration.databinding.MaintenanceImportListItemBinding
+import app.aaps.plugins.configuration.maintenance.PrefsMetadataKeyImpl
+import app.aaps.plugins.configuration.maintenance.data.PrefsStatusImpl
+import app.aaps.plugins.configuration.maintenance.ImportExportPrefsImpl
+import app.aaps.plugins.configuration.maintenance.cloud.CloudConstants
+import app.aaps.plugins.configuration.maintenance.cloud.CloudStorageManager
+import app.aaps.plugins.configuration.maintenance.formats.EncryptedPrefsFormat
+import javax.inject.Inject
+import androidx.lifecycle.lifecycleScope
+import kotlinx.coroutines.launch
+
+class CloudPrefImportListActivity : TranslatedDaggerAppCompatActivity() {
+
+ @Inject lateinit var rh: ResourceHelper
+ @Inject lateinit var fileListProvider: FileListProvider
+ @Inject lateinit var importExportPrefs: ImportExportPrefs
+ @Inject lateinit var cloudStorageManager: CloudStorageManager
+ @Inject lateinit var encryptedPrefsFormat: EncryptedPrefsFormat
+
+ private lateinit var binding: MaintenanceImportListActivityBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = MaintenanceImportListActivityBinding.inflate(layoutInflater)
+ val view = binding.root
+ setContentView(view)
+
+ title = rh.gs(R.string.import_from_cloud)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.setDisplayShowHomeEnabled(true)
+ supportActionBar?.setDisplayShowTitleEnabled(true)
+
+ binding.recyclerview.layoutManager = LinearLayoutManager(this)
+
+ // Use cloud file list
+ val cloudFiles = ImportExportPrefsImpl.cloudPrefsFiles.toMutableList()
+ val adapter = RecyclerViewAdapter(cloudFiles)
+ binding.recyclerview.adapter = adapter
+
+ // Update file count display
+ updateFileCountDisplay(cloudFiles.size)
+
+ // Show or hide "Load More" and update button text
+ updateLoadMoreButton(cloudFiles.size)
+ binding.loadMore.setOnClickListener {
+ // Click load more: fetch PAGE_SIZE more
+ binding.loadMore.isEnabled = false
+ binding.loadMore.text = rh.gs(R.string.loading)
+ lifecycleScope.launch {
+ val nextToken = ImportExportPrefsImpl.cloudNextPageToken
+ if (nextToken == null) {
+ binding.loadMore.visibility = View.GONE
+ return@launch
+ }
+
+ // Get active cloud provider
+ val provider = cloudStorageManager.getActiveProvider()
+ if (provider == null) {
+ binding.loadMore.visibility = View.GONE
+ return@launch
+ }
+
+ val currentLoadedCount = cloudFiles.size // Already loaded count
+ val page = provider.listSettingsFiles(CloudConstants.DEFAULT_PAGE_SIZE, nextToken)
+ ImportExportPrefsImpl.cloudNextPageToken = page.nextPageToken
+ // Download and parse each entry then append
+ val appended = mutableListOf()
+ val namePattern = Regex("^\\d{4}-\\d{2}-\\d{2}_\\d{6}.*\\.json$", RegexOption.IGNORE_CASE)
+ val filesToProcess = page.files.filter { namePattern.containsMatchIn(it.name) }
+ var processedCount = 0
+
+ for (f in filesToProcess) {
+ try {
+ // Update progress on button - add current loaded count
+ processedCount++
+ val currentItemNumber = currentLoadedCount + processedCount
+ val totalItemsInThisBatch = currentLoadedCount + filesToProcess.size
+ runOnUiThread {
+ binding.loadMore.text = rh.gs(R.string.loading_progress, currentItemNumber, totalItemsInThisBatch)
+ }
+
+ val bytes = provider.downloadFile(f.id)
+ if (bytes != null) {
+ val content = String(bytes, Charsets.UTF_8)
+ val metadata = encryptedPrefsFormat.loadMetadata(content)
+ appended.add(PrefsFile(f.name, content, metadata))
+ }
+ } catch (_: Exception) {
+ // Ignore single entry error
+ }
+ }
+ val start = cloudFiles.size
+ cloudFiles.addAll(appended)
+ adapter.notifyItemRangeInserted(start, appended.size)
+ binding.loadMore.isEnabled = true
+ updateLoadMoreButton(cloudFiles.size)
+ updateFileCountDisplay(cloudFiles.size)
+ }
+ }
+ }
+
+ private fun updateLoadMoreButton(currentCount: Int) {
+ if (ImportExportPrefsImpl.cloudNextPageToken == null) {
+ binding.loadMore.visibility = View.GONE
+ } else {
+ binding.loadMore.visibility = View.VISIBLE
+ // Calculate remaining files to load
+ val totalCount = ImportExportPrefsImpl.cloudTotalFilesCount
+ val remainingCount = if (totalCount > 0) {
+ minOf(CloudConstants.DEFAULT_PAGE_SIZE, totalCount - currentCount)
+ } else {
+ CloudConstants.DEFAULT_PAGE_SIZE
+ }
+ binding.loadMore.text = rh.gs(R.string.load_more_with_count, remainingCount, currentCount)
+ }
+ }
+
+ private fun updateFileCountDisplay(currentCount: Int) {
+ val totalCount = ImportExportPrefsImpl.cloudTotalFilesCount
+ if (totalCount > 0) {
+ binding.fileCount.visibility = View.VISIBLE
+ if (currentCount >= totalCount || ImportExportPrefsImpl.cloudNextPageToken == null) {
+ // All files loaded
+ binding.fileCount.text = rh.gs(R.string.cloud_import_file_count_all, currentCount)
+ } else {
+ // Partial files loaded
+ binding.fileCount.text = rh.gs(R.string.cloud_import_file_count, currentCount, totalCount)
+ }
+ } else {
+ binding.fileCount.visibility = View.GONE
+ }
+ }
+
+ inner class RecyclerViewAdapter internal constructor(private var prefFileList: MutableList) : RecyclerView.Adapter() {
+
+ inner class PrefFileViewHolder(val maintenanceImportListItemBinding: MaintenanceImportListItemBinding) : RecyclerView.ViewHolder(maintenanceImportListItemBinding.root) {
+
+ init {
+ with(maintenanceImportListItemBinding) {
+ root.isClickable = true
+ maintenanceImportListItemBinding.root.setOnClickListener {
+ val i = Intent()
+ // Set selected file
+ importExportPrefs.selectedImportFile = prefFileList[filelistName.tag as Int]
+ setResult(RESULT_OK, i)
+ finish()
+ }
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PrefFileViewHolder {
+ val binding = MaintenanceImportListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return PrefFileViewHolder(binding)
+ }
+
+ override fun getItemCount(): Int = prefFileList.size
+
+ override fun onBindViewHolder(holder: PrefFileViewHolder, position: Int) {
+ val prefFile = prefFileList[position]
+ with(holder.maintenanceImportListItemBinding) {
+ filelistName.text = prefFile.name
+ filelistName.tag = position
+
+ metalineName.visibility = View.VISIBLE
+ metaDateTimeIcon.visibility = View.VISIBLE
+ metaAppVersion.visibility = View.VISIBLE
+
+ prefFile.metadata[PrefsMetadataKeyImpl.AAPS_FLAVOUR]?.let {
+ metaVariantFormat.text = it.value
+ val colorAttr = if (it.status == PrefsStatusImpl.OK) app.aaps.core.ui.R.attr.metadataTextOkColor else app.aaps.core.ui.R.attr.metadataTextWarningColor
+ metaVariantFormat.setTextColor(rh.gac(metaVariantFormat.context, colorAttr))
+ }
+
+ prefFile.metadata[PrefsMetadataKeyImpl.CREATED_AT]?.let {
+ metaDateTime.text = fileListProvider.formatExportedAgo(it.value)
+ }
+
+ prefFile.metadata[PrefsMetadataKeyImpl.AAPS_VERSION]?.let {
+ metaAppVersion.text = it.value
+ val colorAttr = if (it.status == PrefsStatusImpl.OK) app.aaps.core.ui.R.attr.metadataTextOkColor else app.aaps.core.ui.R.attr.metadataTextWarningColor
+ metaAppVersion.setTextColor(rh.gac(metaVariantFormat.context, colorAttr))
+ }
+
+ prefFile.metadata[PrefsMetadataKeyImpl.DEVICE_NAME]?.let {
+ metaDeviceName.text = it.value
+ }
+
+ }
+ }
+
+ }
+
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudConstants.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudConstants.kt
new file mode 100644
index 00000000000..831735df062
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudConstants.kt
@@ -0,0 +1,66 @@
+package app.aaps.plugins.configuration.maintenance.cloud
+
+/**
+ * Centralized management of cloud-related constants.
+ *
+ * This object contains constants that are shared across all cloud storage providers.
+ */
+object CloudConstants {
+ // Log prefix for cloud-related logs
+ const val LOG_PREFIX = "[Cloud]"
+
+ // Cloud storage paths - these are logical paths that providers should map to their structure
+ const val CLOUD_PATH_EXPORT = "/AAPS/export"
+ const val CLOUD_PATH_SETTINGS = "${CLOUD_PATH_EXPORT}/preferences"
+ const val CLOUD_PATH_LOGS = "${CLOUD_PATH_EXPORT}/logs"
+ const val CLOUD_PATH_USER_ENTRIES = "${CLOUD_PATH_EXPORT}/user_entries"
+
+ // Activity request codes
+ const val CLOUD_IMPORT_REQUEST_CODE = 1001
+
+ // SharedPreferences keys (provider-agnostic)
+ // Use the same key as GoogleDriveManager for backward compatibility
+ const val PREF_CLOUD_STORAGE_TYPE = "google_drive_storage_type"
+
+ // Default page size for file listing
+ const val DEFAULT_PAGE_SIZE = 5
+}
+
+/**
+ * Storage type constants.
+ * Each cloud provider should have a unique type identifier.
+ */
+object StorageTypes {
+ const val LOCAL = "local"
+ const val GOOGLE_DRIVE = "google_drive"
+
+ // Future cloud storage providers:
+ // const val DROPBOX = "dropbox"
+ // const val ONEDRIVE = "onedrive"
+ // const val AZURE_BLOB = "azure_blob"
+ // const val AWS_S3 = "aws_s3"
+
+ /**
+ * Get all available storage types
+ */
+ val ALL_TYPES = listOf(LOCAL, GOOGLE_DRIVE)
+
+ /**
+ * Get all cloud storage types (excluding local)
+ */
+ val CLOUD_TYPES = listOf(GOOGLE_DRIVE)
+
+ /**
+ * Check if the given storage type is a cloud storage type
+ */
+ fun isCloudStorage(storageType: String): Boolean {
+ return storageType in CLOUD_TYPES
+ }
+
+ /**
+ * Check if the given storage type is valid
+ */
+ fun isValidStorageType(storageType: String): Boolean {
+ return storageType in ALL_TYPES
+ }
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudDirectoryDialog.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudDirectoryDialog.kt
new file mode 100644
index 00000000000..5d3b7b29ccf
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudDirectoryDialog.kt
@@ -0,0 +1,375 @@
+package app.aaps.plugins.configuration.maintenance.cloud
+
+import android.content.Intent
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.RadioButton
+import android.widget.TextView
+import app.aaps.plugins.configuration.activities.DaggerAppCompatActivityWithResult
+import androidx.lifecycle.lifecycleScope
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.core.ui.toast.ToastUtils
+import app.aaps.plugins.configuration.R
+import app.aaps.plugins.configuration.maintenance.MaintenancePlugin
+import app.aaps.plugins.configuration.activities.SingleFragmentActivity
+import app.aaps.core.interfaces.plugin.ActivePlugin
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+import javax.inject.Singleton
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import app.aaps.core.ui.dialogs.AlertDialogHelper
+import androidx.browser.customtabs.CustomTabsIntent
+import androidx.core.net.toUri
+
+/**
+ * Dialog for selecting cloud directory.
+ *
+ * This dialog is provider-agnostic and can be extended to support multiple cloud storage providers
+ * in the future (e.g., Dropbox, OneDrive, etc.)
+ */
+@Singleton
+class CloudDirectoryDialog @Inject constructor(
+ private val aapsLogger: AAPSLogger,
+ private val rh: ResourceHelper,
+ private val cloudStorageManager: CloudStorageManager,
+ private val maintenancePlugin: MaintenancePlugin,
+ private val activePlugin: ActivePlugin,
+ private val exportOptionsDialog: ExportOptionsDialog
+) {
+
+ companion object {
+ private const val LOG_PREFIX = CloudConstants.LOG_PREFIX
+ }
+
+ /**
+ * Show cloud directory dialog
+ */
+ fun showCloudDirectoryDialog(
+ activity: DaggerAppCompatActivityWithResult,
+ onLocalSelected: () -> Unit = { maintenancePlugin.selectAapsDirectory(activity) },
+ onCloudSelected: () -> Unit = {},
+ onStorageChanged: () -> Unit = {}
+ ) {
+ val dialogView = activity.layoutInflater.inflate(R.layout.dialog_cloud_directory, null)
+
+ // UI elements
+ val googleDriveRow = dialogView.findViewById(R.id.google_drive_row)
+ val googleDriveRadio = dialogView.findViewById(R.id.google_drive_radio)
+ val clearAction = dialogView.findViewById(R.id.clear_action)
+
+ // Authorization status section UI elements
+ val authStatusSection = dialogView.findViewById(R.id.authorization_status_section)
+ val authStatusText = dialogView.findViewById(R.id.authorization_status_text)
+ val authCheckIcon = dialogView.findViewById(R.id.authorization_check_icon)
+ val cloudPathText = dialogView.findViewById(R.id.cloud_path_text)
+
+ val currentType = cloudStorageManager.getActiveStorageType()
+ val isCloudSelected = currentType == StorageTypes.GOOGLE_DRIVE
+
+ // Initial state: set radio button based on current settings
+ googleDriveRadio.isChecked = isCloudSelected
+
+ // Update authorization status section
+ updateAuthorizationStatusSection(
+ activity,
+ authStatusSection,
+ authStatusText,
+ authCheckIcon,
+ cloudPathText
+ )
+
+ // Use MaterialAlertDialogBuilder with DialogTheme to match project style
+ // Title is now in the layout itself, so we don't use setCustomTitle
+ val dialog = MaterialAlertDialogBuilder(activity, app.aaps.core.ui.R.style.DialogTheme)
+ .setView(dialogView)
+ .setNegativeButton(rh.gs(app.aaps.core.ui.R.string.cancel), null)
+ .create()
+
+ // Top-right clear: equivalent to the original local storage clear action
+ clearAction.setOnClickListener {
+ val wasCloud = cloudStorageManager.isCloudStorageActive()
+ val proceedClear: () -> Unit = {
+ cloudStorageManager.clearAllCredentials()
+ cloudStorageManager.setActiveStorageType(StorageTypes.LOCAL)
+ cloudStorageManager.clearConnectionError()
+ // Reset export destination settings to local/email mode
+ exportOptionsDialog.resetToLocalSettings()
+ onLocalSelected()
+ onStorageChanged()
+ ToastUtils.infoToast(activity, rh.gs(app.aaps.core.ui.R.string.success))
+ // Reflect selection state on UI
+ googleDriveRadio.isChecked = false
+ dialog.dismiss()
+ }
+ if (wasCloud) {
+ MaterialAlertDialogBuilder(activity, app.aaps.core.ui.R.style.DialogTheme)
+ .setCustomTitle(AlertDialogHelper.buildCustomTitle(activity, rh.gs(R.string.clear_cloud_settings)))
+ .setMessage(rh.gs(R.string.clear_cloud_settings_message))
+ .setPositiveButton(rh.gs(app.aaps.core.ui.R.string.yes)) { _, _ -> proceedClear() }
+ .setNegativeButton(rh.gs(app.aaps.core.ui.R.string.no), null)
+ .show()
+ } else {
+ proceedClear()
+ }
+ }
+
+ // Google Drive row click
+ val handleGoogleDriveClick = {
+ googleDriveRadio.isChecked = true
+ dialog.dismiss()
+ handleCloudSelection(activity, StorageTypes.GOOGLE_DRIVE, onCloudSelected, onStorageChanged)
+ }
+ googleDriveRow.setOnClickListener { handleGoogleDriveClick() }
+ googleDriveRadio.setOnClickListener { handleGoogleDriveClick() }
+
+ dialog.show()
+ }
+
+ /** Handle cloud storage selection */
+ private fun handleCloudSelection(
+ activity: DaggerAppCompatActivityWithResult,
+ storageType: String,
+ onSuccess: () -> Unit,
+ onStorageChanged: () -> Unit
+ ) {
+ activity.lifecycleScope.launch {
+ try {
+ val provider = cloudStorageManager.getProvider(storageType)
+ if (provider == null) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX No provider available for $storageType")
+ ToastUtils.errorToast(activity, "Cloud provider not available")
+ return@launch
+ }
+
+ if (provider.hasValidCredentials()) {
+ if (provider.testConnection()) {
+ cloudStorageManager.setActiveStorageType(storageType)
+ // Automatically point to fixed settings directory
+ val folderId = provider.getOrCreateFolderPath(CloudConstants.CLOUD_PATH_SETTINGS)
+ if (!folderId.isNullOrEmpty()) provider.setSelectedFolderId(folderId)
+ onSuccess()
+ onStorageChanged()
+ } else {
+ showReauthorizeDialog(activity, storageType, onSuccess, onStorageChanged)
+ }
+ } else {
+ startAuthFlow(activity, storageType, onSuccess, onStorageChanged)
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error handling cloud selection", e)
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_auth_error, e.message ?: ""))
+ }
+ }
+ }
+
+ /**
+ * Show dialog asking if user wants to enable cloud export after successful connection
+ */
+ private fun showEnableCloudExportDialog(
+ activity: DaggerAppCompatActivityWithResult,
+ onStorageChanged: () -> Unit
+ ) {
+ activity.runOnUiThread {
+ MaterialAlertDialogBuilder(activity, app.aaps.core.ui.R.style.DialogTheme)
+ .setCustomTitle(AlertDialogHelper.buildCustomTitle(activity, rh.gs(R.string.enable_cloud_export_title)))
+ .setMessage(rh.gs(R.string.enable_cloud_export_message))
+ .setPositiveButton(rh.gs(app.aaps.core.ui.R.string.yes)) { _, _ ->
+ exportOptionsDialog.enableAllCloud()
+ onStorageChanged()
+ ToastUtils.longInfoToast(activity, rh.gs(R.string.can_change_in_export_settings))
+ }
+ .setNegativeButton(rh.gs(app.aaps.core.ui.R.string.no)) { _, _ ->
+ // Still enable local storage even when user declines cloud export
+ exportOptionsDialog.enableLocalStorage()
+ ToastUtils.longInfoToast(activity, rh.gs(R.string.can_change_in_export_settings))
+ }
+ .show()
+ }
+ }
+
+ /** Start auth flow for cloud provider */
+ private suspend fun startAuthFlow(
+ activity: DaggerAppCompatActivityWithResult,
+ storageType: String,
+ onSuccess: () -> Unit,
+ onStorageChanged: () -> Unit
+ ) {
+ try {
+ val provider = cloudStorageManager.getProvider(storageType) ?: return
+
+ // Start OAuth/PKCE auth flow (provider-agnostic)
+ val authUrl = provider.startAuth()
+ if (authUrl == null) {
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_auth_start_failed))
+ return
+ }
+ val customTabsIntent = CustomTabsIntent.Builder()
+ .setShowTitle(true)
+ .build()
+ customTabsIntent.launchUrl(activity, authUrl.toUri())
+ showWaitingDialog(activity, provider.displayName) { cancelled ->
+ if (cancelled) {
+ ToastUtils.infoToast(activity, rh.gs(R.string.cloud_auth_cancelled))
+ } else {
+ activity.lifecycleScope.launch {
+ val authCode = provider.waitForAuthCode(60000)
+ if (authCode != null) {
+ if (provider.completeAuth(authCode)) {
+ cloudStorageManager.setActiveStorageType(storageType)
+ ToastUtils.infoToast(activity, rh.gs(R.string.cloud_auth_success))
+ // Explicitly open maintenance page to prevent main page from stealing focus
+ openMaintenanceScreen(activity)
+ onSuccess()
+ onStorageChanged()
+ // Automatically point to fixed settings directory and skip selection
+ val folderId = provider.getOrCreateFolderPath(CloudConstants.CLOUD_PATH_SETTINGS)
+ if (!folderId.isNullOrEmpty()) provider.setSelectedFolderId(folderId)
+ // Ask user if they want to enable cloud export
+ showEnableCloudExportDialog(activity, onStorageChanged)
+ } else {
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_auth_failed))
+ }
+ } else {
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_auth_timeout))
+ }
+ }
+ }
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error starting auth flow", e)
+ ToastUtils.errorToast(activity, rh.gs(R.string.cloud_auth_error, e.message))
+ }
+ }
+
+ /**
+ * Explicitly open SingleFragmentActivity containing MaintenanceFragment, with a delayed
+ * secondary attempt to prevent the browser closing/system returning to the previous app
+ * from stealing focus back to MainActivity.
+ */
+ private fun openMaintenanceScreen(activity: DaggerAppCompatActivityWithResult) {
+ try {
+ val list = activePlugin.getPluginsList()
+ val idx = list.indexOfFirst { it is MaintenancePlugin }
+ if (idx >= 0) {
+ val intent = Intent(activity, SingleFragmentActivity::class.java)
+ .setAction("CloudDirectoryDialog")
+ .putExtra("plugin", idx)
+ .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NO_ANIMATION)
+ activity.startActivity(intent)
+ // Delay again to counteract possible late system foreground actions
+ activity.window?.decorView?.postDelayed({
+ try { activity.startActivity(intent) } catch (_: Exception) { }
+ }, 1200)
+ } else {
+ // Fallback: if index not found, still try to bring current Activity to foreground
+ bringAppToForeground(activity)
+ }
+ } catch (_: Exception) { }
+ }
+
+ // Fallback method: bring app to foreground (using launch Intent, with double REORDER_TO_FRONT to stabilize focus)
+ private fun bringAppToForeground(activity: DaggerAppCompatActivityWithResult) {
+ try {
+ val launchIntent = activity.packageManager.getLaunchIntentForPackage(activity.packageName)?.apply {
+ addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NO_ANIMATION)
+ }
+ if (launchIntent != null) {
+ activity.startActivity(launchIntent)
+ activity.window?.decorView?.postDelayed({
+ try { activity.startActivity(launchIntent) } catch (_: Exception) { }
+ }, 800)
+ }
+ } catch (_: Exception) { }
+ }
+
+ /** Waiting dialog for authorization */
+ private fun showWaitingDialog(
+ activity: DaggerAppCompatActivityWithResult,
+ providerName: String,
+ onResult: (cancelled: Boolean) -> Unit
+ ) {
+ val dialog = MaterialAlertDialogBuilder(activity, app.aaps.core.ui.R.style.DialogTheme)
+ .setCustomTitle(AlertDialogHelper.buildCustomTitle(
+ activity,
+ rh.gs(R.string.cloud_authorization_title, providerName)
+ ))
+ .setMessage(rh.gs(R.string.cloud_authorization_message, providerName))
+ .setNegativeButton(rh.gs(app.aaps.core.ui.R.string.cancel)) { _, _ ->
+ onResult(true)
+ }
+ .setCancelable(false)
+ .create()
+
+ dialog.show()
+
+ // Immediately signal waiting started (dialog stays until flow finishes externally)
+ onResult(false)
+ dialog.dismiss()
+ }
+
+ /** Reauthorize dialog */
+ private fun showReauthorizeDialog(
+ activity: DaggerAppCompatActivityWithResult,
+ storageType: String,
+ onSuccess: () -> Unit,
+ onStorageChanged: () -> Unit
+ ) {
+ MaterialAlertDialogBuilder(activity, app.aaps.core.ui.R.style.DialogTheme)
+ .setCustomTitle(AlertDialogHelper.buildCustomTitle(
+ activity,
+ rh.gs(R.string.cloud_connection_failed)
+ ))
+ .setMessage(rh.gs(R.string.cloud_reauthorize_message))
+ .setPositiveButton(rh.gs(R.string.reauthorize)) { _, _ ->
+ cloudStorageManager.clearAllCredentials()
+ activity.lifecycleScope.launch {
+ startAuthFlow(activity, storageType, onSuccess, onStorageChanged)
+ }
+ }
+ .setNegativeButton(rh.gs(app.aaps.core.ui.R.string.cancel), null)
+ .show()
+ }
+
+ /**
+ * Update authorization status section based on current cloud storage state
+ */
+ private fun updateAuthorizationStatusSection(
+ activity: DaggerAppCompatActivityWithResult,
+ authStatusSection: LinearLayout,
+ authStatusText: TextView,
+ authCheckIcon: ImageView,
+ cloudPathText: TextView
+ ) {
+ val provider = cloudStorageManager.getProvider(StorageTypes.GOOGLE_DRIVE)
+ val hasCredentials = provider?.hasValidCredentials() == true
+ val hasConnectionError = cloudStorageManager.hasConnectionError()
+
+ if (hasCredentials) {
+ // Show authorization status section
+ authStatusSection.visibility = View.VISIBLE
+
+ if (hasConnectionError) {
+ // Need re-authorization - use provider's resource ID
+ authStatusText.text = rh.gs(provider.reAuthRequiredTextResId)
+ authStatusText.setTextColor(activity.getColor(R.color.cloud_status_warning))
+ authCheckIcon.setImageResource(R.drawable.ic_error)
+ authCheckIcon.setColorFilter(activity.getColor(R.color.cloud_status_warning))
+ } else {
+ // Authorized successfully - use provider's resource ID
+ authStatusText.text = rh.gs(provider.authorizedTextResId)
+ authStatusText.setTextColor(activity.getColor(R.color.cloud_status_success))
+ authCheckIcon.setImageResource(R.drawable.ic_meta_ok)
+ authCheckIcon.setColorFilter(activity.getColor(R.color.cloud_status_success))
+ }
+
+ // Set cloud path
+ cloudPathText.text = CloudConstants.CLOUD_PATH_EXPORT
+ } else {
+ // Hide authorization status section if no credentials
+ authStatusSection.visibility = View.GONE
+ }
+ }
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudModels.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudModels.kt
new file mode 100644
index 00000000000..318f882c249
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudModels.kt
@@ -0,0 +1,58 @@
+package app.aaps.plugins.configuration.maintenance.cloud
+
+/**
+ * Represents a file in cloud storage.
+ * This is a provider-agnostic data class that can be used across different cloud services.
+ */
+data class CloudFile(
+ /**
+ * Unique identifier for this file in the cloud storage
+ */
+ val id: String,
+
+ /**
+ * File name
+ */
+ val name: String,
+
+ /**
+ * MIME type of the file
+ */
+ val mimeType: String
+)
+
+/**
+ * Represents a folder in cloud storage.
+ * This is a provider-agnostic data class that can be used across different cloud services.
+ */
+data class CloudFolder(
+ /**
+ * Unique identifier for this folder in the cloud storage
+ */
+ val id: String,
+
+ /**
+ * Folder name
+ */
+ val name: String
+)
+
+/**
+ * Result of a file listing operation with pagination support.
+ */
+data class CloudFileListResult(
+ /**
+ * List of files returned in this page
+ */
+ val files: List,
+
+ /**
+ * Token for fetching the next page, null if this is the last page
+ */
+ val nextPageToken: String? = null,
+
+ /**
+ * Total number of files (if known), -1 if unknown
+ */
+ val totalCount: Int = -1
+)
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudStorageManager.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudStorageManager.kt
new file mode 100644
index 00000000000..37f8d4ac6ee
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudStorageManager.kt
@@ -0,0 +1,183 @@
+package app.aaps.plugins.configuration.maintenance.cloud
+
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
+import app.aaps.core.interfaces.sharedPreferences.SP
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Cloud Storage Manager - Factory class for managing cloud storage providers.
+ *
+ * This class provides a unified interface for accessing cloud storage providers.
+ * It manages provider registration, selection, and lifecycle.
+ *
+ * The providers are automatically registered via Dagger multi-binding.
+ * To add a new cloud provider:
+ * 1. Create a class that implements CloudStorageProvider
+ * 2. Add a @Binds @IntoSet binding in CloudStorageModule
+ * 3. Add the storage type to StorageTypes
+ *
+ * Usage:
+ * ```
+ * // Get the active provider (based on user settings)
+ * val provider = cloudStorageManager.getActiveProvider()
+ *
+ * // Get a specific provider by type
+ * val googleDrive = cloudStorageManager.getProvider(StorageTypes.GOOGLE_DRIVE)
+ *
+ * // List all available providers
+ * val providers = cloudStorageManager.getAvailableProviders()
+ * ```
+ */
+@Singleton
+class CloudStorageManager @Inject constructor(
+ private val aapsLogger: AAPSLogger,
+ private val sp: SP,
+ /**
+ * Set of all cloud storage providers, injected via Dagger multi-binding.
+ * This allows adding new providers without modifying this class.
+ */
+ cloudStorageProviders: Set<@JvmSuppressWildcards CloudStorageProvider>
+) {
+
+ companion object {
+ private const val LOG_PREFIX = "[CloudStorageManager]"
+ }
+
+ /**
+ * Map of storage type to provider instance
+ */
+ private val providers: Map
+
+ init {
+ // Build provider map from the injected set
+ providers = cloudStorageProviders.associateBy { it.storageType }
+
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX Initialized with ${providers.size} provider(s): ${providers.keys.joinToString()}")
+ }
+
+ /**
+ * Get the currently active provider based on user settings.
+ * @return The active CloudStorageProvider, or null if local storage is selected
+ */
+ fun getActiveProvider(): CloudStorageProvider? {
+ val activeType = sp.getString(CloudConstants.PREF_CLOUD_STORAGE_TYPE, StorageTypes.LOCAL)
+
+ if (activeType == StorageTypes.LOCAL) {
+ return null
+ }
+
+ return providers[activeType]
+ }
+
+ /**
+ * Get a specific provider by its storage type.
+ * @param storageType The storage type identifier (e.g., "google_drive")
+ * @return The provider, or null if not found
+ */
+ fun getProvider(storageType: String): CloudStorageProvider? {
+ return providers[storageType]
+ }
+
+ /**
+ * Get all available cloud storage providers.
+ * @return List of all registered providers
+ */
+ fun getAvailableProviders(): List {
+ return providers.values.toList()
+ }
+
+ /**
+ * Get all cloud storage types that have valid credentials.
+ * @return List of storage types with valid credentials
+ */
+ fun getAuthenticatedProviders(): List {
+ return providers.values.filter { it.hasValidCredentials() }
+ }
+
+ /**
+ * Check if any cloud provider has valid credentials.
+ * @return true if at least one provider is authenticated
+ */
+ fun hasAnyCloudCredentials(): Boolean {
+ return providers.values.any { it.hasValidCredentials() }
+ }
+
+ /**
+ * Get the currently selected storage type.
+ * @return The storage type identifier
+ */
+ fun getActiveStorageType(): String {
+ return sp.getString(CloudConstants.PREF_CLOUD_STORAGE_TYPE, StorageTypes.LOCAL)
+ }
+
+ /**
+ * Set the active storage type.
+ * @param storageType The storage type to set
+ */
+ fun setActiveStorageType(storageType: String) {
+ if (StorageTypes.isValidStorageType(storageType)) {
+ sp.putString(CloudConstants.PREF_CLOUD_STORAGE_TYPE, storageType)
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX Active storage type set to: $storageType")
+ } else {
+ aapsLogger.warn(LTag.CORE, "$LOG_PREFIX Invalid storage type: $storageType")
+ }
+ }
+
+ /**
+ * Check if cloud storage is currently active.
+ * @return true if the active storage type is a cloud type
+ */
+ fun isCloudStorageActive(): Boolean {
+ return StorageTypes.isCloudStorage(getActiveStorageType())
+ }
+
+ /**
+ * Check if the active provider has a connection error.
+ * @return true if there's a connection error
+ */
+ fun hasConnectionError(): Boolean {
+ return getActiveProvider()?.hasConnectionError() ?: false
+ }
+
+ /**
+ * Clear connection error on the active provider.
+ */
+ fun clearConnectionError() {
+ getActiveProvider()?.clearConnectionError()
+ }
+
+ /**
+ * Clear credentials for all providers.
+ * Use this for a complete sign-out from all cloud services.
+ */
+ fun clearAllCredentials() {
+ providers.values.forEach { provider ->
+ try {
+ provider.clearCredentials()
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX Cleared credentials for: ${provider.storageType}")
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error clearing credentials for ${provider.storageType}", e)
+ }
+ }
+ }
+
+ /**
+ * Get the display name for a storage type.
+ * @param storageType The storage type
+ * @return Human-readable display name
+ */
+ fun getDisplayName(storageType: String): String {
+ return providers[storageType]?.displayName ?: storageType
+ }
+
+ /**
+ * Get the icon resource ID for a storage type.
+ * @param storageType The storage type
+ * @return Drawable resource ID, or 0 if not found
+ */
+ fun getIconResId(storageType: String): Int {
+ return providers[storageType]?.iconResId ?: 0
+ }
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudStorageProvider.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudStorageProvider.kt
new file mode 100644
index 00000000000..2e218dac0f4
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/CloudStorageProvider.kt
@@ -0,0 +1,193 @@
+package app.aaps.plugins.configuration.maintenance.cloud
+
+/**
+ * Abstract interface for cloud storage providers.
+ *
+ * This interface defines the contract that all cloud storage providers must implement,
+ * enabling easy extension to support additional cloud services like Dropbox, Azure, OneDrive, etc.
+ *
+ * Usage:
+ * - Implement this interface for each cloud storage provider
+ * - Register the implementation in CloudStorageManager
+ * - The application code uses CloudStorageManager to interact with the active provider
+ */
+interface CloudStorageProvider {
+
+ /**
+ * Unique identifier for this storage type (e.g., "google_drive", "dropbox", "azure_blob")
+ */
+ val storageType: String
+
+ /**
+ * Human-readable display name for this provider
+ */
+ val displayName: String
+
+ /**
+ * Drawable resource ID for the provider's icon
+ */
+ val iconResId: Int
+
+ /**
+ * String resource ID for "authorized" status text (e.g., "Google Drive Authorized")
+ */
+ val authorizedTextResId: Int
+
+ /**
+ * String resource ID for "re-authorization required" status text
+ */
+ val reAuthRequiredTextResId: Int
+
+ // ==================== Authentication ====================
+
+ /**
+ * Start the authentication flow.
+ * @return The authorization URL to open in browser, or null if auth is not needed
+ */
+ suspend fun startAuth(): String?
+
+ /**
+ * Complete the authentication flow with the received auth code.
+ * @param authCode The authorization code received from the OAuth callback
+ * @return true if authentication was successful
+ */
+ suspend fun completeAuth(authCode: String): Boolean
+
+ /**
+ * Check if there are valid stored credentials.
+ * @return true if valid credentials exist
+ */
+ fun hasValidCredentials(): Boolean
+
+ /**
+ * Clear all stored credentials and settings.
+ */
+ fun clearCredentials()
+
+ /**
+ * Get a valid access token, refreshing if necessary.
+ * @return Valid access token or null if unable to obtain one
+ */
+ suspend fun getValidAccessToken(): String?
+
+ // ==================== Connection ====================
+
+ /**
+ * Test the connection to the cloud service.
+ * @return true if connection is successful
+ */
+ suspend fun testConnection(): Boolean
+
+ /**
+ * Check if there's a connection error.
+ * @return true if there's an active connection error
+ */
+ fun hasConnectionError(): Boolean
+
+ /**
+ * Clear the connection error state.
+ */
+ fun clearConnectionError()
+
+ // ==================== Folder Operations ====================
+
+ /**
+ * Get or create a folder path in the cloud storage.
+ * @param path The folder path (e.g., "AAPS/export/settings")
+ * @return The folder ID or null if failed
+ */
+ suspend fun getOrCreateFolderPath(path: String): String?
+
+ /**
+ * Create a single folder.
+ * @param name Folder name
+ * @param parentId Parent folder ID (use "root" for root folder)
+ * @return The created folder ID or null if failed
+ */
+ suspend fun createFolder(name: String, parentId: String = "root"): String?
+
+ /**
+ * List folders in the specified parent folder.
+ * @param parentId Parent folder ID (use "root" for root folder)
+ * @return List of folders
+ */
+ suspend fun listFolders(parentId: String = "root"): List
+
+ // ==================== File Operations ====================
+
+ /**
+ * Upload a file to the specified path.
+ * @param fileName File name
+ * @param content File content as bytes
+ * @param mimeType MIME type of the file
+ * @param path Target folder path
+ * @return The uploaded file ID or null if failed
+ */
+ suspend fun uploadFileToPath(
+ fileName: String,
+ content: ByteArray,
+ mimeType: String,
+ path: String
+ ): String?
+
+ /**
+ * Upload a file to the currently selected folder.
+ * @param fileName File name
+ * @param content File content as bytes
+ * @param mimeType MIME type of the file
+ * @return The uploaded file ID or null if failed
+ */
+ suspend fun uploadFile(
+ fileName: String,
+ content: ByteArray,
+ mimeType: String
+ ): String?
+
+ /**
+ * Download a file by its ID.
+ * @param fileId The file ID
+ * @return File content as bytes or null if failed
+ */
+ suspend fun downloadFile(fileId: String): ByteArray?
+
+ /**
+ * List settings files (JSON files) in the selected folder.
+ * @param pageSize Maximum number of files to return
+ * @param pageToken Page token for pagination
+ * @return List of settings files
+ */
+ suspend fun listSettingsFiles(
+ pageSize: Int = 10,
+ pageToken: String? = null
+ ): CloudFileListResult
+
+ // ==================== Selected Folder ====================
+
+ /**
+ * Get the currently selected folder ID.
+ * @return The selected folder ID or empty string if none selected
+ */
+ fun getSelectedFolderId(): String
+
+ /**
+ * Set the selected folder ID.
+ * @param folderId The folder ID to select
+ */
+ fun setSelectedFolderId(folderId: String)
+
+ // ==================== OAuth Helpers ====================
+
+ /**
+ * Wait for OAuth authorization code (used during OAuth/PKCE auth flow).
+ * Providers that use browser-based auth should implement this.
+ * @param timeoutMs Maximum time to wait in milliseconds
+ * @return The authorization code, or null if timeout/cancelled
+ */
+ suspend fun waitForAuthCode(timeoutMs: Long = 60000): String? = null
+
+ /**
+ * Count the number of settings files in the selected folder.
+ * @return Number of settings files
+ */
+ suspend fun countSettingsFiles(): Int = 0
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/ExportOptionsDialog.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/ExportOptionsDialog.kt
new file mode 100644
index 00000000000..6be0ce5c8a1
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/ExportOptionsDialog.kt
@@ -0,0 +1,298 @@
+package app.aaps.plugins.configuration.maintenance.cloud
+
+import android.content.Context
+import android.widget.CheckBox
+import android.widget.Switch
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.FragmentActivity
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.core.interfaces.sharedPreferences.SP
+import app.aaps.core.ui.toast.ToastUtils
+import app.aaps.plugins.configuration.R
+import app.aaps.plugins.configuration.activities.DaggerAppCompatActivityWithResult
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ExportOptionsDialog @Inject constructor(
+ private val aapsLogger: AAPSLogger,
+ private val rh: ResourceHelper,
+ private val sp: SP,
+ private val cloudStorageManager: CloudStorageManager
+) {
+
+ companion object {
+ private const val LOG_PREFIX = CloudConstants.LOG_PREFIX
+
+ // SharedPreferences keys for export destination settings
+ const val PREF_ALL_CLOUD_ENABLED = "export_all_cloud_enabled"
+ const val PREF_LOG_EMAIL_ENABLED = "export_log_email_enabled"
+ const val PREF_LOG_CLOUD_ENABLED = "export_log_cloud_enabled"
+ const val PREF_SETTINGS_LOCAL_ENABLED = "export_settings_local_enabled"
+ const val PREF_SETTINGS_CLOUD_ENABLED = "export_settings_cloud_enabled"
+ const val PREF_CSV_LOCAL_ENABLED = "export_csv_local_enabled"
+ const val PREF_CSV_CLOUD_ENABLED = "export_csv_cloud_enabled"
+ }
+
+ /**
+ * Show export options configuration dialog
+ */
+ fun showExportOptionsDialog(
+ activity: DaggerAppCompatActivityWithResult,
+ onSettingsChanged: () -> Unit = {}
+ ) {
+ val dialogView = activity.layoutInflater.inflate(R.layout.dialog_export_options, null)
+
+ val allCloudSwitch = dialogView.findViewById(R.id.all_cloud_switch)
+ val logEmailSwitch = dialogView.findViewById(R.id.log_email_switch)
+ val logCloudSwitch = dialogView.findViewById(R.id.log_cloud_switch)
+ val settingsLocalCheckbox = dialogView.findViewById(R.id.settings_local_checkbox)
+ val settingsCloudCheckbox = dialogView.findViewById(R.id.settings_cloud_checkbox)
+ val csvLocalSwitch = dialogView.findViewById(R.id.csv_local_switch)
+ val csvCloudSwitch = dialogView.findViewById(R.id.csv_cloud_switch)
+
+ // Load current settings
+ allCloudSwitch.isChecked = sp.getBoolean(PREF_ALL_CLOUD_ENABLED, false)
+ logEmailSwitch.isChecked = sp.getBoolean(PREF_LOG_EMAIL_ENABLED, true) // Default to email
+ logCloudSwitch.isChecked = sp.getBoolean(PREF_LOG_CLOUD_ENABLED, false)
+ settingsLocalCheckbox.isChecked = sp.getBoolean(PREF_SETTINGS_LOCAL_ENABLED, true) // Default to local
+ settingsCloudCheckbox.isChecked = sp.getBoolean(PREF_SETTINGS_CLOUD_ENABLED, false)
+ csvLocalSwitch.isChecked = sp.getBoolean(PREF_CSV_LOCAL_ENABLED, true) // Default to local
+ csvCloudSwitch.isChecked = sp.getBoolean(PREF_CSV_CLOUD_ENABLED, false)
+
+ // Check if cloud directory is configured
+ val isCloudConfigured = cloudStorageManager.isCloudStorageActive()
+
+ // Disable cloud options if not configured
+ if (!isCloudConfigured) {
+ logCloudSwitch.isEnabled = false
+ settingsCloudCheckbox.isEnabled = false
+ csvCloudSwitch.isEnabled = false
+
+ // Force disable cloud options and enable local/email options
+ logCloudSwitch.isChecked = false
+ settingsCloudCheckbox.isChecked = false
+ csvCloudSwitch.isChecked = false
+
+ if (!logEmailSwitch.isChecked && !logCloudSwitch.isChecked) {
+ logEmailSwitch.isChecked = true
+ }
+ if (!settingsLocalCheckbox.isChecked && !settingsCloudCheckbox.isChecked) {
+ settingsLocalCheckbox.isChecked = true
+ }
+ if (!csvLocalSwitch.isChecked && !csvCloudSwitch.isChecked) {
+ csvLocalSwitch.isChecked = true
+ }
+ }
+
+ // Set up mutual exclusivity for log and csv rows (they still use switches)
+ setupMutualExclusivity(logEmailSwitch, logCloudSwitch)
+ setupMutualExclusivity(csvLocalSwitch, csvCloudSwitch)
+
+ // Set up at-least-one-selected logic for settings checkboxes
+ setupAtLeastOneSelected(settingsLocalCheckbox, settingsCloudCheckbox)
+
+ // Apply master All-Cloud behavior - shared logic for both initialization and user interaction
+ val applyAllCloudState: (Boolean) -> Unit = { enabled ->
+ if (enabled) {
+ // Require cloud for all rows, but preserve local settings checkbox state
+ logCloudSwitch.isChecked = true
+ settingsCloudCheckbox.isChecked = true
+ csvCloudSwitch.isChecked = true
+ logEmailSwitch.isChecked = false
+ // settingsLocalCheckbox - keep current state, don't force uncheck
+ csvLocalSwitch.isChecked = false
+
+ // Disable per-row toggles when master is on (except settings local which can be toggled)
+ logEmailSwitch.isEnabled = false
+ logCloudSwitch.isEnabled = false
+ // settingsLocalCheckbox stays enabled - user can choose to have both local+cloud
+ settingsCloudCheckbox.isEnabled = false
+ csvLocalSwitch.isEnabled = false
+ csvCloudSwitch.isEnabled = false
+ } else {
+ // Re-enable per-row toggles (cloud options depend on configuration)
+ // Don't reset values - just allow user to change them
+ logEmailSwitch.isEnabled = true
+ logCloudSwitch.isEnabled = isCloudConfigured
+ settingsLocalCheckbox.isEnabled = true
+ settingsCloudCheckbox.isEnabled = isCloudConfigured
+ csvLocalSwitch.isEnabled = true
+ csvCloudSwitch.isEnabled = isCloudConfigured
+ }
+ }
+
+ // Apply initial state based on saved preferences
+ if (allCloudSwitch.isChecked && isCloudConfigured) {
+ applyAllCloudState(true)
+ }
+
+ allCloudSwitch.setOnCheckedChangeListener { _, isChecked ->
+ // If cloud not configured, block enabling master switch
+ val cloudConfigured = cloudStorageManager.isCloudStorageActive()
+ if (isChecked && !cloudConfigured) {
+ ToastUtils.warnToast(activity, rh.gs(R.string.cloud_connection_failed))
+ allCloudSwitch.isChecked = false
+ return@setOnCheckedChangeListener
+ }
+ applyAllCloudState(isChecked)
+ }
+
+ val dialog = AlertDialog.Builder(activity)
+ .setTitle(rh.gs(R.string.export_options))
+ .setView(dialogView)
+ .setPositiveButton(rh.gs(app.aaps.core.ui.R.string.ok)) { _, _ ->
+ // Save settings
+ sp.putBoolean(PREF_ALL_CLOUD_ENABLED, allCloudSwitch.isChecked)
+ sp.putBoolean(PREF_LOG_EMAIL_ENABLED, logEmailSwitch.isChecked)
+ sp.putBoolean(PREF_LOG_CLOUD_ENABLED, logCloudSwitch.isChecked)
+ sp.putBoolean(PREF_SETTINGS_LOCAL_ENABLED, settingsLocalCheckbox.isChecked)
+ sp.putBoolean(PREF_SETTINGS_CLOUD_ENABLED, settingsCloudCheckbox.isChecked)
+ sp.putBoolean(PREF_CSV_LOCAL_ENABLED, csvLocalSwitch.isChecked)
+ sp.putBoolean(PREF_CSV_CLOUD_ENABLED, csvCloudSwitch.isChecked)
+
+ onSettingsChanged()
+ ToastUtils.infoToast(activity, rh.gs(R.string.export_options_updated))
+ }
+ .setNegativeButton(rh.gs(app.aaps.core.ui.R.string.cancel), null)
+ .create()
+
+ dialog.show()
+ }
+
+ /**
+ * Set up mutual exclusivity between two switches - when one is turned on, the other is turned off
+ */
+ private fun setupMutualExclusivity(switch1: Switch, switch2: Switch) {
+ switch1.setOnCheckedChangeListener { _, isChecked ->
+ if (isChecked && switch2.isChecked) {
+ switch2.isChecked = false
+ }
+ // Ensure at least one is checked
+ if (!isChecked && !switch2.isChecked) {
+ switch1.isChecked = true
+ }
+ }
+
+ switch2.setOnCheckedChangeListener { _, isChecked ->
+ if (isChecked && switch1.isChecked) {
+ switch1.isChecked = false
+ }
+ // Ensure at least one is checked
+ if (!isChecked && !switch1.isChecked) {
+ switch2.isChecked = true
+ }
+ }
+ }
+
+ /**
+ * Set up at-least-one-selected logic for two checkboxes
+ * Both can be selected, but at least one must be selected
+ */
+ private fun setupAtLeastOneSelected(checkbox1: CheckBox, checkbox2: CheckBox) {
+ checkbox1.setOnCheckedChangeListener { _, isChecked ->
+ // Ensure at least one is checked
+ if (!isChecked && !checkbox2.isChecked) {
+ checkbox1.isChecked = true
+ }
+ }
+
+ checkbox2.setOnCheckedChangeListener { _, isChecked ->
+ // Ensure at least one is checked
+ if (!isChecked && !checkbox1.isChecked) {
+ checkbox2.isChecked = true
+ }
+ }
+ }
+
+ /**
+ * Get current export destination preferences
+ */
+ fun isAllCloudEnabled(): Boolean {
+ val value = sp.getBoolean(PREF_ALL_CLOUD_ENABLED, false)
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: isAllCloudEnabled=$value")
+ return value
+ }
+
+ fun isLogCloudEnabled(): Boolean {
+ val value = sp.getBoolean(PREF_LOG_CLOUD_ENABLED, false)
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: isLogCloudEnabled=$value")
+ return value
+ }
+
+ fun isSettingsLocalEnabled(): Boolean {
+ val value = sp.getBoolean(PREF_SETTINGS_LOCAL_ENABLED, true)
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: isSettingsLocalEnabled=$value")
+ return value
+ }
+
+ fun isSettingsCloudEnabled(): Boolean {
+ val value = sp.getBoolean(PREF_SETTINGS_CLOUD_ENABLED, false)
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: isSettingsCloudEnabled=$value")
+ return value
+ }
+
+ /**
+ * Check if both local and cloud are enabled for settings export
+ */
+ fun isSettingsBothEnabled(): Boolean {
+ val localEnabled = sp.getBoolean(PREF_SETTINGS_LOCAL_ENABLED, true)
+ val cloudEnabled = sp.getBoolean(PREF_SETTINGS_CLOUD_ENABLED, false)
+ val bothEnabled = localEnabled && cloudEnabled
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: isSettingsBothEnabled=$bothEnabled (local=$localEnabled, cloud=$cloudEnabled)")
+ return bothEnabled
+ }
+
+ fun isCsvCloudEnabled(): Boolean {
+ val value = sp.getBoolean(PREF_CSV_CLOUD_ENABLED, false)
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: isCsvCloudEnabled=$value")
+ return value
+ }
+
+ /**
+ * Reset all export settings to local/email mode
+ * - Disable "All Cloud"
+ * - Set Log to "Email" (disable cloud)
+ * - Set Settings to "Local" (disable cloud)
+ * - Set CSV to "Local" (disable cloud)
+ */
+ fun resetToLocalSettings() {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: Resetting all settings to local/email mode")
+ sp.putBoolean(PREF_ALL_CLOUD_ENABLED, false)
+ sp.putBoolean(PREF_LOG_EMAIL_ENABLED, true)
+ sp.putBoolean(PREF_LOG_CLOUD_ENABLED, false)
+ sp.putBoolean(PREF_SETTINGS_LOCAL_ENABLED, true)
+ sp.putBoolean(PREF_SETTINGS_CLOUD_ENABLED, false)
+ sp.putBoolean(PREF_CSV_LOCAL_ENABLED, true)
+ sp.putBoolean(PREF_CSV_CLOUD_ENABLED, false)
+ }
+
+ /**
+ * Enable "All Cloud" option for cloud export
+ * - Enable "All Cloud" switch
+ * - Set Log to "Cloud" (disable email)
+ * - Set Settings to "Cloud" (disable local)
+ * - Set CSV to "Cloud" (disable local)
+ */
+ fun enableAllCloud() {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: Enabling all cloud mode")
+ sp.putBoolean(PREF_ALL_CLOUD_ENABLED, true)
+ sp.putBoolean(PREF_LOG_EMAIL_ENABLED, false)
+ sp.putBoolean(PREF_LOG_CLOUD_ENABLED, true)
+ sp.putBoolean(PREF_SETTINGS_LOCAL_ENABLED, true)
+ sp.putBoolean(PREF_SETTINGS_CLOUD_ENABLED, true)
+ sp.putBoolean(PREF_CSV_LOCAL_ENABLED, false)
+ sp.putBoolean(PREF_CSV_CLOUD_ENABLED, true)
+ }
+
+ /**
+ * Enable local storage for settings export
+ * This is called when user declines cloud export but we still want to ensure local storage is enabled
+ */
+ fun enableLocalStorage() {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX ExportDestination: Enabling local storage")
+ sp.putBoolean(PREF_SETTINGS_LOCAL_ENABLED, true)
+ }
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/ImportSourceDialog.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/ImportSourceDialog.kt
new file mode 100644
index 00000000000..4f72b2ccca8
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/ImportSourceDialog.kt
@@ -0,0 +1,93 @@
+package app.aaps.plugins.configuration.maintenance.cloud
+
+import android.widget.LinearLayout
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.FragmentActivity
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.plugins.configuration.R
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Dialog to let user choose import source when both local and cloud are enabled
+ */
+@Singleton
+class ImportSourceDialog @Inject constructor(
+ private val aapsLogger: AAPSLogger,
+ private val rh: ResourceHelper,
+ private val exportOptionsDialog: ExportOptionsDialog,
+ private val cloudStorageManager: CloudStorageManager
+) {
+
+ enum class ImportSource {
+ LOCAL,
+ CLOUD
+ }
+
+ /**
+ * Check if import source selection dialog should be shown
+ * Returns true if both local and cloud are enabled for settings import
+ */
+ fun shouldShowSourceSelection(): Boolean {
+ val localEnabled = exportOptionsDialog.isSettingsLocalEnabled()
+ val cloudEnabled = exportOptionsDialog.isSettingsCloudEnabled()
+ val isCloudActive = cloudStorageManager.isCloudStorageActive()
+
+ // Show selection dialog only when both are enabled and cloud is properly configured
+ val shouldShow = localEnabled && cloudEnabled && isCloudActive
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} ImportSourceDialog: shouldShowSourceSelection=$shouldShow (local=$localEnabled, cloud=$cloudEnabled, cloudActive=$isCloudActive)")
+ return shouldShow
+ }
+
+ /**
+ * Get the single enabled import source if only one is enabled
+ * Returns null if both are enabled (should show dialog)
+ */
+ fun getSingleEnabledSource(): ImportSource? {
+ val localEnabled = exportOptionsDialog.isSettingsLocalEnabled()
+ val cloudEnabled = exportOptionsDialog.isSettingsCloudEnabled()
+ val isCloudActive = cloudStorageManager.isCloudStorageActive()
+
+ return when {
+ localEnabled && (!cloudEnabled || !isCloudActive) -> ImportSource.LOCAL
+ cloudEnabled && isCloudActive && !localEnabled -> ImportSource.CLOUD
+ else -> null // Both enabled, need to show dialog
+ }
+ }
+
+ /**
+ * Show import source selection dialog
+ */
+ fun showImportSourceDialog(
+ activity: FragmentActivity,
+ onSourceSelected: (ImportSource) -> Unit
+ ) {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} ImportSourceDialog: Showing import source selection dialog")
+
+ val dialogView = activity.layoutInflater.inflate(R.layout.dialog_import_source, null)
+
+ val localStorageRow = dialogView.findViewById(R.id.local_storage_row)
+ val cloudStorageRow = dialogView.findViewById(R.id.cloud_storage_row)
+
+ val dialog = AlertDialog.Builder(activity)
+ .setView(dialogView)
+ .setNegativeButton(rh.gs(app.aaps.core.ui.R.string.cancel), null)
+ .create()
+
+ localStorageRow.setOnClickListener {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} ImportSourceDialog: User selected LOCAL")
+ dialog.dismiss()
+ onSourceSelected(ImportSource.LOCAL)
+ }
+
+ cloudStorageRow.setOnClickListener {
+ aapsLogger.info(LTag.CORE, "${CloudConstants.LOG_PREFIX} ImportSourceDialog: User selected CLOUD")
+ dialog.dismiss()
+ onSourceSelected(ImportSource.CLOUD)
+ }
+
+ dialog.show()
+ }
+}
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/events/EventCloudStorageStatusChanged.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/events/EventCloudStorageStatusChanged.kt
new file mode 100644
index 00000000000..09399592e63
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/events/EventCloudStorageStatusChanged.kt
@@ -0,0 +1,9 @@
+package app.aaps.plugins.configuration.maintenance.cloud.events
+
+import app.aaps.core.interfaces.rx.events.Event
+
+/**
+ * Event fired when cloud storage connection status changes.
+ * This allows UI components to update immediately when connection errors occur.
+ */
+class EventCloudStorageStatusChanged : Event()
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/providers/googledrive/GoogleDriveManager.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/providers/googledrive/GoogleDriveManager.kt
new file mode 100644
index 00000000000..6885ba2f055
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/providers/googledrive/GoogleDriveManager.kt
@@ -0,0 +1,1419 @@
+package app.aaps.plugins.configuration.maintenance.cloud.providers.googledrive
+
+import android.content.Context
+import android.net.Uri
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
+import app.aaps.core.interfaces.notifications.Notification
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.core.interfaces.rx.bus.RxBus
+import app.aaps.core.interfaces.rx.events.EventNewNotification
+import app.aaps.core.interfaces.sharedPreferences.SP
+import app.aaps.plugins.configuration.R
+import app.aaps.plugins.configuration.maintenance.cloud.CloudConstants
+import app.aaps.plugins.configuration.maintenance.cloud.events.EventCloudStorageStatusChanged
+import kotlinx.coroutines.*
+import okhttp3.*
+import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.RequestBody.Companion.toRequestBody
+import org.json.JSONArray
+import org.json.JSONObject
+import java.io.IOException
+import java.io.OutputStream
+import java.net.ServerSocket
+import java.net.Socket
+import java.net.URLEncoder
+import java.security.MessageDigest
+import java.security.SecureRandom
+import java.util.*
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class GoogleDriveManager @Inject constructor(
+ private val aapsLogger: AAPSLogger,
+ private val rh: ResourceHelper,
+ private val sp: SP,
+ private val rxBus: RxBus,
+ private val context: Context
+) {
+
+ companion object {
+ private const val CLIENT_ID = "705061051276-3ied5cqa3kqhb0hpr7p0rggoffhq46ef.apps.googleusercontent.com"
+ private const val REDIRECT_PORT = 8080
+ private const val REDIRECT_URI = "http://localhost:$REDIRECT_PORT/oauth/callback"
+ private const val SCOPE = "https://www.googleapis.com/auth/drive.file"
+ private const val AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth"
+ private const val TOKEN_URL = "https://oauth2.googleapis.com/token"
+ private const val DRIVE_API_URL = "https://www.googleapis.com/drive/v3"
+ private const val UPLOAD_URL = "https://www.googleapis.com/upload/drive/v3"
+ private val LOG_PREFIX = CloudConstants.LOG_PREFIX
+
+ // SharedPreferences keys
+ private const val PREF_GOOGLE_DRIVE_REFRESH_TOKEN = "google_drive_refresh_token"
+ private const val PREF_GOOGLE_DRIVE_ACCESS_TOKEN = "google_drive_access_token"
+ private const val PREF_GOOGLE_DRIVE_TOKEN_EXPIRY = "google_drive_token_expiry"
+ private const val PREF_GOOGLE_DRIVE_STORAGE_TYPE = "google_drive_storage_type"
+ private const val PREF_GOOGLE_DRIVE_FOLDER_ID = "google_drive_folder_id"
+
+ // Storage types
+ const val STORAGE_TYPE_LOCAL = "local"
+ const val STORAGE_TYPE_GOOGLE_DRIVE = "google_drive"
+
+ // Notification IDs
+ const val NOTIFICATION_GOOGLE_DRIVE_ERROR = Notification.USER_MESSAGE + 100
+
+ }
+
+ private val client = OkHttpClient()
+ private val pathCache = mutableMapOf() // cache for resolved folder paths
+
+ // Error state tracking
+ private var connectionError = false
+ private var errorNotificationId: Int? = null
+
+ // Local server related
+ private var localServer: ServerSocket? = null
+ private var authCodeReceived: String? = null
+ private var authState: String? = null
+ private var serverJob: Job? = null
+
+ /**
+ * Check if there is a valid refresh token
+ */
+ fun hasValidRefreshToken(): Boolean {
+ return sp.getString(PREF_GOOGLE_DRIVE_REFRESH_TOKEN, "").isNotBlank()
+ }
+
+ /**
+ * Get current storage type with default value
+ */
+ fun getStorageType(): String {
+ val storageType = sp.getString(PREF_GOOGLE_DRIVE_STORAGE_TYPE, STORAGE_TYPE_LOCAL)
+ // If there is a refresh token but storage type is local, settings may have been reset, try to restore
+ if (storageType == STORAGE_TYPE_LOCAL && hasValidRefreshToken()) {
+ // Check if there is a valid folder ID
+ val folderId = sp.getString(PREF_GOOGLE_DRIVE_FOLDER_ID, "")
+ if (folderId.isNotEmpty()) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX Restoring Google Drive storage type from token presence")
+ sp.putString(PREF_GOOGLE_DRIVE_STORAGE_TYPE, STORAGE_TYPE_GOOGLE_DRIVE)
+ return STORAGE_TYPE_GOOGLE_DRIVE
+ }
+ }
+ return storageType
+ }
+
+ /**
+ * Set storage type
+ */
+ fun setStorageType(type: String) {
+ sp.putString(PREF_GOOGLE_DRIVE_STORAGE_TYPE, type)
+ }
+
+ /**
+ * Start OAuth2 authentication flow using PKCE
+ *
+ * Note: This implementation uses a local server approach instead of traditional Android OAuth2
+ * because AAPS is an open-source medical application where each user must compile their own APK.
+ * Since each compilation uses a different JKS (Java KeyStore) for signing, we cannot rely on
+ * a fixed JKS for Google OAuth2 verification. Therefore, we use a local HTTP server to receive
+ * the OAuth callback, which works regardless of the APK signing certificate.
+ */
+ suspend fun startPKCEAuth(): String {
+ return withContext(Dispatchers.IO) {
+ try {
+ // Start local server
+ startLocalServer()
+
+ // Generate code verifier and code challenge
+ val codeVerifier = generateCodeVerifier()
+ val codeChallenge = generateCodeChallenge(codeVerifier)
+
+ // Save code verifier for later use
+ sp.putString("google_drive_code_verifier", codeVerifier)
+
+ // Build authorization URL
+ val authUrl = buildAuthUrl(codeChallenge)
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX Google Drive auth URL: $authUrl")
+
+ authUrl
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error starting PKCE auth", e)
+ throw e
+ }
+ }
+ }
+
+ /**
+ * Handle authorization code and obtain refresh token
+ */
+ suspend fun exchangeCodeForTokens(authCode: String): Boolean {
+ return withContext(Dispatchers.IO) {
+ try {
+ val codeVerifier = sp.getString("google_drive_code_verifier", "")
+ if (codeVerifier.isEmpty()) {
+ throw IllegalStateException("Code verifier not found")
+ }
+
+ val requestBody = FormBody.Builder()
+ .add("client_id", CLIENT_ID)
+ .add("code", authCode)
+ .add("code_verifier", codeVerifier)
+ .add("grant_type", "authorization_code")
+ .add("redirect_uri", REDIRECT_URI)
+ .build()
+
+ val request = Request.Builder()
+ .url(TOKEN_URL)
+ .post(requestBody)
+ .build()
+
+ val response = client.newCall(request).execute()
+ val responseBody = response.body?.string() ?: ""
+
+ if (response.isSuccessful) {
+ val jsonResponse = JSONObject(responseBody)
+ val refreshToken = jsonResponse.optString("refresh_token")
+ val accessToken = jsonResponse.optString("access_token")
+ val expiresIn = jsonResponse.optLong("expires_in", 3600)
+
+ if (refreshToken.isNotEmpty()) {
+ sp.putString(PREF_GOOGLE_DRIVE_REFRESH_TOKEN, refreshToken)
+ sp.putString(PREF_GOOGLE_DRIVE_ACCESS_TOKEN, accessToken)
+ sp.putLong(PREF_GOOGLE_DRIVE_TOKEN_EXPIRY, System.currentTimeMillis() + expiresIn * 1000)
+
+ // Clear code verifier
+ sp.remove("google_drive_code_verifier")
+
+ // Clear any previous connection error since authorization succeeded
+ clearConnectionError()
+
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX Google Drive tokens obtained successfully")
+ return@withContext true
+ }
+ }
+
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Failed to exchange code for tokens: $responseBody")
+ false
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error exchanging code for tokens", e)
+ false
+ }
+ }
+ }
+
+ /**
+ * Get a valid access token
+ */
+ suspend fun getValidAccessToken(): String? = withContext(Dispatchers.IO) {
+ try {
+ val cachedToken = sp.getString(PREF_GOOGLE_DRIVE_ACCESS_TOKEN, "")
+ val expiry = sp.getLong(PREF_GOOGLE_DRIVE_TOKEN_EXPIRY, 0)
+
+ // If token still has more than 5 minutes of validity, use directly
+ if (cachedToken.isNotEmpty() && System.currentTimeMillis() < expiry - 300_000) {
+ return@withContext cachedToken
+ }
+
+ val refreshToken = sp.getString(PREF_GOOGLE_DRIVE_REFRESH_TOKEN, "")
+ if (refreshToken.isEmpty()) {
+ aapsLogger.warn(LTag.CORE, "$LOG_PREFIX Missing refresh token when refreshing access token")
+ showConnectionError(rh.gs(R.string.cloud_token_expired_or_invalid))
+ return@withContext null
+ }
+
+ val requestBody = FormBody.Builder()
+ .add("client_id", CLIENT_ID)
+ .add("grant_type", "refresh_token")
+ .add("refresh_token", refreshToken)
+ .build()
+
+ val request = Request.Builder()
+ .url(TOKEN_URL)
+ .post(requestBody)
+ .build()
+
+ val response = client.newCall(request).execute()
+ val responseBody = response.body?.string() ?: ""
+
+ if (response.isSuccessful) {
+ val jsonResponse = JSONObject(responseBody)
+ val newAccessToken = jsonResponse.optString("access_token")
+ val expiresIn = jsonResponse.optLong("expires_in", 3600)
+
+ if (newAccessToken.isNotEmpty()) {
+ sp.putString(PREF_GOOGLE_DRIVE_ACCESS_TOKEN, newAccessToken)
+ sp.putLong(PREF_GOOGLE_DRIVE_TOKEN_EXPIRY, System.currentTimeMillis() + expiresIn * 1000)
+ clearConnectionError()
+ return@withContext newAccessToken
+ }
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Failed to refresh access token: code=${response.code} body=${responseBody.take(200)}")
+ // Check if token is expired or revoked
+ handleApiError(response.code, responseBody, rh.gs(R.string.google_drive_token_refresh_failed))
+ }
+
+ null
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error refreshing access token", e)
+ showConnectionError(rh.gs(R.string.google_drive_token_refresh_error, e.message ?: ""))
+ null
+ }
+ }
+
+ /**
+ * Test Google Drive connection
+ */
+ suspend fun testConnection(): Boolean {
+ return withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken()
+ if (accessToken == null) {
+ // Error already shown in getValidAccessToken
+ return@withContext false
+ }
+ val request = Request.Builder()
+ .url("$DRIVE_API_URL/about?fields=user")
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ val response = client.newCall(request).execute()
+ if (response.isSuccessful) {
+ clearConnectionError()
+ return@withContext true
+ } else {
+ // Check if token expired/revoked
+ handleApiError(response.code, "", rh.gs(R.string.google_drive_connection_test_failed))
+ return@withContext false
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error testing Google Drive connection", e)
+ showConnectionError(rh.gs(R.string.google_drive_connect_error, e.message ?: ""))
+ false
+ }
+ }
+ }
+
+ /**
+ * List folders in Google Drive
+ */
+ suspend fun listFolders(parentId: String = "root"): List {
+ return withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken()
+ if (accessToken == null) {
+ // Error already shown in getValidAccessToken
+ return@withContext emptyList()
+ }
+ val url = "$DRIVE_API_URL/files?q=mimeType='application/vnd.google-apps.folder' and '$parentId' in parents and trashed=false&fields=files(id,name)&supportsAllDrives=true&includeItemsFromAllDrives=true"
+ val request = Request.Builder()
+ .url(url)
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ val response = client.newCall(request).execute()
+ val responseBody = response.body?.string() ?: ""
+ if (response.isSuccessful) {
+ clearConnectionError()
+ val jsonResponse = JSONObject(responseBody)
+ val files = jsonResponse.getJSONArray("files")
+ val folders = mutableListOf()
+ for (i in 0 until files.length()) {
+ val file = files.getJSONObject(i)
+ folders.add(DriveFolder(id = file.getString("id"), name = file.getString("name")))
+ }
+ return@withContext folders
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX List folders failed: ${response.code} ${response.message} body=${responseBody}")
+ // Check if token expired/revoked
+ handleApiError(response.code, responseBody, rh.gs(R.string.google_drive_list_folders_failed))
+ return@withContext emptyList()
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error listing Google Drive folders", e)
+ showConnectionError(rh.gs(R.string.google_drive_list_folders_error, e.message ?: ""))
+ emptyList()
+ }
+ }
+ }
+
+ /**
+ * Create folder
+ */
+ suspend fun createFolder(name: String, parentId: String = "root"): String? {
+ return withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken() ?: return@withContext null
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX GDRIVE creating folder: name='$name' parentId=$parentId")
+ val metadata = JSONObject().apply {
+ put("name", name)
+ put("mimeType", "application/vnd.google-apps.folder")
+ put("parents", JSONArray().put(parentId))
+ }
+
+ val requestBody = metadata.toString().toRequestBody("application/json".toMediaType())
+
+ val request = Request.Builder()
+ .url("$DRIVE_API_URL/files?fields=id&supportsAllDrives=true")
+ .header("Authorization", "Bearer $accessToken")
+ .post(requestBody)
+ .build()
+
+ val response = client.newCall(request).execute()
+ val responseBody = response.body?.string() ?: ""
+
+ if (response.isSuccessful) {
+ clearConnectionError()
+ val jsonResponse = JSONObject(responseBody)
+ val id = jsonResponse.optString("id").takeIf { it.isNotEmpty() }
+ if (id == null) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX GDRIVE Create folder missing id for name='$name' under parent=$parentId body=$responseBody")
+ }else{
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_CREATE_OK name='$name' parent=$parentId id=$id")
+ }
+ return@withContext id
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX GDRIVE Failed to create folder: $responseBody")
+ return@withContext null
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX GDRIVE Error creating folder", e)
+ null
+ }
+ }
+ }
+
+ /**
+ * Upload file to Google Drive (multipart/related)
+ */
+ suspend fun uploadFile(fileName: String, fileContent: ByteArray, mimeType: String = "application/octet-stream"): String? {
+ return withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken()
+ if (accessToken == null) {
+ // Error already shown in getValidAccessToken
+ return@withContext null
+ }
+ debugCurrentUser(accessToken)
+ // Resolve target folder: always prefer CloudConstants by file type; fallback to selected folder, then root
+ val inferredPath = inferCloudPathFor(fileName)
+ val folderId = resolveFolderIdForUpload(inferredPath) ?: return@withContext null
+ if (inferredPath != null) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_START pathHint='$inferredPath' usingFolderId=$folderId file=$fileName size=${fileContent.size} mimeHint=$mimeType")
+ } else {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_START noPathHint usingFolderId=$folderId file=$fileName size=${fileContent.size} mimeHint=$mimeType")
+ }
+
+ // Metadata JSON body with its own Content-Type
+ val metadataJson = JSONObject().apply {
+ put("name", fileName)
+ put("parents", JSONArray().put(folderId))
+ }.toString()
+ val metadataBody = metadataJson.toRequestBody("application/json; charset=UTF-8".toMediaType())
+
+ // File body with its own Content-Type (guess when needed)
+ val effectiveMime = guessMimeType(fileName, mimeType)
+ if (effectiveMime != mimeType) aapsLogger.info(LTag.CORE, "$LOG_PREFIX MIME_ADJUST original=$mimeType effective=$effectiveMime file=$fileName")
+ val mediaBody = fileContent.toRequestBody(effectiveMime.toMediaType())
+
+ val multipart = MultipartBody.Builder()
+ .setType("multipart/related".toMediaType())
+ // OkHttp automatically generates Content-Type header for each part based on RequestBody.contentType();
+ // Manually adding Content-Type will trigger IllegalArgumentException: Unexpected header: Content-Type.
+ .addPart(metadataBody)
+ .addPart(mediaBody)
+ .build()
+
+ val request = Request.Builder()
+ .url("$UPLOAD_URL/files?uploadType=multipart&fields=id&supportsAllDrives=true")
+ .header("Authorization", "Bearer $accessToken")
+ .post(multipart)
+ .build()
+
+ val response = client.newCall(request).execute()
+ val responseBodyStr = response.body?.string() ?: ""
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_RESPONSE code=${response.code} message='${response.message}' hasBody=${responseBodyStr.isNotEmpty()} folderId=$folderId file=$fileName")
+ if (responseBodyStr.isNotEmpty()) aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_RESPONSE_BODY ${responseBodyStr.take(500)}")
+
+ if (response.isSuccessful) {
+ val jsonResponse = JSONObject(responseBodyStr.ifEmpty { "{}" })
+ val id = jsonResponse.optString("id").takeIf { it.isNotEmpty() }
+ if (id == null) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX UPLOAD_NO_ID folderId=$folderId file=$fileName rawBody='${responseBodyStr.take(200)}'")
+ showConnectionError(rh.gs(R.string.google_drive_upload_no_id))
+ return@withContext null
+ }
+ // Post-upload verification
+ val verified = verifyFileExists(id, accessToken)
+ return@withContext if (verified) {
+ clearConnectionError()
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_OK id=$id file=$fileName folderId=$folderId")
+ logFilePathChain(id, accessToken, "UPLOAD_OK_CHAIN")
+ debugListFolderSnapshot(folderId, accessToken, label = "AFTER_UPLOAD")
+ id
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX UPLOAD_VERIFY_FAIL id=$id file=$fileName folderId=$folderId")
+ showConnectionError(rh.gs(R.string.google_drive_upload_verify_failed))
+ null
+ }
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX UPLOAD_FAIL code=${response.code} message='${response.message}' folderId=$folderId body=${responseBodyStr.take(300)}")
+ showConnectionError(rh.gs(R.string.google_drive_upload_failed, response.code.toString()))
+ null
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX EXCEPTION uploadFile file=$fileName", e)
+ showConnectionError(rh.gs(R.string.google_drive_upload_error, e.message ?: ""))
+ null
+ }
+ }
+ }
+
+ /**
+ * Infer default cloud path based on filename (used when no folder is selected).
+ */
+ private fun inferCloudPathFor(fileName: String): String? {
+ val lower = fileName.lowercase(Locale.getDefault())
+ return when {
+ lower.endsWith(".json") -> CloudConstants.CLOUD_PATH_SETTINGS
+ lower.endsWith(".csv") -> CloudConstants.CLOUD_PATH_USER_ENTRIES
+ lower.endsWith(".zip") -> CloudConstants.CLOUD_PATH_LOGS
+ else -> null
+ }
+ }
+
+ /** Ensure path always starts with AAPS/ */
+ private fun normalizeAapsPath(path: String?): String? {
+ if (path.isNullOrBlank()) return path
+ val trimmed = path.trim('/', ' ')
+ return if (trimmed.startsWith("AAPS/")) trimmed else "AAPS/$trimmed"
+ }
+
+ /**
+ * Ensure specified cloud path exists; if creation fails, send notification and return null.
+ */
+ private suspend fun ensureCloudPathOrError(path: String): String? {
+ val normalized = normalizeAapsPath(path) ?: path
+ if (normalized != path) aapsLogger.info(LTag.CORE, "$LOG_PREFIX ENSURE_PATH_NORMALIZE original='$path' normalized='$normalized'")
+ val id = getOrCreateFolderPath(normalized)
+ if (id.isNullOrEmpty()) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Unable to ensure cloud path '$normalized'")
+ showConnectionError(rh.gs(R.string.google_drive_folder_access_error, normalized))
+ return null
+ }
+ return id
+ }
+
+ private suspend fun resolveFolderIdForUpload(pathHint: String?): String? {
+ if (!pathHint.isNullOrBlank()) {
+ val ensured = ensureCloudPathOrError(pathHint)
+ if (ensured != null) {
+ val stored = getSelectedFolderId()
+ if (stored != ensured) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_RESOLVE_UPDATE path='$pathHint' newId=$ensured oldId=${stored?.ifEmpty { "" } ?: ""}")
+ setSelectedFolderId(ensured)
+ } else {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_RESOLVE_REUSE path='$pathHint' id=$ensured")
+ }
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX FOLDER_RESOLVE_FAILED path='$pathHint'")
+ }
+ return ensured
+ }
+
+ val stored = getSelectedFolderId()?.ifEmpty { null }
+ if (stored != null) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_RESOLVE_USE_STORED storedId=$stored pathHint=''")
+ return stored
+ }
+
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_RESOLVE_DEFAULT_ROOT")
+ return "root"
+ }
+
+ /**
+ * Set selected folder ID
+ */
+ fun setSelectedFolderId(folderId: String) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX SET_SELECTED_FOLDER folderId=$folderId")
+ sp.putString(PREF_GOOGLE_DRIVE_FOLDER_ID, folderId)
+ }
+
+ /**
+ * Get selected folder ID
+ */
+ fun getSelectedFolderId(): String {
+ val folderId = sp.getString(PREF_GOOGLE_DRIVE_FOLDER_ID, "")
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX GET_SELECTED_FOLDER folderId='$folderId'")
+ return folderId
+ }
+
+ /**
+ * Clear Google Drive related settings
+ */
+ fun clearGoogleDriveSettings() {
+ sp.remove(PREF_GOOGLE_DRIVE_REFRESH_TOKEN)
+ sp.remove(PREF_GOOGLE_DRIVE_ACCESS_TOKEN)
+ sp.remove(PREF_GOOGLE_DRIVE_TOKEN_EXPIRY)
+ sp.remove(PREF_GOOGLE_DRIVE_FOLDER_ID)
+ sp.remove("google_drive_code_verifier")
+ }
+
+ /**
+ * Show connection error notification
+ */
+ private fun showConnectionError(message: String) {
+ connectionError = true
+ val notificationId = NOTIFICATION_GOOGLE_DRIVE_ERROR
+ errorNotificationId = notificationId
+
+ val notification = Notification(
+ notificationId,
+ message,
+ Notification.URGENT,
+ 60
+ )
+ rxBus.send(EventNewNotification(notification))
+ // Notify UI to update cloud storage error state immediately
+ rxBus.send(EventCloudStorageStatusChanged())
+ }
+
+ /**
+ * Check if response indicates token expired or revoked
+ */
+ private fun isTokenExpiredOrRevoked(responseCode: Int, responseBody: String = ""): Boolean {
+ return responseCode == 401 || responseCode == 403 ||
+ responseBody.contains("invalid_grant") ||
+ responseBody.contains("Token has been expired or revoked")
+ }
+
+ /**
+ * Handle API error response and show appropriate error message
+ * @param responseCode HTTP response code
+ * @param responseBody Response body for additional error detection
+ * @param fallbackMessage Message to show when error is not token-related
+ */
+ private fun handleApiError(responseCode: Int, responseBody: String = "", fallbackMessage: String) {
+ if (isTokenExpiredOrRevoked(responseCode, responseBody)) {
+ showConnectionError(rh.gs(R.string.cloud_token_expired_or_invalid))
+ } else {
+ showConnectionError(fallbackMessage)
+ }
+ }
+
+
+
+ /**
+ * Generate code verifier
+ */
+ private fun generateCodeVerifier(): String {
+ val bytes = ByteArray(32)
+ SecureRandom().nextBytes(bytes)
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes)
+ }
+
+ /**
+ * Generate code challenge
+ */
+ private fun generateCodeChallenge(codeVerifier: String): String {
+ val bytes = codeVerifier.toByteArray(Charsets.US_ASCII)
+ val messageDigest = MessageDigest.getInstance("SHA-256")
+ val digest = messageDigest.digest(bytes)
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(digest)
+ }
+
+ /**
+ * Build authorization URL
+ */
+ private fun buildAuthUrl(codeChallenge: String): String {
+ val state = UUID.randomUUID().toString()
+ sp.putString("google_drive_oauth_state", state)
+
+ return Uri.parse(AUTH_URL).buildUpon()
+ .appendQueryParameter("client_id", CLIENT_ID)
+ .appendQueryParameter("redirect_uri", REDIRECT_URI)
+ .appendQueryParameter("response_type", "code")
+ .appendQueryParameter("scope", SCOPE)
+ .appendQueryParameter("code_challenge", codeChallenge)
+ .appendQueryParameter("code_challenge_method", "S256")
+ .appendQueryParameter("state", state)
+ .appendQueryParameter("access_type", "offline")
+ .appendQueryParameter("prompt", "consent")
+ .build()
+ .toString()
+ }
+
+ /**
+ * Start local HTTP server to receive OAuth callback
+ */
+ private fun startLocalServer() {
+ try {
+ // Stop existing server
+ stopLocalServer()
+
+ // Create new server
+ localServer = ServerSocket(REDIRECT_PORT)
+ localServer?.soTimeout = 1000 // Set timeout to avoid permanent blocking
+
+ // Start server to handle requests
+ serverJob = CoroutineScope(Dispatchers.IO).launch {
+ try {
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX Local OAuth server started on port $REDIRECT_PORT")
+
+ val server = localServer ?: return@launch
+ while (isActive && !server.isClosed) {
+ try {
+ val clientSocket = try { server.accept() } catch (toe: java.net.SocketTimeoutException) { null }
+ clientSocket?.let { socket ->
+ launch { handleHttpRequest(socket) }
+ }
+ } catch (e: Exception) {
+ if (!server.isClosed) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error accepting connection", e)
+ }
+ }
+ }
+ } catch (e: Exception) {
+ val server = localServer
+ if (server != null && !server.isClosed) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Server error", e)
+ }
+ }
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Failed to start local OAuth server", e)
+ throw e
+ }
+ }
+
+ /**
+ * Stop local HTTP server
+ */
+ private fun stopLocalServer() {
+ try {
+ serverJob?.cancel()
+ localServer?.close()
+ localServer = null
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX Local OAuth server stopped")
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error stopping server", e)
+ }
+ }
+
+ /**
+ * Handle HTTP request
+ */
+ private suspend fun handleHttpRequest(socket: Socket) {
+ try {
+ val input = socket.getInputStream().bufferedReader()
+ val output = socket.getOutputStream()
+
+ // Read HTTP request
+ val requestLine = input.readLine()
+ if (requestLine == null) {
+ socket.close()
+ return
+ }
+
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX HTTP Request: $requestLine")
+
+ // Parse request path
+ val parts = requestLine.split(" ")
+ if (parts.size >= 2) {
+ val path = parts[1]
+ if (path.startsWith("/oauth/callback")) {
+ handleOAuthCallback(path, output)
+ } else {
+ sendHttpResponse(output, 404, "Not Found")
+ }
+ } else {
+ sendHttpResponse(output, 400, "Bad Request")
+ }
+
+ socket.close()
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error handling HTTP request", e)
+ try {
+ socket.close()
+ } catch (ignored: Exception) {}
+ }
+ }
+
+ /**
+ * Handle OAuth callback
+ */
+ private suspend fun handleOAuthCallback(path: String, output: OutputStream) {
+ try {
+ // Parse query parameters
+ val queryIndex = path.indexOf('?')
+ val params = if (queryIndex >= 0) {
+ parseQueryString(path.substring(queryIndex + 1))
+ } else {
+ emptyMap()
+ }
+
+ val code = params["code"]
+ val state = params["state"]
+ val error = params["error"]
+
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX OAuth callback received - code: ${code != null}, state: $state, error: $error")
+
+ if (error != null) {
+ sendHttpResponse(output, 400, "OAuth error: $error")
+ return
+ }
+
+ if (code != null && state != null) {
+ // Verify state
+ val savedState = sp.getString("google_drive_oauth_state", "")
+ if (state == savedState) {
+ authCodeReceived = code
+ authState = state
+ sendHttpResponse(output, 200, "Authorization successful! You can close this window.")
+ } else {
+ sendHttpResponse(output, 400, "Invalid state parameter")
+ }
+ } else {
+ sendHttpResponse(output, 400, "Missing code or state parameter")
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error handling OAuth callback", e)
+ sendHttpResponse(output, 500, "Internal server error")
+ } finally {
+ // Delay closing server
+ CoroutineScope(Dispatchers.IO).launch {
+ delay(2000) // Wait 2 seconds for response to complete
+ stopLocalServer()
+ }
+ }
+ }
+
+ /**
+ * Parse query string
+ */
+ private fun parseQueryString(query: String?): Map {
+ if (query.isNullOrEmpty()) return emptyMap()
+
+ return query.split("&").associate { param ->
+ val keyValue = param.split("=", limit = 2)
+ val key = keyValue[0]
+ val value = if (keyValue.size > 1) keyValue[1] else ""
+ key to value
+ }
+ }
+
+ /**
+ * Send HTTP response
+ */
+ private fun sendHttpResponse(output: OutputStream, statusCode: Int, message: String) {
+ try {
+ val statusText = when (statusCode) {
+ 200 -> "OK"
+ 400 -> "Bad Request"
+ 404 -> "Not Found"
+ 500 -> "Internal Server Error"
+ else -> "Unknown"
+ }
+ val autoCloseScript = if (statusCode == 200) """
+
+ """ else ""
+ val metaRefresh = if (statusCode == 200) "" else ""
+ val className = if (statusCode == 200) "success" else "error"
+ val htmlContent = """
+
+
+
+ AAPS Google Drive Authorization
+
+ $metaRefresh
+
+
+
+
AAPS Google Drive Authorization
+
$message
+ $autoCloseScript
+
+
+ """.trimIndent()
+ val response = "HTTP/1.1 $statusCode $statusText\r\n" +
+ "Content-Type: text/html; charset=UTF-8\r\n" +
+ "Content-Length: ${htmlContent.toByteArray().size}\r\n" +
+ "Connection: close\r\n" +
+ "\r\n" +
+ htmlContent
+ output.write(response.toByteArray())
+ output.flush()
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error sending HTTP response", e)
+ }
+ }
+
+ /**
+ * Wait and get authorization code
+ */
+ suspend fun waitForAuthCode(timeoutMs: Long = 60000): String? {
+ return withContext(Dispatchers.IO) {
+ val startTime = System.currentTimeMillis()
+
+ while (authCodeReceived == null && System.currentTimeMillis() - startTime < timeoutMs) {
+ delay(500)
+ }
+
+ val code = authCodeReceived
+ authCodeReceived = null // Clear used authorization code
+ authState = null
+
+ code
+ }
+ }
+
+ /**
+ * Check if there is a connection error
+ */
+ fun hasConnectionError(): Boolean {
+ val storageType = sp.getString(PREF_GOOGLE_DRIVE_STORAGE_TYPE, STORAGE_TYPE_LOCAL)
+ return storageType == STORAGE_TYPE_GOOGLE_DRIVE && connectionError
+ }
+
+ /**
+ * Clear connection error state
+ */
+ fun clearConnectionError() {
+ connectionError = false
+ errorNotificationId?.let { id ->
+ // TODO: Implement logic to clear notification
+ }
+ errorNotificationId = null
+ // Notify UI to update cloud storage error state immediately
+ rxBus.send(EventCloudStorageStatusChanged())
+ }
+
+ /**
+ * List settings files (json) in current folder
+ */
+ suspend fun listSettingsFiles(): List = withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken() ?: return@withContext emptyList()
+ val folderId = getSelectedFolderId()?.ifEmpty { "root" } ?: "root"
+ val query = "'$folderId' in parents and trashed=false"
+ val encodedQuery = URLEncoder.encode(query, "UTF-8")
+ val url = "$DRIVE_API_URL/files?q=$encodedQuery&fields=files(id,name,modifiedTime,mimeType)&pageSize=50&supportsAllDrives=true&includeItemsFromAllDrives=true"
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX LIST_SETTINGS_FILES_START folderId=$folderId query='$query' encodedQuery=$encodedQuery")
+ val request = Request.Builder()
+ .url(url)
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ val response = client.newCall(request).execute()
+ val body = response.body?.string() ?: ""
+ if (!response.isSuccessful) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX FOLDER_LIST_FAIL folderId=$folderId code=${response.code} body=${body.take(300)}")
+ showConnectionError(rh.gs(R.string.google_drive_list_settings_failed))
+ return@withContext emptyList()
+ }
+ clearConnectionError()
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX LIST_SETTINGS_FILES_OK count=${body.length} folderId=$folderId")
+ val json = JSONObject(body)
+ val arr = json.optJSONArray("files") ?: JSONArray()
+ val result = mutableListOf()
+ for (i in 0 until arr.length()) {
+ val f = arr.getJSONObject(i)
+ val mimeType = f.optString("mimeType", "")
+ // Filter out folders
+ if (mimeType != "application/vnd.google-apps.folder") {
+ result.add(DriveFile(id = f.getString("id"), name = f.getString("name")))
+ }
+ }
+ result
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error listing settings files", e)
+ showConnectionError(rh.gs(R.string.google_drive_list_settings_error, e.message ?: ""))
+ emptyList()
+ }
+ }
+
+ /**
+ * Download file content
+ */
+ suspend fun downloadFile(fileId: String): ByteArray? = withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken() ?: return@withContext null
+ val request = Request.Builder()
+ .url("$DRIVE_API_URL/files/$fileId?alt=media")
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ val response = client.newCall(request).execute()
+ if (!response.isSuccessful) {
+ val msg = response.body?.string()
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Failed to download file: ${msg}")
+ showConnectionError(rh.gs(R.string.google_drive_download_failed))
+ return@withContext null
+ }
+ clearConnectionError()
+ response.body?.bytes()
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error downloading file", e)
+ showConnectionError(rh.gs(R.string.google_drive_download_error, e.message ?: ""))
+ null
+ }
+ }
+
+ /**
+ * List settings files (json) in current folder with pagination
+ */
+ suspend fun listSettingsFilesPaged(pageToken: String? = null, pageSize: Int = 10): DriveFilePage = withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken() ?: return@withContext DriveFilePage(emptyList(), null)
+ val folderId = getSelectedFolderId().ifEmpty { "root" }
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX LIST_SETTINGS_PAGED folderId='$folderId' pageToken=$pageToken pageSize=$pageSize")
+ val query = "'$folderId' in parents and trashed=false"
+ val encodedQuery = URLEncoder.encode(query, "UTF-8")
+ val base = StringBuilder()
+ .append("$DRIVE_API_URL/files?q=").append(encodedQuery)
+ .append("&fields=files(id,name,modifiedTime,mimeType),nextPageToken")
+ .append("&pageSize=").append(pageSize)
+ .append("&supportsAllDrives=true&includeItemsFromAllDrives=true")
+ if (!pageToken.isNullOrEmpty()) base.append("&pageToken=").append(pageToken)
+ val request = Request.Builder()
+ .url(base.toString())
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ val response = client.newCall(request).execute()
+ val body = response.body?.string() ?: ""
+ if (!response.isSuccessful) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Failed to list settings files (paged): $body")
+ showConnectionError(rh.gs(R.string.google_drive_list_settings_failed))
+ return@withContext DriveFilePage(emptyList(), null)
+ }
+ clearConnectionError()
+ val json = JSONObject(body)
+ val arr = json.optJSONArray("files") ?: JSONArray()
+ val result = mutableListOf()
+ for (i in 0 until arr.length()) {
+ val f = arr.getJSONObject(i)
+ val mimeType = f.optString("mimeType", "")
+ // Filter out folders
+ if (mimeType != "application/vnd.google-apps.folder") {
+ result.add(DriveFile(id = f.getString("id"), name = f.getString("name")))
+ }
+ }
+ val next = json.optString("nextPageToken", "").ifEmpty { null }
+ DriveFilePage(result, next)
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error listing settings files (paged)", e)
+ showConnectionError(rh.gs(R.string.google_drive_list_settings_error, e.message ?: ""))
+ DriveFilePage(emptyList(), null)
+ }
+ }
+
+ /**
+ * Count total settings files matching yyyy-MM-dd_HHmmss*.json pattern in current folder
+ */
+ suspend fun countSettingsFiles(): Int = withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken() ?: return@withContext 0
+ val folderId = getSelectedFolderId().ifEmpty { "root" }
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX COUNT_SETTINGS_FILES folderId='$folderId'")
+ val query = "'$folderId' in parents and trashed=false"
+ val encodedQuery = URLEncoder.encode(query, "UTF-8")
+ val namePattern = Regex("^\\d{4}-\\d{2}-\\d{2}_\\d{6}.*\\.json$", RegexOption.IGNORE_CASE)
+
+ var totalCount = 0
+ var pageToken: String? = null
+
+ do {
+ val base = StringBuilder()
+ .append("$DRIVE_API_URL/files?q=").append(encodedQuery)
+ .append("&fields=files(name,mimeType),nextPageToken")
+ .append("&pageSize=100") // Use larger page size for counting
+ .append("&supportsAllDrives=true&includeItemsFromAllDrives=true")
+ if (!pageToken.isNullOrEmpty()) base.append("&pageToken=").append(pageToken)
+
+ val request = Request.Builder()
+ .url(base.toString())
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ val response = client.newCall(request).execute()
+ val body = response.body?.string() ?: ""
+
+ if (!response.isSuccessful) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Failed to count settings files: $body")
+ return@withContext 0
+ }
+
+ val json = JSONObject(body)
+ val arr = json.optJSONArray("files") ?: JSONArray()
+
+ for (i in 0 until arr.length()) {
+ val f = arr.getJSONObject(i)
+ val mimeType = f.optString("mimeType", "")
+ val name = f.optString("name", "")
+ // Filter out folders and count only matching files
+ if (mimeType != "application/vnd.google-apps.folder" && namePattern.containsMatchIn(name)) {
+ totalCount++
+ }
+ }
+
+ pageToken = json.optString("nextPageToken", "").ifEmpty { null }
+ } while (pageToken != null)
+
+ totalCount
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error counting settings files", e)
+ 0
+ }
+ }
+
+ /**
+ * Get or create multi-level folders (expressed as path), return final folder ID.
+ * All paths are automatically prefixed with "AAPS/" if not already present.
+ * Example: path = "export/preferences" -> creates "AAPS/export/preferences"
+ *
+ * Special handling for "AAPS" folder: Always reuses existing AAPS folder if one exists in root.
+ */
+ suspend fun getOrCreateFolderPath(path: String, baseParentId: String = "root"): String? = withContext(Dispatchers.IO) {
+ try {
+ // Normalize path to always start with AAPS/
+ val normalizedPath = normalizeAapsPath(path) ?: return@withContext null
+ var trimmed = normalizedPath.trim('/',' ')
+
+ val segments = trimmed.split('/').filter { it.isNotBlank() }
+ var currentParentId = baseParentId
+ val accumulated = mutableListOf()
+
+ for ((index, seg) in segments.withIndex()) {
+ accumulated.add(seg)
+ val currentPath = accumulated.joinToString("/")
+ val parentPath = accumulated.dropLast(1).joinToString("/")
+ val cachedId = pathCache[currentPath]
+ if (cachedId != null) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_SEGMENT_CACHE_HIT level=${index + 1} path='/${currentPath}' id=$cachedId")
+ currentParentId = cachedId
+ continue
+ }
+
+ val parentDisplay = if (parentPath.isEmpty()) "/" else "/$parentPath"
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_SEGMENT_CHECK level=${index + 1} name='$seg' parentPath='$parentDisplay' parentId=$currentParentId fullPath='/$currentPath'")
+
+ val existingId = findFolderIdByName(seg, currentParentId)
+
+ val resolvedId = existingId ?: createFolder(seg, currentParentId) ?: run {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX FOLDER_SEGMENT_CREATE_FAIL name='$seg' parentPath='$parentDisplay' parentId=$currentParentId requested='/$currentPath'")
+ return@withContext null
+ }
+
+ if (existingId != null) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_SEGMENT_EXIST level=${index + 1} name='$seg' id=$resolvedId fullPath='/$currentPath'")
+ } else {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_SEGMENT_CREATED level=${index + 1} name='$seg' id=$resolvedId fullPath='/$currentPath'")
+ }
+
+ pathCache[currentPath] = resolvedId
+ currentParentId = resolvedId
+ }
+
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_PATH_READY path='$path' finalId=$currentParentId")
+ pathCache[trimmed] = currentParentId
+ currentParentId
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Error ensuring folder path $path", e)
+ null
+ }
+ }
+
+ /**
+ * Find subfolder by name under specified parent, return its ID if exists; otherwise return null.
+ */
+ private suspend fun findFolderIdByName(name: String, parentId: String): String? = withContext(Dispatchers.IO) {
+ try {
+ val accessToken = getValidAccessToken() ?: return@withContext null
+ val query = "mimeType='application/vnd.google-apps.folder' and name='$name' and '$parentId' in parents and trashed=false"
+ val encodedQuery = URLEncoder.encode(query, "UTF-8")
+ val url = "$DRIVE_API_URL/files?q=$encodedQuery&fields=files(id,name)&pageSize=1&supportsAllDrives=true&includeItemsFromAllDrives=true"
+ val request = Request.Builder()
+ .url(url)
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ val response = client.newCall(request).execute()
+ val body = response.body?.string() ?: ""
+ if (!response.isSuccessful) return@withContext null
+ val json = JSONObject(body)
+ val arr = json.optJSONArray("files") ?: JSONArray()
+ if (arr.length() == 0) return@withContext null
+ arr.getJSONObject(0).getString("id")
+ } catch (_: Exception) {
+ null
+ }
+ }
+
+ /**
+ * Upload file to specified cloud path (automatically creates folders).
+ */
+ suspend fun uploadFileToPath(fileName: String, fileContent: ByteArray, mimeType: String, path: String): String? {
+ return withContext(Dispatchers.IO) {
+ try {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_REQUESTED path='$path' file=$fileName size=${fileContent.size}")
+ val folderId = resolveFolderIdForUpload(path) ?: run {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX Cannot resolve target path '$path'")
+ showConnectionError("Cannot create destination path")
+ return@withContext null
+ }
+ val accessToken = getValidAccessToken() ?: return@withContext null
+ try {
+ debugCurrentUser(accessToken)
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX DEBUG_USER_FAILED (non-critical)", e)
+ }
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_START pathHint='$path' folderId=$folderId file=$fileName size=${fileContent.size} mimeHint=$mimeType")
+
+ val metadataJson = JSONObject().apply {
+ put("name", fileName)
+ put("parents", JSONArray().put(folderId))
+ }.toString()
+ val metadataBody = metadataJson.toRequestBody("application/json; charset=UTF-8".toMediaType())
+ val effectiveMime = guessMimeType(fileName, mimeType)
+ if (effectiveMime != mimeType) aapsLogger.info(LTag.CORE, "$LOG_PREFIX MIME_ADJUST original=$mimeType effective=$effectiveMime file=$fileName")
+ val mediaBody = fileContent.toRequestBody(effectiveMime.toMediaType())
+
+ val multipart = MultipartBody.Builder()
+ .setType("multipart/related".toMediaType())
+ // Same as above, remove custom Content-Type header, let OkHttp automatically add based on body.
+ .addPart(metadataBody)
+ .addPart(mediaBody)
+ .build()
+
+ val request = Request.Builder()
+ .url("$UPLOAD_URL/files?uploadType=multipart&fields=id&supportsAllDrives=true")
+ .header("Authorization", "Bearer $accessToken")
+ .post(multipart)
+ .build()
+
+ val response = client.newCall(request).execute()
+ val responseBodyStr = response.body?.string() ?: ""
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_RESPONSE code=${response.code} message='${response.message}' hasBody=${responseBodyStr.isNotEmpty()} path='$path' file=$fileName")
+ if (responseBodyStr.isNotEmpty()) aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_RESPONSE_BODY ${responseBodyStr.take(500)}")
+ if (response.isSuccessful) {
+ val jsonResponse = JSONObject(responseBodyStr.ifEmpty { "{}" })
+ val id = jsonResponse.optString("id").takeIf { it.isNotEmpty() }
+ if (id == null) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_NO_ID path='$path' file=$fileName rawBody='${responseBodyStr.take(200)}'")
+ showConnectionError("Upload succeeded but no id returned")
+ return@withContext null
+ }
+ val verified = verifyFileExists(id, accessToken)
+ return@withContext if (verified) {
+ clearConnectionError()
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_OK id=$id path='$path' file=$fileName")
+ logFilePathChain(id, accessToken, "UPLOAD_PATH_OK_CHAIN")
+ debugListFolderSnapshot(folderId, accessToken, label = "AFTER_UPLOAD_PATH")
+ id
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_VERIFY_FAIL id=$id path='$path' file=$fileName")
+ showConnectionError("Upload verification failed")
+ null
+ }
+ } else {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX UPLOAD_PATH_FAIL path='$path' code=${response.code} message='${response.message}' body=${responseBodyStr.take(300)}")
+ showConnectionError("Upload failed: ${response.code}")
+ null
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX EXCEPTION uploadFileToPath path='$path' file=$fileName", e)
+ showConnectionError("Error uploading file: ${e.message}")
+ null
+ }
+ }
+ }
+
+ /**
+ * Infer MIME type for common file extensions, avoid using imprecise octet-stream.
+ */
+ private fun guessMimeType(fileName: String, provided: String?): String {
+ val prov = provided?.trim().orEmpty()
+ if (prov.isNotEmpty() && prov != "application/octet-stream") return prov
+ val lower = fileName.lowercase(Locale.getDefault())
+ return when {
+ lower.endsWith(".json") -> "application/json; charset=UTF-8"
+ lower.endsWith(".csv") -> "text/csv; charset=UTF-8"
+ lower.endsWith(".zip") -> "application/zip"
+ else -> if (prov.isNotEmpty()) prov else "application/octet-stream"
+ }
+ }
+
+ /**
+ * Verify if file actually exists (immediately call Drive API to retrieve metadata).
+ * If retrieval fails or file is marked as trashed, verification is considered failed.
+ */
+ private fun verifyFileExists(fileId: String, accessToken: String): Boolean {
+ return try {
+ val req = Request.Builder()
+ .url("$DRIVE_API_URL/files/$fileId?fields=id,name,parents,mimeType,trashed,webViewLink,createdTime,modifiedTime,size&supportsAllDrives=true")
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ client.newCall(req).execute().use { resp ->
+ val bodyStr = resp.body?.string() ?: ""
+ if (!resp.isSuccessful) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX VERIFY_FAIL id=$fileId code=${resp.code} body='${bodyStr.take(300)}'")
+ return false
+ }
+ val json = JSONObject(bodyStr)
+ val trashed = json.optBoolean("trashed", false)
+ if (trashed) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX VERIFY_FAIL_TRASHED id=$fileId json='${bodyStr.take(200)}'")
+ return false
+ }
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX VERIFY_OK id=$fileId name=${json.optString("name")} parents=${json.optJSONArray("parents")?.toString() ?: "[]"} mime=${json.optString("mimeType")} size=${json.optLong("size", -1)} webViewLink=${json.optString("webViewLink")} created=${json.optString("createdTime")} modified=${json.optString("modifiedTime")}")
+ true
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX VERIFY_EXCEPTION id=$fileId", e)
+ false
+ }
+ }
+
+ private fun debugCurrentUser(accessToken: String) {
+ try {
+ val req = Request.Builder()
+ .url("$DRIVE_API_URL/about?fields=user(emailAddress,displayName)&supportsAllDrives=true")
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ client.newCall(req).execute().use { resp ->
+ val body = resp.body?.string() ?: ""
+ if (resp.isSuccessful) {
+ runCatching { JSONObject(body).optJSONObject("user") }.getOrNull()?.let { u ->
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX USER email=${u.optString("emailAddress")} display=${u.optString("displayName")}")
+ }
+ } else {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX USER_FAIL code=${resp.code}")
+ }
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.CORE, "$LOG_PREFIX USER_EXCEPTION", e)
+ }
+ }
+
+ private fun debugListFolderSnapshot(folderId: String, accessToken: String, label: String) {
+ try {
+ val query = "'$folderId' in parents and trashed=false"
+ val url = "$DRIVE_API_URL/files?q=${Uri.encode(query)}&fields=files(id,name,mimeType,modifiedTime),nextPageToken&pageSize=20&supportsAllDrives=true&includeItemsFromAllDrives=true"
+ val req = Request.Builder().url(url).header("Authorization", "Bearer $accessToken").build()
+ client.newCall(req).execute().use { resp ->
+ val body = resp.body?.string() ?: ""
+ if (!resp.isSuccessful) {
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX FOLDER_LIST_FAIL_DEBUG (non-critical) folderId=$folderId code=${resp.code}")
+ return
+ }
+ val json = JSONObject(body)
+ val arr = json.optJSONArray("files") ?: JSONArray()
+ val summary = StringBuilder()
+ for (i in 0 until arr.length()) {
+ val f = arr.getJSONObject(i)
+ summary.append(f.optString("name")).append('(').append(f.optString("id")).append(") ")
+ }
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX FOLDER_SNAPSHOT label=$label folderId=$folderId items=${arr.length()} list='${summary.toString().trim()}'")
+ }
+ } catch (e: Exception) {
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX FOLDER_SNAPSHOT_EXCEPTION (non-critical) folderId=$folderId: ${e.message}")
+ }
+ }
+
+ private fun logFilePathChain(fileId: String, accessToken: String, tag: String) {
+ try {
+ val chain = mutableListOf()
+ var currentId: String? = fileId
+ var safety = 0
+ var reachedRoot = false
+ var abort = false
+ while (currentId != null && safety++ < 12 && !abort) {
+ val req = Request.Builder()
+ .url("$DRIVE_API_URL/files/$currentId?fields=id,name,parents&supportsAllDrives=true")
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+ client.newCall(req).execute().use { resp ->
+ val body = resp.body?.string() ?: ""
+ if (!resp.isSuccessful) {
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX PATH_CHAIN_FAIL_DEBUG (non-critical) id=$currentId code=${resp.code} partial='${chain.joinToString("/")}'")
+ abort = true
+ }
+ if (!abort) {
+ val json = JSONObject(body)
+ chain.add(json.optString("name"))
+ val parentsArr = json.optJSONArray("parents")
+ currentId = if (parentsArr != null && parentsArr.length() > 0) parentsArr.getString(0) else null
+ if (currentId == "root") {
+ chain.add("root")
+ reachedRoot = true
+ }
+ }
+ }
+ if (reachedRoot) break
+ }
+ val status = if (reachedRoot) "COMPLETE" else if (abort) "ABORT" else "PARTIAL"
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX $tag status=$status chain='${chain.joinToString("/")}' depth=${chain.size}")
+ } catch (e: Exception) {
+ aapsLogger.debug(LTag.CORE, "$LOG_PREFIX PATH_CHAIN_EXCEPTION (non-critical) fileId=$fileId: ${e.message}")
+ }
+ }
+}
+
+/**
+ * Google Drive folder data class
+ */
+data class DriveFolder(
+ val id: String,
+ val name: String
+)
+
+/** Google Drive file data class */
+data class DriveFile(
+ val id: String,
+ val name: String
+)
+
+/** Paginated result data class */
+data class DriveFilePage(
+ val files: List,
+ val nextPageToken: String?,
+ val totalCount: Int? = null // Optional total count of files matching pattern
+)
diff --git a/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/providers/googledrive/GoogleDriveProvider.kt b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/providers/googledrive/GoogleDriveProvider.kt
new file mode 100644
index 00000000000..b8cc077ac8c
--- /dev/null
+++ b/plugins/configuration/src/main/kotlin/app/aaps/plugins/configuration/maintenance/cloud/providers/googledrive/GoogleDriveProvider.kt
@@ -0,0 +1,203 @@
+package app.aaps.plugins.configuration.maintenance.cloud.providers.googledrive
+
+import android.content.Context
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.core.interfaces.rx.bus.RxBus
+import app.aaps.core.interfaces.sharedPreferences.SP
+import app.aaps.plugins.configuration.R
+import app.aaps.plugins.configuration.maintenance.cloud.CloudConstants
+import app.aaps.plugins.configuration.maintenance.cloud.CloudFile
+import app.aaps.plugins.configuration.maintenance.cloud.CloudFileListResult
+import app.aaps.plugins.configuration.maintenance.cloud.CloudFolder
+import app.aaps.plugins.configuration.maintenance.cloud.CloudStorageProvider
+import app.aaps.plugins.configuration.maintenance.cloud.StorageTypes
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Google Drive implementation of CloudStorageProvider.
+ *
+ * This class adapts GoogleDriveManager to the CloudStorageProvider interface,
+ * enabling the unified cloud storage architecture.
+ */
+@Singleton
+class GoogleDriveProvider @Inject constructor(
+ private val aapsLogger: AAPSLogger,
+ private val rh: ResourceHelper,
+ private val sp: SP,
+ private val rxBus: RxBus,
+ private val context: Context,
+ private val googleDriveManager: GoogleDriveManager
+) : CloudStorageProvider {
+
+ companion object {
+ private const val LOG_PREFIX = "[GoogleDriveProvider]"
+ }
+
+ private fun gLog(message: String) {
+ aapsLogger.info(LTag.CORE, "$LOG_PREFIX $message")
+ }
+
+ // ==================== Provider Identity ====================
+
+ override val storageType: String = StorageTypes.GOOGLE_DRIVE
+
+ override val displayName: String
+ get() = rh.gs(R.string.storage_google_drive)
+
+ override val iconResId: Int = R.drawable.ic_google_drive
+
+ override val authorizedTextResId: Int = R.string.google_drive_authorized
+
+ override val reAuthRequiredTextResId: Int = R.string.google_drive_reauth_required
+
+ // ==================== Authentication ====================
+
+ override suspend fun startAuth(): String? {
+ gLog("startAuth")
+ return googleDriveManager.startPKCEAuth()
+ }
+
+ override suspend fun completeAuth(authCode: String): Boolean {
+ gLog("completeAuth")
+ return googleDriveManager.exchangeCodeForTokens(authCode)
+ }
+
+ override fun hasValidCredentials(): Boolean {
+ return googleDriveManager.hasValidRefreshToken()
+ }
+
+ override fun clearCredentials() {
+ gLog("clearCredentials")
+ googleDriveManager.clearGoogleDriveSettings()
+ }
+
+ override suspend fun getValidAccessToken(): String? {
+ return googleDriveManager.getValidAccessToken()
+ }
+
+ // ==================== Connection ====================
+
+ override suspend fun testConnection(): Boolean {
+ gLog("testConnection")
+ return googleDriveManager.testConnection()
+ }
+
+ override fun hasConnectionError(): Boolean {
+ return googleDriveManager.hasConnectionError()
+ }
+
+ override fun clearConnectionError() {
+ googleDriveManager.clearConnectionError()
+ }
+
+ // ==================== Folder Operations ====================
+
+ override suspend fun getOrCreateFolderPath(path: String): String? {
+ gLog("getOrCreateFolderPath: $path")
+ return googleDriveManager.getOrCreateFolderPath(path)
+ }
+
+ override suspend fun createFolder(name: String, parentId: String): String? {
+ gLog("createFolder: $name under $parentId")
+ return googleDriveManager.createFolder(name, parentId)
+ }
+
+ override suspend fun listFolders(parentId: String): List {
+ gLog("listFolders: $parentId")
+ return googleDriveManager.listFolders(parentId).map { driveFolder ->
+ CloudFolder(
+ id = driveFolder.id,
+ name = driveFolder.name
+ )
+ }
+ }
+
+ // ==================== File Operations ====================
+
+ override suspend fun uploadFileToPath(
+ fileName: String,
+ content: ByteArray,
+ mimeType: String,
+ path: String
+ ): String? {
+ gLog("uploadFileToPath: $fileName to $path")
+ return googleDriveManager.uploadFileToPath(fileName, content, mimeType, path)
+ }
+
+ override suspend fun uploadFile(
+ fileName: String,
+ content: ByteArray,
+ mimeType: String
+ ): String? {
+ gLog("uploadFile: $fileName")
+ return googleDriveManager.uploadFile(fileName, content, mimeType)
+ }
+
+ override suspend fun downloadFile(fileId: String): ByteArray? {
+ gLog("downloadFile: $fileId")
+ return googleDriveManager.downloadFile(fileId)
+ }
+
+ override suspend fun listSettingsFiles(
+ pageSize: Int,
+ pageToken: String?
+ ): CloudFileListResult {
+ gLog("listSettingsFiles: pageSize=$pageSize")
+ val result = googleDriveManager.listSettingsFilesPaged(pageToken, pageSize)
+
+ return CloudFileListResult(
+ files = result.files.map { driveFile ->
+ CloudFile(
+ id = driveFile.id,
+ name = driveFile.name,
+ mimeType = guessMimeType(driveFile.name)
+ )
+ },
+ nextPageToken = result.nextPageToken,
+ totalCount = result.totalCount ?: -1
+ )
+ }
+
+ // ==================== Selected Folder ====================
+
+ override fun getSelectedFolderId(): String {
+ return googleDriveManager.getSelectedFolderId()
+ }
+
+ override fun setSelectedFolderId(folderId: String) {
+ gLog("setSelectedFolderId: $folderId")
+ googleDriveManager.setSelectedFolderId(folderId)
+ }
+
+ // ==================== OAuth Helpers ====================
+
+ /**
+ * Wait for OAuth authorization code (used during PKCE auth flow)
+ */
+ override suspend fun waitForAuthCode(timeoutMs: Long): String? {
+ return googleDriveManager.waitForAuthCode(timeoutMs)
+ }
+
+ /**
+ * Count settings files in the selected folder
+ */
+ override suspend fun countSettingsFiles(): Int {
+ return googleDriveManager.countSettingsFiles()
+ }
+
+ /**
+ * Guess MIME type based on file extension
+ */
+ private fun guessMimeType(fileName: String): String {
+ val lower = fileName.lowercase()
+ return when {
+ lower.endsWith(".json") -> "application/json"
+ lower.endsWith(".csv") -> "text/csv"
+ lower.endsWith(".zip") -> "application/zip"
+ else -> "application/octet-stream"
+ }
+ }
+}
diff --git a/plugins/configuration/src/main/res/drawable/ic_cloud_upload.xml b/plugins/configuration/src/main/res/drawable/ic_cloud_upload.xml
new file mode 100644
index 00000000000..b9896d7810b
--- /dev/null
+++ b/plugins/configuration/src/main/res/drawable/ic_cloud_upload.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/plugins/configuration/src/main/res/drawable/ic_error.xml b/plugins/configuration/src/main/res/drawable/ic_error.xml
new file mode 100644
index 00000000000..c9307610a20
--- /dev/null
+++ b/plugins/configuration/src/main/res/drawable/ic_error.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/plugins/configuration/src/main/res/drawable/ic_export_options.xml b/plugins/configuration/src/main/res/drawable/ic_export_options.xml
new file mode 100644
index 00000000000..4a43f3ac0a9
--- /dev/null
+++ b/plugins/configuration/src/main/res/drawable/ic_export_options.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/plugins/configuration/src/main/res/drawable/ic_google_drive.xml b/plugins/configuration/src/main/res/drawable/ic_google_drive.xml
new file mode 100644
index 00000000000..d92d05ad9d2
--- /dev/null
+++ b/plugins/configuration/src/main/res/drawable/ic_google_drive.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/plugins/configuration/src/main/res/layout/dialog_cloud_directory.xml b/plugins/configuration/src/main/res/layout/dialog_cloud_directory.xml
new file mode 100644
index 00000000000..36b398afab3
--- /dev/null
+++ b/plugins/configuration/src/main/res/layout/dialog_cloud_directory.xml
@@ -0,0 +1,197 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/layout/dialog_export_options.xml b/plugins/configuration/src/main/res/layout/dialog_export_options.xml
new file mode 100644
index 00000000000..149dcecc83d
--- /dev/null
+++ b/plugins/configuration/src/main/res/layout/dialog_export_options.xml
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/layout/dialog_import_source.xml b/plugins/configuration/src/main/res/layout/dialog_import_source.xml
new file mode 100644
index 00000000000..1db07485942
--- /dev/null
+++ b/plugins/configuration/src/main/res/layout/dialog_import_source.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/layout/maintenance_fragment.xml b/plugins/configuration/src/main/res/layout/maintenance_fragment.xml
index 0321e6108cf..6433bf446f6 100644
--- a/plugins/configuration/src/main/res/layout/maintenance_fragment.xml
+++ b/plugins/configuration/src/main/res/layout/maintenance_fragment.xml
@@ -133,20 +133,97 @@
app:columnCount="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:layout_row="2" />
+ app:layout_row="2" />
diff --git a/plugins/configuration/src/main/res/layout/maintenance_import_list_activity.xml b/plugins/configuration/src/main/res/layout/maintenance_import_list_activity.xml
index ce7701a5192..172f369dcfe 100644
--- a/plugins/configuration/src/main/res/layout/maintenance_import_list_activity.xml
+++ b/plugins/configuration/src/main/res/layout/maintenance_import_list_activity.xml
@@ -1,4 +1,4 @@
-
+
+
+ android:scrollbars="vertical" />
-
+
-
+
diff --git a/plugins/configuration/src/main/res/values-ar-rSA/strings.xml b/plugins/configuration/src/main/res/values-ar-rSA/strings.xml
index ad2df3c989b..92dfcf23145 100644
--- a/plugins/configuration/src/main/res/values-ar-rSA/strings.xml
+++ b/plugins/configuration/src/main/res/values-ar-rSA/strings.xml
@@ -1,9 +1,15 @@
+
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-bg-rBG/strings.xml b/plugins/configuration/src/main/res/values-bg-rBG/strings.xml
index adbb1ad2edd..66ec334b2f6 100644
--- a/plugins/configuration/src/main/res/values-bg-rBG/strings.xml
+++ b/plugins/configuration/src/main/res/values-bg-rBG/strings.xml
@@ -44,6 +44,7 @@
Избор на данниКачване на статистики във FabricИдентификация (имейл, Фейсбук или Дискорд и др.)
+
ИсканеAPS режимГрешка искане за разрешения
@@ -153,4 +154,9 @@
КриптиранеНов форматНепознат формат
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-ca-rES/strings.xml b/plugins/configuration/src/main/res/values-ca-rES/strings.xml
index ae312784a4e..7bf1a08cd59 100644
--- a/plugins/configuration/src/main/res/values-ca-rES/strings.xml
+++ b/plugins/configuration/src/main/res/values-ca-rES/strings.xml
@@ -41,6 +41,7 @@
Opcions de dadesEnviar a fabric.ioIdentificació (correu electrònic, FB, nick de Discord, etc.)
+
PeticióMode APSSembla que aquest dispositiu no permet optimitzar la bateria amb llistes blanques, això pot provocar problemes de rendiment.
@@ -134,4 +135,9 @@
Encriptació d\'arxiusFormat nou d\'encriptacióFormat d\'exportació desconegut
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-cs-rCZ/strings.xml b/plugins/configuration/src/main/res/values-cs-rCZ/strings.xml
index c3fc0ffc512..be5bab8d59b 100644
--- a/plugins/configuration/src/main/res/values-cs-rCZ/strings.xml
+++ b/plugins/configuration/src/main/res/values-cs-rCZ/strings.xml
@@ -48,6 +48,14 @@
Automatický export nastaveníPovolení této volby bezpečně uloží vaše heslo do telefonuIdentifikace (e-mail, jméno na FB nebo Discord atd.)
+
+ Nastavení úspěšně exportováno do cloudového úložiště
+ Export do cloudového úložiště se nezdařil
+ Připojení ke cloudovému úložišti se nezdařilo
+ Načítání nastavení z cloudového úložiště, čekejte prosím…
+ Nepodařilo se načíst složky cloudového úložiště
+ Uživatelské záznamy CSV byly úspěšně nahrány do cloudového úložiště
+ Připojení ke cloudovému úložišti se nezdařilo. Chcete se znovu ověřit?PožadavekTyp smyčkyChyba žádosti o oprávnění
@@ -166,4 +174,91 @@
Neznámý formát souboruResetovat výsledky APSChyba při přístupu k souborům. Vyberte adresář AAPS.
+
+ Lokální úložiště
+ Disk Google
+ Vyberte typ úložiště
+ Zálohovat na Disk Google
+ Chyba připojení Disk Google
+ Znovu ověřit
+ Ověření cloudového úložiště proběhlo úspěšně
+ Ověření cloudového úložiště se nezdařilo
+ Chyba ověření cloudového úložiště: %1$s
+ Povolit export do cloudu
+ Chcete povolit export do cloudu? Tímto povolíte volbu „Vše do cloudu“ v nastavení exportu.
+ Toto můžete později změnit v části Export nastavení
+ Chcete-li používat Export nastavení. nejprve nastavte cloudový adresář
+ MÍSTNÍ adresář
+ Cloudový adresář
+ Možnosti exportu
+ Protokol
+ Uživatelská nastavení
+ Exportovat uživatelské záznamy do Excelu (CSV)
+ E-mail
+ Lokální úložiště
+ Cloudové úložiště
+ Vše do cloudu
+ Exportovat protokoly do cloudu
+ Exportovat uživatelské záznamy do cloudu (CSV)
+ Exportovat uživatelské záznamy do místního úložiště (CSV)
+ Exportovat nastavení (Místní)
+ Exportovat nastavení (Cloud)
+ Exportovat nastavení (Místní+Cloud)
+ Importovat nastavení (Místní)
+ Importovat nastavení (Cloud)
+ Importovat nastavení (Místní+Cloud)
+
+ Vybrat zdroj importu
+ Importovat z místního úložiště
+ Importovat z cloudového úložiště
+ Importovat nastavení z úložiště zařízení
+ Importovat nastavení z cloudového úložiště
+ Zobrazuji %1$d z %2$d souborů
+ Zobrazuji všechny soubory: %1$d
+ Načíst další
+ Načíst dalších %1$d (načteno %2$d)
+ Načítání…
+ Načítání %1$d z %2$d…
+ Načítání %1$s (%2$d/%3$d)…
+ Protokoly byly úspěšně nahrány do cloudového úložiště
+ Nepodařilo se nahrát protokoly do cloudového úložiště
+ Při nahrávání protokolů do cloudového úložiště došlo k chybě
+ Nepodařilo se nahrát uživatelské záznamy CSV do cloudového úložiště
+ Při nahrávání CSV do cloudového úložiště došlo k chybě
+ Možnosti exportu byly aktualizovány
+ V cloudovém úložišti nebyly nalezeny žádné soubory nastavení
+ Vymazat nastavení
+ Vymazat nastavení cloudu
+ Tato volba přepne na místní úložiště a vymaže udělená oprávnění. Chcete pokračovat?
+ Nahrávání do cloudu…
+ Cloudový adresář: %1$s
+ Byl vybrán chybný adresář
+ Místo kořenového adresáře AAPS jste vybrali podadresář „%1$s“. Vyberte prosím hlavní adresář AAPS. Podadresáře jsou automaticky vytvořeny a spravovány aplikací.
+
+ Nelze aktualizovat přístupový token Disku Google
+ Nelze aktualizovat přístupový token Disku Google: %1$s
+ Test připojení Disku Google se nezdařil
+ Nelze se připojit k Disku Google: %1$s
+ Nepodařilo se načíst složky Disku Google
+ Chyba při načítání složek: %1$s
+ Nahrání proběhlo úspěšně, ale nevrátilo žádné ID
+ Ověření nahrávání se nezdařilo
+ Nahrávání se nezdařilo: %1$s
+ Chyba při nahrávání souboru: %1$s
+ Nelze vytvořit cílovou složku nebo k ní získat přístup: %1$s
+ Nepodařilo se načíst soubory s nastavením
+ Chyba při načítání souborů nastavení: %1$s
+ Nepodařilo se stáhnout soubor
+ Chyba při stahování souboru: %1$s
+
+ Oprávnění %1$s
+ Ve vašem prohlížeči byla otevřena stránka pro udělení oprávnění %1$s .\n\nProsím dokončete udělení oprávnění a poté se vraťte do této aplikace.\n\nToto dialogové okno se automaticky zavře po udělení oprávnění.
+ Nepodařilo se zahájit udělení oprávnění
+ Udělení oprávnění zrušeno
+ Vypršel časový limit pro udělení oprávnění, zkuste to prosím znovu
+ Platnost oprávnění cloudového úložiště vypršela nebo je oprávnění neplatné. Prosím proveďte udělení oprávnění znovu.
+
+ Stav oprávnění
+ Oprávnění pro Disk Google uděleno
+ Prosím vymažte nastavení a znovu udělte oprávnění pro Disk Google
diff --git a/plugins/configuration/src/main/res/values-da-rDK/strings.xml b/plugins/configuration/src/main/res/values-da-rDK/strings.xml
index c14baf421dc..cbd7b4306e9 100644
--- a/plugins/configuration/src/main/res/values-da-rDK/strings.xml
+++ b/plugins/configuration/src/main/res/values-da-rDK/strings.xml
@@ -44,6 +44,7 @@
Valg Af DataFabric UploadIdentifikation (e-mail, FB eller Discord alias osv.)
+
AnmodAPS TilstandFejl under forespørgsel af tilladelser
@@ -154,4 +155,9 @@
FilkrypteringNyt krypteret formatUkendt eksportformat
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-de-rDE/strings.xml b/plugins/configuration/src/main/res/values-de-rDE/strings.xml
index aed160ea666..1061e449d90 100644
--- a/plugins/configuration/src/main/res/values-de-rDE/strings.xml
+++ b/plugins/configuration/src/main/res/values-de-rDE/strings.xml
@@ -44,6 +44,7 @@
DatenübermittlungFabric-UploadIdentifikation (E-Mail, Facebook oder Discord Nickname)
+
AnfordernAPS-ModusFehler beim Anfordern der Erlaubnis
@@ -153,4 +154,9 @@
DateiverschlüsselungNeues verschlüsseltes FormatUnbekanntes Export-Format
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-el-rGR/strings.xml b/plugins/configuration/src/main/res/values-el-rGR/strings.xml
index 7d34c8e4200..dbc6b6d2d68 100644
--- a/plugins/configuration/src/main/res/values-el-rGR/strings.xml
+++ b/plugins/configuration/src/main/res/values-el-rGR/strings.xml
@@ -44,6 +44,7 @@
Επιλογές δεδομένωνΑποστολή δεδομένων στο εργοστάσιοΤαυτότητα (email, FB ή Discord κλπ)
+
ΑίτημαΛειτουργία APSΣφάλμα στην ερώτηση για δικαιώματα
@@ -153,4 +154,9 @@
Κρυπτογράφηση αρχείωνΝέα κρυπτογραφημένη μορφήΆγνωστη μορφή εξαγωγής
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-es-rES/strings.xml b/plugins/configuration/src/main/res/values-es-rES/strings.xml
index 80debda8e25..279bb66b801 100644
--- a/plugins/configuration/src/main/res/values-es-rES/strings.xml
+++ b/plugins/configuration/src/main/res/values-es-rES/strings.xml
@@ -48,6 +48,14 @@
Exportación de ajustes no atendidaHabilitar esto almacenará tu contraseña de forma segura en tu teléfonoIdentificación (correo electrónico, FB, nick de Discord, etc.)
+
+ Ajustes exportados correctamente al almacenamiento en la nube
+ Error al exportar al almacenamiento en la nube
+ Error de conexión con el almacenamiento en la nube
+ Cargando ajustes desde el almacenamiento en la nube, por favor espera...
+ Error al cargar las carpetas del almacenamiento en la nube
+ El CSV de entradas de usuario se ha subido correctamente al almacenamiento en la nube
+ Error de conexión con el almacenamiento en la nube. ¿Te gustaría volver a autenticarte?SolicitarModo APSError al solicitar los permisos
@@ -166,4 +174,91 @@
Formato de exportación desconocidoRestablecer resultados de APSError al acceder al sistema de archivos. Selecciona el directorio de AAPS correctamente.
+
+ Almacenamiento local
+ Google Drive
+ Selecciona el tipo de almacenamiento
+ Copia de seguridad en Google Drive
+ Error de conexión con Google Drive
+ Volver a autenticarse
+ Autenticación en el almacenamiento en la nube correcta
+ Error de autenticación en el almacenamiento en la nube
+ Error de autenticación en el almacenamiento en la nube: %1$s
+ Activar exportación a la nube
+ ¿Quieres activar la exportación a la nube? Esto habilitará la opción \"Todo en la nube\" en los ajustes de exportación.
+ Puedes modificar esto más tarde en los ajustes de exportación
+ Configura primero el directorio en la nube para usar los ajustes de exportación
+ Directorio local
+ Directorio de nube
+ Opciones de exportación
+ Registro
+ Ajustes de usuario
+ Exportar entradas de usuario a Excel (CSV)
+ Correo
+ Almacenamiento local
+ Almacenamiento en la nube
+ Todo en la nube
+ Exportar registros a la nube
+ Exportar entradas de usuario a la nube (CSV)
+ Exportar entradas de usuario al dispositivo local (CSV)
+ Exportar ajustes (Local)
+ Exportar ajustes (Nube)
+ Exportar ajustes (Local+Nube)
+ Importar ajustes (Local)
+ Importar ajustes (Nube)
+ Ajustes de importación (Local/Nube)
+
+ Seleccionar origen de importación
+ Importar desde almacenamiento local
+ Importar desde almacenamiento en la nube
+ Importar ajustes desde el dispositivo
+ Importar ajustes desde la nube
+ Mostrando %1$d de %2$d archivos
+ Mostrando los %1$d archivos
+ Cargar más
+ Cargar los siguientes %1$d (cargados %2$d)
+ Cargando…
+ Cargando %1$d de %2$d…
+ Cargando %1$s (%2$d/%3$d)…
+ Registros subidos con éxito al almacenamiento en la nube
+ Error al subir los registros al almacenamiento en la nube
+ Se produjo un error al subir los registros al almacenamiento en la nube
+ Error al subir el CSV de entradas de usuario al almacenamiento en la nube
+ Se produjo un error al subir el CSV a la nube
+ Opciones de exportación actualizadas
+ No se encontraron archivos de configuración en la nube
+ Limpiar configuración
+ Limpiar configuración de la nube
+ Se cambiará al almacenamiento local y se borrará la autorización. ¿Continuar?
+ Subiendo a la nube...
+ Directorio en la nube: %1$s
+ Directorio seleccionado incorrecto
+ Has seleccionado el subdirectorio \"%1$s\" en lugar del directorio raíz de AAPS. Por favor, selecciona el directorio principal de AAPS. La aplicación creará y gestionará los subdirectorios automáticamente.
+
+ No se pudo actualizar el token de acceso de Google Drive
+ No se pudo actualizar el token de acceso de Google Drive: %1$s
+ Error en la prueba de conexión con Google Drive
+ No se pudo conectar con Google Drive: %1$s
+ Error al listar las carpetas de Google Drive
+ Error al listar las carpetas: %1$s
+ Subida finalizada con éxito, pero no se devolvió ningún ID
+ Error en la verificación de la subida
+ Error de subida: %1$s
+ Error al subir el archivo: %1$s
+ No se puede crear o acceder a la carpeta de destino: %1$s
+ Error al listar los archivos de configuración
+ Error al listar los archivos de configuración: %1$s
+ Error al descargar el archivo
+ Error al descargar el archivo: %1$s
+
+ %1$s Autorización
+ Se ha abierto la página de autorización de %1$s en tu navegador.\n\nPor favor, completa la autorización y vuelve a esta aplicación.\n\nEste cuadro de diálogo se cerrará automáticamente una vez finalizada la autorización.
+ Error al iniciar la autorización
+ Autorización cancelada
+ La autorización ha caducado, inténtalo de nuevo
+ La autorización del almacenamiento en la nube ha caducado o no es válida. Por favor, vuelve a autorizarla.
+
+ Estado de la autorización
+ Google Drive autorizado
+ Borra los ajustes y vuelve a autorizar Google Drive
diff --git a/plugins/configuration/src/main/res/values-fr-rFR/strings.xml b/plugins/configuration/src/main/res/values-fr-rFR/strings.xml
index 3cad20f3b6e..feeebe003f2 100644
--- a/plugins/configuration/src/main/res/values-fr-rFR/strings.xml
+++ b/plugins/configuration/src/main/res/values-fr-rFR/strings.xml
@@ -49,6 +49,7 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
Export des paramètres sans surveillanceL\'activation permettra de stocker votre mot de passe en toute sécurité sur votre téléphoneIdentification (email, FB ou pseudo dans Discord, etc)
+
DemandeMode APSErreur lors de la demande des autorisations
@@ -167,4 +168,9 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S
Format d\'export inconnuRéinitialiser les résultats d\'APSErreur lors de l’accès au fichier. Sélectionnez le répertoire AAPS correctement.
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-hr-rHR/strings.xml b/plugins/configuration/src/main/res/values-hr-rHR/strings.xml
index f0cbe9ac8a8..41a2c1b78db 100644
--- a/plugins/configuration/src/main/res/values-hr-rHR/strings.xml
+++ b/plugins/configuration/src/main/res/values-hr-rHR/strings.xml
@@ -8,6 +8,7 @@
Aplikaciji je potrebno dopuštenje za pohranu kako bi mogla pohranjivati datoteke dnevnika i izvoziti postavke%1$s potrebno stavljanje na popis dopuštenih za optimizaciju baterije za pravilan radProfil
+
ZahtjevPogreška pri traženju dopuštenjaČini se da ovaj uređaj ne podržava stavljanje na popis dopuštenih za optimizaciju baterije - mogli biste imati problema s performansama.
@@ -59,4 +60,9 @@
Algoritam šifriranja nije podržan ili nije naveden!
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-hu-rHU/strings.xml b/plugins/configuration/src/main/res/values-hu-rHU/strings.xml
index 3ca15016b8d..7d44b5c034e 100644
--- a/plugins/configuration/src/main/res/values-hu-rHU/strings.xml
+++ b/plugins/configuration/src/main/res/values-hu-rHU/strings.xml
@@ -13,6 +13,7 @@
Beteg neveProfilRileyLink állapot:
+
PumpaProfil
@@ -36,4 +37,9 @@
FájltitkosításÚj titkosított formátomIsmeretlen export formátum
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-it-rIT/strings.xml b/plugins/configuration/src/main/res/values-it-rIT/strings.xml
index 3ca81c1c34f..ac854f7abfc 100644
--- a/plugins/configuration/src/main/res/values-it-rIT/strings.xml
+++ b/plugins/configuration/src/main/res/values-it-rIT/strings.xml
@@ -36,6 +36,7 @@
Cambia profiloSalta configurazione guidataIl plugin di sensibilità è usato per il rilevamento della sensibilità all\'insulina e il calcolo di COB. Per ulteriori informazioni visita:
+ https://wiki.aaps.app/en/latest/DailyLifeWithAaps/SensitivityDetectionAndCob.htmlSeleziona uno degli algoritmi disponibili. Sono ordinati dal più vecchio al più recente. L\'algoritmo più recente è solitamente più potente e più aggressivo. Pertanto, se sei un nuovo utente, probabilmente dovresti iniziare con AMA e non con l\'ultimo. Non dimenticare di leggere la documentazione di OpenAPS e di configurarlo prima dell\'uso.Configura il RileyLink di seguito. Dopo aver selezionato un RileyLink, sarà possibile continuare la configurazione una volta che lo stato del RileyLink sarà \"Connesso\". Questo potrebbe richiedere un minuto.\nNota: Puoi continuare la configurazione una volta che il micro è stato configurato.\n
@@ -47,6 +48,14 @@
Esportazione Impostazioni Non presidiataAbilitando questa opzione memorizzerai in modo sicuro la tua password sul tuo telefonoIdentificazione (email, nick Discord o FB, etc)
+
+ Impostazioni esportate con successo su cloud storage
+ Esportazione nell\'archivio cloud non riuscita
+ Connessione all\'archiviazione cloud fallita
+ Caricamento impostazioni dall\'archivio cloud, attendere…
+ Caricamento delle cartelle di archiviazione cloud non riuscito
+ Voci utente CSV caricate con successo su cloud storage
+ Connessione all\'archiviazione cloud non riuscita. Vuoi autenticarti?RichiestaModalità APSErrore nel richiedere le autorizzazioni
@@ -165,4 +174,91 @@
Formato esportazione sconosciutoResetta i risultati di APSErrore nell\'accedere al filesystem. Selezionare correttamente la directory AAPS.
+
+ Archiviazione locale
+ Google Drive
+ Seleziona il Tipo di Storage
+ Backup su Google Drive
+ Errore di connessione Google Drive
+ Ri-autenticazione
+ Autenticazione archiviazione cloud riuscita
+ Connessione all\'archiviazione cloud fallita
+ Errore di autenticazione archiviazione cloud: %1$s
+ Abilita Esportazione Cloud
+ Vuoi abilitare l\'esportazione in cloud? Questo attiverà l\'opzione \"All Cloud\" nelle impostazioni di esportazione.
+ È possibile modificare questo in seguito nelle impostazioni di esportazione
+ Si prega di impostare la directory Cloud prima di utilizzare le impostazioni di esportazione
+ Directory LOCALE
+ Directory Cloud
+ Opzioni di esportazione
+ Log
+ Impostazioni Utente
+ Esporta voci utente in Excel (csv)
+ Email
+ Archiviazione locale
+ Archiviazione cloud
+ Tutto Il Cloud
+ Esporta log su Cloud
+ Esporta in cloud le voci utente (csv)
+ Esporta in locale le voci utente (csv)
+ Esporta impostazioni (locale)
+ Esporta impostazioni (Cloud)
+ Impostazioni di esportazione (Local+Cloud)
+ Importa impostazioni (locale)
+ Importa impostazioni (Cloud)
+ Importa impostazioni (Local/Cloud)
+
+ Seleziona Sorgente Importazione
+ Importa da Archivio Locale
+ Importa dall\'archivio cloud
+ Importa impostazioni dalla memoria del dispositivo
+ Importa impostazioni dal cloud storage
+ Mostra %1$d di %2$d files
+ Mostra tutti i %1$d files
+ Carica Altre
+ Carica il prossimo %1$d (caricato %2$d)
+ Caricamento…
+ Caricamento di %1$d di %2$d…
+ Caricamento %1$s (%2$d/%3$d)…
+ Log caricati con successo nell\'archivio cloud
+ Impossibile caricare i log nella memoria cloud
+ Si è verificato un errore durante il caricamento dei log nell\'archivio cloud
+ Impossibile caricare le Voci dell\'Utente CSV nell\'archivio cloud
+ Si è verificato un errore durante il caricamento del CSV nel cloud
+ Opzioni di esportazione aggiornate
+ Nessun file di impostazioni trovato nell\'archivio cloud
+ Cancella impostazioni
+ Cancella Impostazioni Cloud
+ Questo passerà alla memoria locale cancellerà l\'autenticazione. Continuare?
+ Caricamento nel cloud...
+ Directory cloud: %1$s
+ Directory Selezionata Errata
+ Hai selezionato la sottodirectory \"%1$s\" invece della directory AAPS principale. Seleziona la directory AAPS principale. L\'applicazione creerà e gestirà automaticamente le sottodirectory.
+
+ Impossibile aggiornare il token di accesso a Google Drive
+ Impossibile aggiornare il token di accesso a Google Drive: %1$s
+ Test di connessione Google Drive non riuscito
+ Impossibile connettersi a Google Drive: %1$s
+ Elenco delle cartelle Google Drive non riuscito
+ Errore nell\'elencare le cartelle: %1$s
+ Caricamento riuscito ma nessun id restituito
+ Verifica del caricamento fallita
+ Caricamento fallito: %1$s
+ Errore nel caricare il file: %1$s
+ Impossibile creare o accedere alla cartella di destinazione: %1$s
+ Impossibile elencare i file delle impostazioni
+ Errore nell\'elencare i file delle impostazioni: %1$s
+ Download del file non riuscito
+ Errore nello scaricare il file: %1$s
+
+ Autorizzazione %1$s
+ La pagina di autorizzazione %1$s è stata aperta nel tuo browser.\n\nSi prega di completare l\'autorizzazione, quindi tornare a questa app.\n\nQuesta finestra si chiuderà automaticamente una volta completata l\'autorizzazione.
+ Impossibile avviare l\'autorizzazione
+ Autorizzazione cancellata
+ Autorizzazione scaduta, riprova
+ Autorizzazione all\'archiviazione cloud scaduta o non valida. Per favore ri-autorizza.
+
+ Stato Autorizzazione
+ Google Drive Autorizzato
+ Si prega di cancellare le impostazioni e ri-autorizzare Google Drive
diff --git a/plugins/configuration/src/main/res/values-iw-rIL/strings.xml b/plugins/configuration/src/main/res/values-iw-rIL/strings.xml
index 9558f61fafd..e9a15713123 100644
--- a/plugins/configuration/src/main/res/values-iw-rIL/strings.xml
+++ b/plugins/configuration/src/main/res/values-iw-rIL/strings.xml
@@ -44,6 +44,7 @@
אפשרויות נתוניםהעלאה ל-Fabricאמצעי זיהוי (מייל, פייסבוק או דיסקורד וכו\')
+
בקשהמצב APSשגיאה בעת בקשת הרשאות
@@ -160,4 +161,10 @@
פורמט הצפנה חדשפורמט ייצוא לא ידועשגיאה בגישה למערכת הקבצים. אנא בחרו את תיקיית AAPS כראוי.
+
+ אפשרויות ייצוא
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-ko-rKR/strings.xml b/plugins/configuration/src/main/res/values-ko-rKR/strings.xml
index 27d8473652c..f8b5d1cb91a 100644
--- a/plugins/configuration/src/main/res/values-ko-rKR/strings.xml
+++ b/plugins/configuration/src/main/res/values-ko-rKR/strings.xml
@@ -44,6 +44,7 @@
데이터선택Fabric 업로드신원 증명 (이메일, FB, 또는 Discord nick 등)
+
요청APS 모드사용 권한을 묻는 중 오류가 발생했습니다
@@ -153,4 +154,9 @@
파일 암호화암호화된 새로운 형식알려지지 않은 내보내기 형식
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-lt-rLT/strings.xml b/plugins/configuration/src/main/res/values-lt-rLT/strings.xml
index 2f1c11d41d1..d532881dedf 100644
--- a/plugins/configuration/src/main/res/values-lt-rLT/strings.xml
+++ b/plugins/configuration/src/main/res/values-lt-rLT/strings.xml
@@ -48,6 +48,7 @@
Automatinis nustatymų eksportavimasĮjungus šią parinktį, jūsų slaptažodis bus saugiai saugomas jūsų telefoneIdentifikacija (el. paštas, FB, Discord slapyvardis ar kt.)
+
UžklausaDKS režimasLeidimo užklausos klaida
@@ -166,4 +167,9 @@
Nežinomas eksporto formatasIš naujo nustatyti APS rezultatusKlaida pasiekiant failų sistemą. Tinkamai pasirinkite AAPS katalogą.
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-nb-rNO/strings.xml b/plugins/configuration/src/main/res/values-nb-rNO/strings.xml
index 440f9013d2b..8d35d892818 100644
--- a/plugins/configuration/src/main/res/values-nb-rNO/strings.xml
+++ b/plugins/configuration/src/main/res/values-nb-rNO/strings.xml
@@ -48,6 +48,14 @@
Uovervåket eksport av innstillingerAktivering av dette vil lagre ditt passord sikkert på din telefonIdentifikasjon (e-post, Facebook eller Discord-nick osv.)
+
+ Innstillinger ble eksportert til skylagring
+ Kunne ikke eksportere til skylagring
+ Tilkobling til skylagring mislyktes
+ Laster inn innstillinger fra skylagring, vennligst vent…
+ Kunne ikke laste mapper fra skylagring
+ CSV med brukeroppføringer ble lastet opp til skylagring
+ Tilkobling til skylagring mislyktes. Vil du godkjenne på nytt?ForespørselAPS modusFeil under spørring etter tillatelser
@@ -166,4 +174,91 @@
Ukjent eksportformatTilbakestill APS-resultaterFeil ved tilgang til filsystem. Velg AAPS-mappe riktig.
+
+ Lokal lagring
+ Google Drive
+ Velg lagringstype
+ Sikkerhetskopier til Google Drive
+ Feil ved tilkobling til Google Drive
+ Godkjenn på nytt
+ Autentisering av skylagring vellykket
+ Autentisering av skylagring mislyktes
+ Feil ved autentisering av skylagring: %1$s
+ Aktiver sky-eksport
+ Vil du aktivere eksport til skyen? Dette vil aktivere «Kun sky»-valget i Eksportinnstillinger.
+ Du kan endre dette senere i Eksportinnstillinger
+ Sett opp skymappe først for å bruke Eksportinnstillinger
+ Lokal mappe
+ Skymappe
+ Eksportalternativer
+ Logg
+ Brukerinnstillinger
+ Eksporter brukeroppføringer til Excel (CSV)
+ E-post
+ Lokal lagring
+ Skylagring
+ Kun sky
+ Eksporter logger til skyen
+ Eksporter brukeroppføringer til skyen (CSV)
+ Eksporter brukeroppføringer lokalt (CSV)
+ Eksporter innstillinger (lokalt)
+ Eksporter innstillinger (sky)
+ Eksporter innstillinger (lokalt + sky)
+ Importer innstillinger (lokalt)
+ Importer innstillinger (sky)
+ Importer innstillinger (lokalt/sky)
+
+ Velg importkilde
+ Importer fra lokal lagring
+ Importer fra skylagring
+ Importer innstillinger fra enhetens lagring
+ Importer innstillinger fra skylagring
+ Viser %1$d av %2$d filer
+ Viser alle %1$d filer
+ Last inn flere
+ Last inn neste %1$d (lastet %2$d)
+ Laster…
+ Laster %1$d av %2$d…
+ Laster %1$s (%2$d/%3$d)…
+ Logger ble lastet opp til skylagring
+ Kunne ikke laste opp logger til skylagring
+ Det oppstod en feil ved opplasting av logger til skylagring
+ Kunne ikke laste opp CSV med brukeroppføringer til skylagring
+ Det oppstod en feil ved opplasting av CSV til skyen
+ Eksportalternativer oppdatert
+ Ingen innstillingsfiler funnet i skylagring
+ Tøm innstillinger
+ Tøm skyinnstillinger
+ Dette vil bytte til lokal lagring og fjerne autorisasjon. Fortsette?
+ Laster opp til skyen...
+ Skymappe: %1$s
+ Feil mappe valgt
+ Du har valgt undermappen «%1$s» i stedet for rotmappen for AAPS. Velg overordnet AAPS-mappe. Appen vil automatisk opprette og administrere undermapper.
+
+ Kunne ikke oppdatere Google Drive-tilgangstoken
+ Kunne ikke oppdatere Google Drive-tilgangstoken: %1$s
+ Test av Google Drive-tilkobling mislyktes
+ Kunne ikke koble til Google Drive: %1$s
+ Kunne ikke liste mapper i Google Drive
+ Feil ved henting av mapper: %1$s
+ Opplasting fullført, men ingen ID returnert
+ Verifisering av opplasting mislyktes
+ Opplasting mislyktes: %1$s
+ Feil ved opplasting av fil: %1$s
+ Kan ikke opprette eller få tilgang til målmappe: %1$s
+ Kunne ikke liste opp innstillingsfilene
+ Feil ved henting av innstillingsfiler: %1$s
+ Kunne ikke laste ned fil
+ Feil ved nedlasting av fil: %1$s
+
+ %1$s Autorisering
+ %1$s autorisering er åpnet i nettleseren din.\n\nFullfør autoriseringen og gå deretter tilbake til appen.\n\nDenne dialogen lukkes automatisk når autoriseringen er fullført.
+ Kunne ikke starte autorisering
+ Autorisering avbrutt
+ Autorisering tidsavbrutt, prøv igjen
+ Autorisasjonen for skylagring er utløpt eller ugyldig. Godkjenn på nytt.
+
+ Autorisasjonsstatus
+ Google Drive autorisert
+ Tøm innstillinger og autoriser Google Drive på nytt
diff --git a/plugins/configuration/src/main/res/values-night/colors.xml b/plugins/configuration/src/main/res/values-night/colors.xml
new file mode 100644
index 00000000000..e40008c5704
--- /dev/null
+++ b/plugins/configuration/src/main/res/values-night/colors.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ #4ADE80
+
+ #FBBF24
+
diff --git a/plugins/configuration/src/main/res/values-nl-rNL/strings.xml b/plugins/configuration/src/main/res/values-nl-rNL/strings.xml
index d6c85db49d2..6d62862fb92 100644
--- a/plugins/configuration/src/main/res/values-nl-rNL/strings.xml
+++ b/plugins/configuration/src/main/res/values-nl-rNL/strings.xml
@@ -48,6 +48,14 @@
Niet interactief instellingen exporterenMet het activeren van deze optie wordt uw wachtwoord veilig opgeslagen op uw telefoonIdentificatie (e-mail, FB, Discord e. d.)
+
+ Instellingen succesvol geëxporteerd naar cloudopslag
+ Exporteren naar cloudopslag is mislukt
+ Verbinding maken met cloud opslag mislukt
+ Instellingen laden uit cloud opslag, even geduld…
+ Laden van cloud opslag mappen mislukt
+ Gebruiker invoer CSV succesvol geüpload naar cloud opslag
+ Verbinding maken met cloud opslag mislukt. Wil je je opnieuw authenticeren?VerzoekAPS ModeFout bij het vragen van toestemming
@@ -166,4 +174,54 @@
Onbekende export indelingReset APS resultatenFout bij toegang tot het bestandssysteem. Selecteer de juiste AAPS map.
+
+ Lokale opslag
+ Google Drive
+ Selecteer een opslagtype
+ Back-up maken naar Google Drive
+ Google Drive verbindingsfout
+ Opnieuw authenticeren
+ Authenticatie cloudopslag gelukt
+ Authenticatie met cloudopslag mislukt
+ Authenticatie fout voor cloud opslag: %1$s
+ Cloud export inschakelen
+ Wilt u cloud export inschakelen? Dit zal de \"Alle Cloud\" optie inschakelen voor de Export instellingen.
+ U kunt dit later wijzigen in de exportinstellingen
+ Stel de cloud storage directory eerst in om de export Instellingen te gebruiken
+ LOKALE map
+ Cloud map
+ Export opties
+ Logbestanden
+ Gebruikersinstellingen
+ Exporteer gebruikersgegevens naar Excel (CSV)
+ E-mail
+ Lokale opslag
+ Cloud opslag
+ Alles cloud
+ Logbestanden exporteren naar cloud opslag
+ Exporteer gebruikersgegevens naar cloud opslag (CSV)
+ Exporteer gebruikersgegevens naar lokale opslag (CSV)
+ Exporteer instellingen (lokaal)
+ Exporteer instellingen (cloud)
+ Exporteer instellingen (lokaal+cloud)
+ Importeer instellingen (lokaal)
+ Importeer instellingen (cloud)
+ Importeer instellingen (lokaal/cloud)
+
+ Selecteer importbron
+ Importeren uit lokale opslag
+ Importeren uit cloud opslag
+ Instellingen importeren uit apparaatopslag
+ Instellingen importeren uit cloud opslag
+ Toont %1$d van %2$d bestanden
+ Alle %1$d bestanden worden getoond
+ Meer laden
+ Laden volgende %1$d (geladen %2$d)
+ Laden…
+ Laden %1$d van %2$d…
+ Verkeerde map geselecteerd
+ U heeft de \"%1$s\" submap geselecteerd in plaats van de AAPS hoofdmap. Selecteer de bovenliggende AAPS map. De app zal automatisch submappen aanmaken en beheren.
+
+
+
diff --git a/plugins/configuration/src/main/res/values-pl-rPL/strings.xml b/plugins/configuration/src/main/res/values-pl-rPL/strings.xml
index 28d83c20b8f..6e9cbee539a 100644
--- a/plugins/configuration/src/main/res/values-pl-rPL/strings.xml
+++ b/plugins/configuration/src/main/res/values-pl-rPL/strings.xml
@@ -48,6 +48,7 @@
Automatyczny Eksport UstawieńWłączenie tej opcji spowoduje, że twoje hasło zostanie bezpieczne zapisane na telefonieIdentyfikator (email, nick na FB lub Discordzie itp.)
+
ŻądanieTryb APSWystąpił błąd podczas żądania uprawnień
@@ -79,6 +80,8 @@
Uwaga: Jeśli aktywujesz połączenie z pompą inną niż wirtualna, AAPS skopiuje ustawienia bazy do profilu pompy, zastępując istniejące ustawienia w niej zapisane. Upewnij się, że ustawienia bazy w AAPS są poprawne. Jeśli nie jesteś pewien lub nie chcesz nadpisywać podstawowych ustawień pompy, naciśnij przycisk anuluj i połącz ponownie w innym czasie.otwórz ustawieniaWersja AAPSClient nie jest zgodna z wersją AAPS. Proszę zaktualizować.
+ Rozwiń kategorię
+ Zwiń kategorięUstawieniaZostaniesz poproszony o hasło główne, które będzie użyte do szyfrowania wyeksportowanych ustawień.
@@ -164,4 +167,9 @@
Nieznany format eksportuZresetuj wyniki APSBłąd dostępu do systemu plików. Wybierz prawidłowo katalog AAPS.
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-pt-rBR/strings.xml b/plugins/configuration/src/main/res/values-pt-rBR/strings.xml
index 6c8f1ce7a33..57af4f6df74 100644
--- a/plugins/configuration/src/main/res/values-pt-rBR/strings.xml
+++ b/plugins/configuration/src/main/res/values-pt-rBR/strings.xml
@@ -44,6 +44,7 @@
Escolha de DadosEnvio FabricIdentificação (e-mail, apelido FB ou Discord, etc)
+
PedidoModo APSErro alterando permissões
@@ -153,4 +154,9 @@
Criptografia do arquivoNovo formato de encriptaçãoFormato de exportação desconhecido
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-pt-rPT/strings.xml b/plugins/configuration/src/main/res/values-pt-rPT/strings.xml
index 97025b46f35..73f3a6b6bcd 100644
--- a/plugins/configuration/src/main/res/values-pt-rPT/strings.xml
+++ b/plugins/configuration/src/main/res/values-pt-rPT/strings.xml
@@ -44,6 +44,7 @@
Escolha de DadosEnvio FabricIdentificação (e-mail, nick FB ou Discord, etc)
+
PedidoModo APSErro ao pedir permissões
@@ -153,4 +154,9 @@
Encriptação do FicheiroNovo formato de encriptaçãoFormato de exportação desconhecido
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-ro-rRO/strings.xml b/plugins/configuration/src/main/res/values-ro-rRO/strings.xml
index f1b16e24619..c942f1bb858 100644
--- a/plugins/configuration/src/main/res/values-ro-rRO/strings.xml
+++ b/plugins/configuration/src/main/res/values-ro-rRO/strings.xml
@@ -44,6 +44,7 @@
Alegeri dateÎncărcare \"fabric\"Identificare (email, FB sau Discord etc)
+
CerințăMod APSEroare în solicitarea permisiunilor
@@ -153,4 +154,9 @@
Criptare fișierFormat nou criptatFormat necunoscut pentru export
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-ru-rRU/strings.xml b/plugins/configuration/src/main/res/values-ru-rRU/strings.xml
index 4096d558ea2..2cc38af68f3 100644
--- a/plugins/configuration/src/main/res/values-ru-rRU/strings.xml
+++ b/plugins/configuration/src/main/res/values-ru-rRU/strings.xml
@@ -48,6 +48,14 @@
Автоматический экспорт настроекВключение данного параметра безопасно сохранит ваш пароль на этом телефонеИдентификация (электронная почта, ник в Facebook или Discord и т. п)
+
+ Настройки успешно экспортированы в облачное хранилище
+ Не удалось экспортировать в облачное хранилище
+ Не удалось подключиться к облачному хранилищу
+ Загрузка настроек из облачного хранилища, подождите…
+ Ошибка загрузки папок из облака
+ Записи пользователя успешно загружены в облачное хранилище в формате CSV
+ Не удалось подключиться к облачному хранилищу. Хотите повторно авторизоваться?ЗапросРежим APSОшибка при запросе разрешения
@@ -166,4 +174,91 @@
Неизвестный формат экспортаСбросить результаты APSОшибка доступа к файловой системе. Выберите каталог AAPS правильно.
+
+ Локальное Хранилище
+ Диск Google
+ Выберите тип хранилища
+ Резервное копирование на Google Диск
+ Ошибка подключения к Google Диску
+ Повторить аутентификацию
+ Аутентификация в облаке прошла успешно
+ Ошибка аутентификации в облачном хранилище
+ Ошибка аутентификации в облачном хранилище: %1$s
+ Включить экспорт из облака
+ Вы хотите включить экспорт в облако? Это включит опцию \"Все в облако\" в настройках экспорта.
+ Вы можете изменить это позже в настройках экспорта
+ Настройте облачную директорию для экспорта
+ Локальная директория
+ Облачная директория
+ Опции экспорта
+ Журнал
+ Настройки пользователя
+ Экспорт пользовательских записей в Excel (csv)
+ Электронная почта
+ Локальное Хранилище
+ Облачное хранилище
+ Все в Облако
+ Экспортировать журналы в Облако
+ Экспортировать записи пользователя в Облако (csv)
+ Экспорт пользовательских записей в локальное хранилище (csv)
+ Экспорт настроек (локально)
+ Экспорт настроек (в Облако)
+ Экспорт настроек (Локально + Облако)
+ Импорт настроек (локальный)
+ Импорт настроек (из Облака)
+ Импорт настроек (Локально + Облако)
+
+ Выберите источник для импорта
+ Импорт из локального хранилища
+ Импорт из облачного хранилища
+ Импорт настроек из памяти устройства
+ Импорт настроек из облачного хранилища
+ Показаны %1$d из %2$d файлов
+ Показаны все %1$d файлы
+ Загрузить ещё
+ Загрузить следующий %1$d (загружено %2$d)
+ Загрузка…
+ Загрузка %1$d из %2$d…
+ Загрузка %1$s (%2$d/%3$d)…
+ Журналы успешно загружены в облачное хранилище
+ Не удалось загрузить журналы в облачное хранилище
+ Произошла ошибка при загрузке журналов в облачное хранилище
+ Не удалось загрузить файл CSV пользователя в облачное хранилище
+ Произошла ошибка при загрузке CSV в облако
+ Параметры экспорта обновлены
+ Не найдено файлов настроек в облачном хранилище
+ Очистить настройки
+ Очистить настройки облака
+ Это переключит на локальное хранилище и очистит авторизацию. Продолжить?
+ Загрузка в облако...
+ Облачная директория: %1$s
+ Выбрана неверная директория
+ Вы выбрали поддиректорию \"%1$s\" вместо корневой директории AAPS. Выберите корневой каталог AAPS. Приложение будет автоматически создавать и управлять подкаталогами.
+
+ Не удалось обновить ключ доступа к Google Drive
+ Не удалось обновить ключ доступа Google Drive: %1$s
+ Проверка соединения с Google Drive не состоялась
+ Не удалось подключиться к Google Drive: %1$s
+ Не удалось получить список папок Google Drive
+ Ошибка отображения папок: %1$s
+ Загрузка завершена, но не вернулся идентификатор
+ Ошибка подтверждения загрузки
+ Загрузка не состоялась: %1$s
+ Ошибка загрузки файла: %1$s
+ Невозможно создать или получить доступ к папке назначения: %1$s
+ Не удалось отобразить файлы настроек
+ Ошибка при отображении файлов настроек: %1$s
+ Не удалось скачать файл
+ Ошибка скачивания файла: %1$s
+
+ %1$s Авторизация
+ %1$s страница авторизации была открыта в вашем браузере.\n\nЗавершите авторизацию, а затем вернитесь в это приложение.\n\nЭтот диалог будет автоматически закрываться после завершения авторизации.
+ Не удалось начать авторизацию
+ Авторизация отменена
+ Истекло время авторизации, повторите попытку
+ Срок действия авторизации в облачном хранилище истек или неверен. Повторите авторизацию.
+
+ Статус авторизации
+ Google Drive авторизован
+ Очистите настройки и повторно авторизуйте Google Drive
diff --git a/plugins/configuration/src/main/res/values-sk-rSK/strings.xml b/plugins/configuration/src/main/res/values-sk-rSK/strings.xml
index d8b4756d860..d872ee69f5e 100644
--- a/plugins/configuration/src/main/res/values-sk-rSK/strings.xml
+++ b/plugins/configuration/src/main/res/values-sk-rSK/strings.xml
@@ -48,6 +48,14 @@
Automatický export nastaveníPovolenie tejto voľby bezpečne uloží vaše heslo do telefónuIdentifikácia (E-mail, prezývka FB, alebo Discord atď.)
+
+ Nastavenie úspešne exportované do cloudového úložiska
+ Export do cloudového úložiska zlyhal
+ Pripojenie ku cloudovému úložisku zlyhalo
+ Načítanie nastavení z cloudového úložiska, čakajte prosím…
+ Nepodarilo se načítať zložky cloudového úložiska
+ Užívateľské záznamy CSV boli úspešne nahrané do cloudového úložiska
+ Pripojenie ku cloudovému úložisku zlyhalo. Chcete sa znovu overiť?PožiadavkaAPS módChyba pri žiadosti o oprávnenie
@@ -166,4 +174,91 @@
Neznámy formát exportuResetovať výsledky APSChyba pri prístupe k súborom. Vyberte adresár AAPS.
+
+ Lokálne úložisko
+ Google Disk
+ Vyberte typ úložiska
+ Zálohovať na Google Disk
+ Chyba pripojenia na Google Disk
+ Znovu overiť
+ Overenie cloudového úložiska prebehlo úspešne
+ Overenie cloudového úložiska zlyhalo
+ Chyba overenia cloudového úložiska: %1$s
+ Povoliť export do cloudu
+ Chcete povoliť export do cloudu? Týmto povolíte voľbu „Všetko do cloudu“ v nastaveniach exportu.
+ Toto môžete neskôr zmenit v časti Export nastavení
+ Ak chcete používať Export nastavení, najskôr nastavte adresár cloudu
+ Lokálny adresár
+ Cloudový adresár
+ Nastavenia exportu
+ Log
+ Užívateľské nastavenia
+ Exportovať záznamy užívateľa do Excelu (CSV)
+ E-mail
+ Lokálne úložisko
+ Cloudové úložisko
+ Všetko do cloudu
+ Exportovať logy do cloudu
+ Exportovat záznamy užívateľa do cloudu (CSV)
+ Exportovať užívateľské záznamy do lokálneho úložiska (CSV)
+ Exportovať nastavenia (lokálne)
+ Exportovať nastavenia (Cloud)
+ Exportovať nastavenia (Lokálne+Cloud)
+ Importovať nastavenia (Lokálne)
+ Importovať nastavenia (Cloud)
+ Importovať nastavenia (Lokálne+Cloud)
+
+ Vybrať zdroj importu
+ Importovať z lokálneho úložiska
+ Importovať z cloudového úložiska
+ Importovať nastavenia z úložiska zariadenia
+ Importovať nastavenia z úložiska cloudu
+ Zobrazujem %1$d z %2$d súborov
+ Zobrazujem všetky súbory: %1$d
+ Načítať viac
+ Načítať ďalšie %1$d (načítaných %2$d)
+ Načítavanie…
+ Načítavanie %1$d z %2$d…
+ Načítavanie %1$s (%2$d/%3$d)…
+ Logy boli úspešne nahrané na cloudové úložisko
+ Nahrávanie logov na cloudové úložisko zlyhalo
+ Pri nahrávaní logov na cloudové úložisko došlo k chybe
+ Nahrávanie záznamov užívateľa CSV na cloudové úložisko zlyhalo
+ Pri nahrávaní CSV na cloudové úložisko došlo k chybe
+ Nastavenia exportu boli aktualizované
+ Na cloudovom úložisku neboli nájdené žiadne súbory z nastaveniami
+ Vymazať nastavenia
+ Vymazať nastavenia cloudu
+ Táto voľba prepne na lokálne úložisko a vymaže udelené oprávnenia. Pokračovať?
+ Nahrávanie do cloudu…
+ Adresár Cloudu: %1$s
+ Bol vybratý nesprávny adresár
+ Namiesto koreňového adresára AAPS ste vybrali podadresár „%1$s“. Vyberte prosím hlavný adresár AAPS. Podadresáre sú automaticky vytvorené a spravované aplikáciou.
+
+ Nie je možné aktualizovať prístupový token Google Disku
+ Nie je možné aktualizovať prístupový token Google Disku: %1$s
+ Test pripojenia Google Disku zlyhal
+ Nie je možné pripojiť sa ku Google Disku: %1$s
+ Nepodarilo sa načítať zložky Google Disku
+ Chyba pri načítavaní zložiek: %1$s
+ Nahrávanie prebehlo úspešne, ale nevrátilo žiadne ID
+ Overenie nahrávania zlyhalo
+ Nahrávanie zlyhalo: %1$s
+ Chyba pri nahrávaní súboru: %1$s
+ Nie je možné vytvoriť cieľovú zložku, alebo k nej získať prístup: %1$s
+ Načítavanie súborov s nastaveniami zlyhalo
+ Chyba pri načítavaní súborov s nastaveniami: %1$s
+ Sťahovanie súboru zlyhalo
+ Chyba pri sťahovaní súboru: %1$s
+
+ Autorizácia %1$s
+ Vo vašom prehliadači bola otvorená stránka pre autorizáciu%1$s .\n\nProsím dokončite autorizáciu a potom se vráťte do tejto aplikácie.\n\nToto dialogové okno sa automaticky zatvorí po úspešnej autorizácii.
+ Zahájanie autorizácie zlyhalo
+ Autorizácia zrušená
+ Vypršal časový limit pre autorizáciu, skúste to prosím znovu
+ Platnosť autorizácie cloudového úložiska vypršala, alebo je autorizácia neplatná. Prosím zopakujte pokus o autorizáciu.
+
+ Stav autorizácie
+ Autorizácia na Google Disk úspešná
+ Prosím vymažte nastavenia a znovu sa autorizujte na Google Disk
diff --git a/plugins/configuration/src/main/res/values-sr-rCS/strings.xml b/plugins/configuration/src/main/res/values-sr-rCS/strings.xml
index 82cf37cd9cd..fcb7e312fb2 100644
--- a/plugins/configuration/src/main/res/values-sr-rCS/strings.xml
+++ b/plugins/configuration/src/main/res/values-sr-rCS/strings.xml
@@ -4,6 +4,7 @@
NE SME SE KORISTITI ZA DONOŠENJE MEDICINSKIH ODLUKA. NE POSTOJI GARANCIJA ZA PROGRAM, U MERI DOPUŠTENOJ PRIMJENJIVIM ZAKONOM. OSIM KADA JE DRUGAČE NAVEDENO U PISANJU NOSILACA AUTORSKOG PRAVA I/ILI DRUGE STRANE OBEZBEĐUJU PROGRAM „KAKAV JESTE“ BEZ BILO KOJE GARANCIJE, BILO IZRIČENE ILI PODRAZUMEVANE, UKLJUČUJUĆI, ALI NE OGRANIČAVAJUĆI SE NA, PODRAZUMEVANE GARANCIJE O PRODAJNOSTI I PRIKLADNOSTI ZA ODREĐENU NAMENU. CEO RIZIK PO KVALITETU I PERFORMANSE PROGRAMA JE NA VAMA. AKO SE POKAŽE NEISPRAVAN PROGRAM, VI PREUZIMATE TROŠKOVE SVIH NEOPHODNIH SERVISIRANJA, POPRAVKE ILI KOREKCIJE.RAZUMEM I SLAŽEM SEProfil
+
ZahtevAPS režimČini se da ovaj uređaj ne podržava stavljanje na belu listu za optimizaciju baterije – mogli biste imati problema s performansama.
@@ -54,4 +55,9 @@
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-sv-rSE/strings.xml b/plugins/configuration/src/main/res/values-sv-rSE/strings.xml
index 5dc046cb3fb..d9552a9a2c0 100644
--- a/plugins/configuration/src/main/res/values-sv-rSE/strings.xml
+++ b/plugins/configuration/src/main/res/values-sv-rSE/strings.xml
@@ -44,6 +44,7 @@
DatavalUppladdning till FabricIdentifiering (e-post, FB, Discord-namn etc)
+
BegäranAPS-lägeFel vid begäran om behörigheter
@@ -153,4 +154,9 @@
· FilkrypteringNytt krypterat formatOkänt exportformat
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-tr-rTR/strings.xml b/plugins/configuration/src/main/res/values-tr-rTR/strings.xml
index bc96579b56e..2950614e35e 100644
--- a/plugins/configuration/src/main/res/values-tr-rTR/strings.xml
+++ b/plugins/configuration/src/main/res/values-tr-rTR/strings.xml
@@ -48,6 +48,7 @@
Gözetimsiz Ayarlar Dışa AktarımıBunu etkinleştirmek, parolanızı telefonunuzda güvenli bir şekilde saklayacaktırTanımlama (E-posta, FB veya Discord rumuz vs.)
+
İstekAPS moduİzin istenirken hata
@@ -166,4 +167,9 @@
Bilinmeyen dışa aktarma formatıAPS sonuçlarını sıfırlaDosya sistemine erişim hatası. Lütfen AAPS dizinini doğru seçin.
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-uk-rUA/strings.xml b/plugins/configuration/src/main/res/values-uk-rUA/strings.xml
index 886e21af88b..9a71b9adffb 100644
--- a/plugins/configuration/src/main/res/values-uk-rUA/strings.xml
+++ b/plugins/configuration/src/main/res/values-uk-rUA/strings.xml
@@ -1,6 +1,7 @@
Профіль
+
@@ -16,4 +17,9 @@
Шифрування файлуНовий метод шифруванняНевідомий формат експорту
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-vi-rVN/strings.xml b/plugins/configuration/src/main/res/values-vi-rVN/strings.xml
index 03d4fdc445d..c1aa26f69f2 100644
--- a/plugins/configuration/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/configuration/src/main/res/values-vi-rVN/strings.xml
@@ -4,10 +4,10 @@
Chọn đơn vị mà bạn muốn hiển thị giá trịTiếp theoTrước đó
- Hướng dẫn thiết lập
+ Cài đặt nhanhKẾT THÚCChào mừng
- Chào mừng đến với trình hướng dẫn cài đặt. Nó sẽ hướng dẫn bạn từng bước trong quá trình thiết lập.\n
+ Chào mừng đến với trình hướng dẫn cài đặt. Hệ thống sẽ hướng dẫn bạn từng bước trong quá trình thiết lập.\nThỏa thuận cấp phép với người dùng cuốiKHÔNG ĐƯỢC SỬ DỤNG ĐỂ RA QUYẾT ĐỊNH Y TẾ. CHƯƠNG TRÌNH KHÔNG ĐƯỢC BẢO HÀNH, TRONG MỨC CHO PHÉP THEO LUẬT HIỆN HÀNH. TRỪ KHI ĐƯỢC NÊU KHÁC BẰNG VĂN BẢN, CÁC CHỦ SỞ HỮU BẢN QUYỀN VÀ/HOẶC CÁC BÊN KHÁC CUNG CẤP CHƯƠNG TRÌNH \"NGUYÊN TRẠNG\" MÀ KHÔNG CÓ BẢO HÀNH DẠNG NÀO, DÙ RÕ RÀNG HAY NGỤ Ý, BAO GỒM NHƯNG KHÔNG GIỚI HẠN Ở BẢO HÀNH NGỤ Ý VỀ TÍNH THƯƠNG MẠI VÀ PHÙ HỢP CHO MỤC ĐÍCH CỤ THỂ. TOÀN BỘ RỦI RO VỀ CHẤT LƯỢNG VÀ HIỆU SUẤT CỦA CHƯƠNG TRÌNH SẼ DO BẠN CHỊU TRÁCH NHIỆM. NẾU CHƯƠNG TRÌNH BỊ LỖI, BẠN PHẢI CHỊU TOÀN BỘ CHI PHÍ CHO VIỆC BẢO TRÌ, SỬA CHỮA HOẶC KHẮC PHỤC.TÔI ĐÃ HIỂU VÀ ĐỒNG Ý
@@ -31,9 +31,9 @@
Trạng thái:Tên người dùngVui lòng cung cấp tên bệnh nhân hoặc biệt danh để phân biệt giữa nhiều thiết lập
- Lưu ý: các Cấu hình insulin mới yêu cầu DIA ít nhất 5 giờ. DIA 5–6 giờ trên Cấu hình mới tương đương với DIA 3 giờ trên hồ sơ insulin cũ.
- Cấu hình
- Thực hiện chuyển Cấu hình
+ Lưu ý: Các Hồ sơ insulin mới yêu cầu DIA ít nhất 5 giờ. DIA 5–6 giờ trên Hồ sơ mới tương đương với DIA 3 giờ trên hồ sơ insulin cũ.
+ Hồ sơ
+ Thực hiện chuyển Hồ sơBỏ qua cài đặt nhanhPlugin Sensitivity được sử dụng để phát hiện độ nhạy và tính toán COB. Để biết thêm thông tin, hãy truy cập:https://wiki.aaps.app/en/latest/DailyLifeWithAaps/SensitivityDetectionAndCob.html
@@ -48,35 +48,43 @@
Xuất cài đặt tự độngBật tùy chọn này sẽ lưu mật khẩu của bạn một cách an toàn trên điện thoạiNhận dạng (email, Facebook hoặc Discord, v.v.)
+
+ Đã xuất cài đặt thành công lên lưu trữ đám mây
+ Xuất lên lưu trữ đám mây thất bại
+ Không thể kết nối tới lưu trữ đám mây
+ Đang tải cài đặt từ lưu trữ đám mây, vui lòng chờ…
+ Không thể tải các thư mục lưu trữ đám mây
+ Đã tải CSV mục nhập người dùng lên đám mây thành công
+ Không thể kết nối tới lưu trữ đám mây. Xác thực lại chứ?Yêu cầuChế độ APSLỗi khi yêu cầu cấp quyềnThiết bị này dường như không hỗ trợ loại trừ khỏi tối ưu pin – bạn có thể gặp các vấn đề về hiệu suất.
- Config Builder
- Pump
+ Xây dựng Cấu hình
+ Bơm InsulinBạn muốn sử dụng loại bơm nào với AAPS?
- Cấu hình
- AAPS nên dùng Cấu hình điều trị nào?
+ Hồ sơ
+ AAPS nên dùng Hồ sơ điều trị nào?APSThuật toán APS nào sẽ thực hiện điều chỉnh điều trị?
- General
- Đây là một số plugin chung mà bạn có thể thấy hữu ích.
- Synchronization
- Các plugin dùng để tải lên và đồng bộ dữ liệu.
+ Cài đặt chung
+ Đây là một số Tiện ích chung mà bạn có thể thấy hữu ích.
+ Đồng bộ hóa
+ Các Tiện ích dùng để tải lên và đồng bộ dữ liệu.Những giới hạn nào đang được áp dụng?LoopSử dụng tùy chọn này để kích hoạt tích hợp vòng lặp của AAPS.Bạn đang dùng loại insulin gì?
- BG Source
+ Nguồn Đường huyếtBạn muốn AAPS lấy dữ liệu từ đâu?
- Smoothing
+ Làm mượtChọn thuật toán làm mượt
- Sensitivity detection
+ Phát hiện độ nhạy insulinBạn muốn chọn thuật toán độ nhạy nào?CONF
- Được dùng để thiết lập các plugin đang chạy
- Chú ý: Nếu bạn kích hoạt và kết nối với phần cứng bơm insulin, AAPS sẽ sao chép các thiết lập basal từ Cấu hình sang bơm, ghi đè lên tốc độ basal hiện có được lưu trên bơm. Hãy đảm bảo rằng bạn đã có thiết lập basal chính xác trong AAPS. Nếu bạn không chắc chắn hoặc không muốn ghi đè các thiết lập basal trên bơm, hãy nhấn Hủy và thực hiện lại việc chuyển sang bơm sau.
+ Được dùng để thiết lập các Tiện ích đang chạy
+ Chú ý: Nếu bạn kích hoạt và kết nối với phần cứng bơm insulin, AAPS sẽ sao chép các thiết lập liều nền từ Hồ sơ sang bơm, ghi đè lên tốc độ liều nền hiện có được lưu trên bơm. Hãy đảm bảo rằng bạn đã có thiết lập liều nền chính xác trong AAPS. Nếu bạn không chắc chắn hoặc không muốn ghi đè các thiết lập liều nền trên bơm, hãy nhấn Hủy và thực hiện lại việc chuyển sang bơm sau.mở cài đặtPhiên bản AAPSClient không khớp với phiên bản AAPS. Vui lòng cập nhật.Mở rộng danh mục
@@ -86,7 +94,7 @@
Hệ thống sẽ yêu cầu mật khẩu chính để mã hóa các thiết lập bạn xuất ra.Xuất dữ liệu đã bị hủy! Tùy chọn KHÔNG được xuất dữ liệu!Nhập dữ liệu đã bị hủy! Tùy chọn KHÔNG được nhập dữ liệu!
- Không thể nhập thiết lập!
+ Không thể nhập các tùy chọn!Giải thích sự cố nhập dữ liệu…Chi tiết sự cố nhập dữ liệuNhập dữ liệu
@@ -95,16 +103,16 @@
Thư mục AAPSChọn thư mục AAPS để lưu trữ các tệp xuất ra, cấu hình và dữ liệu khác.Vui lòng xem lại các thiết lập trước khi nhập:
- Không thể nhập các thiết lập!
- Không nên nhập các thiết lập!
+ Không thể nhập các tùy chọn cài đặt!
+ Không nên nhập các tùy chọn cài đặt này!Xuất cài đặt đếnNhập cài đặt từCác cài đặt đã được nhậpMật khẩu chính cũTệp này đã được xuất và mã hóa bằng mật khẩu khác. Vui lòng nhập mật khẩu cũ để giải mã tệp.Khi nhập thành công, mật khẩu chính hiện tại SẼ BỊ THAY THẾ bằng mật khẩu chính cũ!
- Tùy chọn đã xuất
- Xuất tùy cài đặt thất bại!
+ Đã xuất cài đặt tùy chọn
+ Xuất tùy cài đặt tùy chọn thất bại!Không tìm thấy tệpVui lòng quay lại màn hình chính và thử lại.Thoát ứng dụng để áp dụng thiết lập.
@@ -112,7 +120,7 @@
Bảo mậtChưa thiết lập mật khẩu chính!\n\nVui lòng đặt mật khẩu chính trong Tùy chọn cài đặt (%1$s)
- Maintenance
+ Bảo trì hệ thốngMAINTCung cấp một số chức năng bảo trì (ví dụ: gửi nhật ký, xóa nhật ký).Dọn dẹp cơ sở dữ liệu
@@ -148,7 +156,7 @@
Lỗi giải mã, mật khẩu đã nhập không thể giải mã tệpTệp không có mã kiểm tra (checksum/hash), không thể xác minh tính hợp lệ của cài đặt!Tệp đã bị chỉnh sửa sau khi xuất dữ liệu!
- Lỗi giải mã: không thể đọc tệp cài đặt!
+ Lỗi giải mã: không thể đọc tệp cài đặt tùy chọn!Lỗi giải mã, mật khẩu cung cấp không hợp lệ hoặc tệp cài đặt đã bị chỉnh sửa! Điều này có thể xảy ra nếu tệp nhập dữ liệu vào được xuất dữ liệu bằng mật khẩu khác.Thiếu cấu hình mã hóa, định dạng cài đặt không hợp lệ!Thuật toán mã hóa không được hỗ trợ hoặc chưa được chỉ định!
@@ -166,4 +174,91 @@
Định dạng xuất dữ liệu không xác địnhĐặt lại kết quả APSLỗi truy cập hệ thống tệp. Hãy chọn đúng thư mục AAPS.
+
+ Lưu trữ Cục bộ
+ Google Drive
+ Chọn Kiểu lưu trữ
+ Sao lưu vào Google Drive
+ Lỗi kết nối Google Drive
+ Xác thực lại
+ Xác thực lưu trữ đám mây thành công
+ Không thể kết nối tới lưu trữ đám mây
+ Lỗi xác thực lưu trữ đám mây: %1$s
+ Bật xuất dữ liệu lên đám mây
+ Bạn có muốn bật xuất lên đám mây không? Thao tác này sẽ kích hoạt tùy chọn “All Cloud” trong Cài đặt xuất.
+ Bạn có thể thay đổi việc này sau trong Xuất Cài đặt
+ Vui lòng thiết lập Thư mục đám mây trước để sử dụng Xuất Cài đặt
+ Thư mục CỤC BỘ
+ Thư mục đám mây
+ Xuất các tuỳ chọn
+ Nhật ký
+ Cài đặt người sử dụng
+ Xuất dữ liệu sang Excel (csv)
+ Email
+ Lưu trữ Cục bộ
+ Lưu trữ đám mây
+ Toàn bộ lên đám mây
+ Xuất nhật ký lên đám mây
+ Xuất dữ liệu người dùng lên đám mây (csv)
+ Xuất mục dữ liệu vào cục bộ (csv)
+ Xuất cài đặt (Cục bộ)
+ Xuất cài đặt (Đám mây)
+ Xuất cài đặt (Cục bộ + Đám mây)
+ Nhập cài đặt (Cục bộ)
+ Nhập cài đặt (Đám mây)
+ Nhập cài đặt (Cục bộ + Đám mây)
+
+ Chọn nguồn nhập dữ liệu
+ Nhập từ lưu trữ Cục bộ
+ Nhập từ lưu trữ Đám mây
+ Nhập cài đặt từ thiết bị lưu trữ
+ Nhập cài đặt từ lưu trữ đám mây
+ Đang hiển thị %1$d của %2$d tệp
+ Đang hiển thị tất cả %1$d tệp
+ Tải thêm
+ Tải thêm %1$d (đã tải %2$d)
+ Đang tải…
+ Đang tải %1$d của %2$d…
+ Đang tải %1$s (%2$d/%3$d)…
+ Đã tải nhật ký lên đám mây thành công
+ Tải nhật ký lên đám mây thất bại
+ Đã xảy ra lỗi khi tải nhật ký lên lưu trữ đám mây
+ Tải dữ liệu CSV lên đám mây thất bại
+ Đã xảy ra lỗi khi tải CSV lên đám mây
+ Đã cập nhật tùy chọn Xuất dữ liệu
+ Không có tệp cài đặt trên đám mây
+ Xóa Cài Đặt
+ Xóa Cài Đặt Đám mây
+ Sẽ chuyển sang lưu trữ cục bộ và xóa xác thực. Tiếp tục?
+ Đang tải lên Đám mây...
+ Thư mục Đám mây: %1$s
+ Đã chọn sai thư mục
+ Bạn đã chọn thư mục con “%1$s” thay vì thư mục gốc của AAPS. Vui lòng chọn thư mục AAPS cấp cha. Ứng dụng sẽ tự động tạo và quản lý các thư mục con.
+
+ Không thể làm mới mã truy cập Google Drive
+ Không thể làm mới mã truy cập Google Drive: %1$s
+ Kiểm tra kết nối Google Drive thất bại
+ Không thể kết nối tới Google Drive: %1$s
+ Không thể liệt kê các thư mục Google Drive
+ Lỗi khi liệt kê thư mục: %1$s
+ Đã tải lên nhưng không nhận được ID
+ Xác minh tải lên thất bại
+ Tải lên thất bại: %1$s
+ Lỗi khi tải tệp lên: %1$s
+ Không thể tạo hoặc truy cập thư mục đích: %1$s
+ Không thể liệt kê các tệp cài đặt
+ Lỗi khi liệt kê tệp cài đặt: %1$s
+ Không thể tải tệp xuống
+ Lỗi khi tải tệp xuống: %1$s
+
+ Xác thực %1$s
+ Trang xác thực %1$s đã được mở trong trình duyệt của bạn.\n\nVui lòng hoàn tất việc xác thực, sau đó quay lại ứng dụng này.\n\nHộp thoại này sẽ tự động đóng khi quá trình xác thực hoàn tất.
+ Không thể bắt đầu quá trình xác thực
+ Đã hủy xác thực
+ Xác thực đã hết hạn, vui lòng thử lại
+ Quyền xác thực lưu trữ đám mây đã hết hạn hoặc không hợp lệ. Vui lòng xác thực lại.
+
+ Trạng thái xác thực
+ Đã xác thực Google Drive
+ Vui lòng xóa cài đặt và xác thực lại Google Drive
diff --git a/plugins/configuration/src/main/res/values-zh-rCN/strings.xml b/plugins/configuration/src/main/res/values-zh-rCN/strings.xml
index ac5f0047b24..60d7ae24544 100644
--- a/plugins/configuration/src/main/res/values-zh-rCN/strings.xml
+++ b/plugins/configuration/src/main/res/values-zh-rCN/strings.xml
@@ -41,6 +41,7 @@
数据选择通过Fabric上传身份识别 (email邮件地址, FaceBook账号 或 Discord账号等等)
+
请求APS模式此设备似乎不支持电池优化白名单 - 您可能会遇到性能问题。
@@ -135,4 +136,9 @@
文件加密密钥。新的加密格式未知的导出格式
+
+
+
+
+
diff --git a/plugins/configuration/src/main/res/values-zh-rTW/strings.xml b/plugins/configuration/src/main/res/values-zh-rTW/strings.xml
index 8688afe4bed..12f9790c2bc 100644
--- a/plugins/configuration/src/main/res/values-zh-rTW/strings.xml
+++ b/plugins/configuration/src/main/res/values-zh-rTW/strings.xml
@@ -48,6 +48,14 @@
自動設定匯出啟用此功能將安全儲存您的密碼於手機上標識(電子郵件、FB或Discord暱稱等)
+
+ 已成功將設定匯出到雲端儲存空間
+ 匯出到雲端儲存空間失敗
+ 雲端儲存空間連線失敗
+ 正在從雲端儲存空間載入設定,請稍候…
+ 無法載入雲端儲存空間資料夾
+ 已成功將使用者輸入 CSV 上傳到雲端儲存空間
+ 雲端儲存空間連線失敗。要重新驗證嗎?請求APS模式請求權限時出錯
@@ -166,4 +174,91 @@
未知的匯出格式重置APS結果無法存取檔案系統。請正確選擇 AAPS 目錄。
+
+ 本機儲存空間
+ Google 雲端硬碟
+ 選擇儲存空間類型
+ 備份到 Google 雲端硬碟
+ Google 雲端硬碟連線錯誤
+ 重新驗證
+ 雲端儲存空間驗證成功
+ 雲端儲存空間驗證失敗
+ 雲端儲存空間驗證錯誤:%1$s
+ 啟用雲端匯出
+ 要啟用雲端匯出嗎?這會在匯出設定中啟用 \"全部雲端\" 選項。
+ 之後可在匯出設定中變更
+ 請先設定雲端目錄以使用匯出設定
+ 本機目錄
+ 雲端目錄
+ 匯出選項
+ 記錄
+ 使用者設定
+ 將使用者輸入匯出成 Excel (CSV)
+ 電子郵件
+ 本機儲存空間
+ 雲端儲存空間
+ 全部雲端
+ 將記錄匯出到雲端
+ 將使用者輸入匯出到雲端 (CSV)
+ 將使用者輸入匯出到本機 (CSV)
+ 匯出設定 (本機)
+ 匯出設定 (雲端)
+ 匯出設定 (本機 + 雲端)
+ 匯入設定 (本機)
+ 匯入設定 (雲端)
+ 匯入設定(本機/雲端)
+
+ 選擇匯入來源
+ 從本機儲存空間匯入
+ 從雲端儲存空間匯入
+ 從裝置儲存空間匯入設定
+ 從雲端儲存空間匯入設定
+ 顯示 %1$d 個檔案(共 %2$d 個)
+ 顯示全部 %1$d 個檔案
+ 載入更多
+ 載入接下來的 %1$d(已載入 %2$d)
+ 載入中…
+ 正在載入第 %1$d 個(共 %2$d 個)…
+ 正在載入 %1$s(%2$d/%3$d)…
+ 記錄檔已成功上傳至雲端儲存空間
+ 無法將記錄檔上傳至雲端儲存空間
+ 上傳記錄檔至雲端儲存空間時發生錯誤
+ 無法將使用者輸入 CSV 上傳至雲端儲存空間
+ 上傳 CSV 到雲端時發生錯誤
+ 匯出選項已更新
+ 雲端儲存空間中找不到設定檔
+ 清除設定
+ 清除雲端設定
+ 這將切換到本機儲存並清除授權。是否繼續?
+ 正在上傳到雲端…
+ 雲端目錄:%1$s
+ 目錄選擇錯誤
+ 你選的是「%1$s」這個子目錄,而不是 AAPS 的根目錄。請改選上一層的 AAPS 目錄。App 會自動建立並管理子目錄。
+
+ 無法重新整理 Google Drive 存取權杖
+ 無法重新整理 Google Drive 存取權杖:%1$s
+ Google Drive 連線測試失敗
+ 無法連線至 Google Drive:%1$s
+ 無法列出 Google Drive 資料夾
+ 列出資料夾時發生錯誤:%1$s
+ 上傳成功,但未返回 id
+ 上傳驗證失敗
+ 上傳失敗:%1$s
+ 上傳檔案時發生錯誤:%1$s
+ 無法建立或存取目的資料夾:%1$s
+ 無法列出設定檔
+ 列出設定檔時發生錯誤:%1$s
+ 無法下載檔案
+ 下載檔案時發生錯誤:%1$s
+
+ %1$s 授權
+ 已在您的瀏覽器中開啟 %1$s 授權頁面。\n\n請完成授權,然後返回此 App。\n\n此對話框將在授權完成後自動關閉。
+ 無法啟動授權
+ 已取消授權
+ 授權逾時,請重試
+ 雲端儲存空間授權已過期或無效。請重新授權。
+
+ 授權狀態
+ Google Drive 已授權
+ 請清除設定並重新授權 Google Drive
diff --git a/plugins/configuration/src/main/res/values/colors.xml b/plugins/configuration/src/main/res/values/colors.xml
new file mode 100644
index 00000000000..dd9eb9850de
--- /dev/null
+++ b/plugins/configuration/src/main/res/values/colors.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ #1B8F5A
+
+ #D97706
+
diff --git a/plugins/configuration/src/main/res/values/strings.xml b/plugins/configuration/src/main/res/values/strings.xml
index 14a61f1956a..b51fcf8afef 100644
--- a/plugins/configuration/src/main/res/values/strings.xml
+++ b/plugins/configuration/src/main/res/values/strings.xml
@@ -48,6 +48,15 @@
Unattended Settings ExportEnabling this will securely store your password on your phoneIdentification (email, FB or Discord nick etc)
+
+
+ Settings successfully exported to cloud storage
+ Failed to export to cloud storage
+ Cloud storage connection failed
+ Loading settings from cloud storage, please wait…
+ Failed to load cloud storage folders
+ User Entries CSV successfully uploaded to cloud storage
+ Cloud storage connection failed. Would you like to re-authenticate?RequestAPS ModeError asking for permissions
@@ -174,4 +183,95 @@
Reset APS resultsError accessing filesystem. Select AAPS directory properly.
+
+ Local Storage
+ Google Drive
+ Select Storage Type
+ Backup to Google Drive
+ Google Drive connection error
+ Re-authenticate
+ Cloud storage authentication successful
+ Cloud storage authentication failed
+ Cloud storage authentication error: %1$s
+ Enable Cloud Export
+ Would you like to enable cloud export? This will enable the \"All Cloud\" option in Export Settings.
+ You can modify this later in Export Settings
+ Please set up Cloud Directory first to use Export Settings
+ LOCAL Directory
+ Cloud Directory
+ Export Options
+ Log
+ User Settings
+ Export User Entries to Excel (CSV)
+ Email
+ Local Storage
+ Cloud Storage
+ All Cloud
+ Export Logs to Cloud
+ Export User Entries to Cloud (csv)
+ Export User Entries to Local (csv)
+ Export settings (Local)
+ Export settings (Cloud)
+ Export settings (Local+Cloud)
+ Import settings (Local)
+ Import settings (Cloud)
+ Import settings (Local/Cloud)
+
+
+ Select Import Source
+ Import from Local Storage
+ Import from Cloud Storage
+ Import settings from device storage
+ Import settings from cloud storage
+ Showing %1$d of %2$d files
+ Showing all %1$d files
+ Load More
+ Load next %1$d (loaded %2$d)
+ Loading…
+ Loading %1$d of %2$d…
+ Loading %1$s (%2$d/%3$d)…
+ Logs successfully uploaded to cloud storage
+ Failed to upload logs to cloud storage
+ Error occurred while uploading logs to cloud storage
+ Failed to upload User Entries CSV to cloud storage
+ Error occurred while uploading CSV to cloud
+ Export options updated
+ No settings files found in cloud storage
+ Clear Settings
+ Clear Cloud Settings
+ This will switch to local storage and clear authorization. Continue?
+ Uploading to cloud...
+ Cloud directory: %1$s
+ Wrong Directory Selected
+ You have selected the \"%1$s\" subdirectory instead of the root AAPS directory. Please select the parent AAPS directory. The app will automatically create and manage subdirectories.
+
+
+ Unable to refresh Google Drive access token
+ Unable to refresh Google Drive access token: %1$s
+ Google Drive connection test failed
+ Unable to connect to Google Drive: %1$s
+ Failed to list Google Drive folders
+ Error listing folders: %1$s
+ Upload succeeded but no id returned
+ Upload verification failed
+ Upload failed: %1$s
+ Error uploading file: %1$s
+ Cannot create or access destination folder: %1$s
+ Failed to list settings files
+ Error listing settings files: %1$s
+ Failed to download file
+ Error downloading file: %1$s
+
+
+ %1$s Authorization
+ %1$s authorization page has been opened in your browser.\n\nPlease complete the authorization, then return to this app.\n\nThis dialog will close automatically once authorization is completed.
+ Failed to start authorization
+ Authorization cancelled
+ Authorization timed out, please retry
+ Cloud storage authorization has expired or is invalid. Please re-authorize.
+
+
+ Authorization Status
+ Google Drive Authorized
+ Please clear settings and re-authorize Google Drive
\ No newline at end of file
diff --git a/plugins/configuration/src/test/kotlin/app/aaps/configuration/maintenance/MaintenancePluginTest.kt b/plugins/configuration/src/test/kotlin/app/aaps/configuration/maintenance/MaintenancePluginTest.kt
index 0c661dc62fc..63057210a2a 100644
--- a/plugins/configuration/src/test/kotlin/app/aaps/configuration/maintenance/MaintenancePluginTest.kt
+++ b/plugins/configuration/src/test/kotlin/app/aaps/configuration/maintenance/MaintenancePluginTest.kt
@@ -5,6 +5,8 @@ import app.aaps.core.interfaces.logging.UserEntryLogger
import app.aaps.core.interfaces.maintenance.FileListProvider
import app.aaps.core.interfaces.nsclient.NSSettingsStatus
import app.aaps.plugins.configuration.maintenance.MaintenancePlugin
+import app.aaps.plugins.configuration.maintenance.cloud.CloudStorageManager
+import app.aaps.plugins.configuration.maintenance.cloud.ExportOptionsDialog
import app.aaps.shared.tests.TestBaseWithProfile
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.BeforeEach
@@ -18,12 +20,14 @@ class MaintenancePluginTest : TestBaseWithProfile() {
@Mock lateinit var loggerUtils: LoggerUtils
@Mock lateinit var fileListProvider: FileListProvider
@Mock lateinit var uel: UserEntryLogger
+ @Mock lateinit var cloudStorageManager: CloudStorageManager
+ @Mock lateinit var exportOptionsDialog: ExportOptionsDialog
private lateinit var sut: MaintenancePlugin
@BeforeEach
fun mock() {
- sut = MaintenancePlugin(context, rh, preferences, nsSettingsStatus, aapsLogger, config, fileListProvider, loggerUtils, uel)
+ sut = MaintenancePlugin(context, rh, preferences, nsSettingsStatus, aapsLogger, config, fileListProvider, loggerUtils, uel, cloudStorageManager, exportOptionsDialog)
whenever(loggerUtils.suffix).thenReturn(".log.zip")
whenever(loggerUtils.logDirectory).thenReturn("src/test/assets/logger")
// Unknown solution after scoped access
diff --git a/plugins/constraints/build.gradle.kts b/plugins/constraints/build.gradle.kts
index 4030c2e74b7..b9293f266b9 100644
--- a/plugins/constraints/build.gradle.kts
+++ b/plugins/constraints/build.gradle.kts
@@ -32,6 +32,8 @@ dependencies {
testImplementation(project(":shared:impl"))
testImplementation(project(":shared:tests"))
+ api(libs.kotlinx.datetime)
+
// Phone checker
api(libs.com.scottyab.rootbeer.lib)
diff --git a/plugins/constraints/src/main/kotlin/app/aaps/plugins/constraints/versionChecker/AllowedVersions.kt b/plugins/constraints/src/main/kotlin/app/aaps/plugins/constraints/versionChecker/AllowedVersions.kt
index 32b69eb14e0..088ac8c864f 100644
--- a/plugins/constraints/src/main/kotlin/app/aaps/plugins/constraints/versionChecker/AllowedVersions.kt
+++ b/plugins/constraints/src/main/kotlin/app/aaps/plugins/constraints/versionChecker/AllowedVersions.kt
@@ -1,12 +1,10 @@
package app.aaps.plugins.constraints.versionChecker
import app.aaps.core.utils.JsonHelper
+import kotlinx.datetime.LocalDate
+import kotlinx.datetime.TimeZone
+import kotlinx.datetime.atStartOfDayIn
import org.json.JSONObject
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.time.LocalTime
-import java.time.ZoneId
-import java.time.format.DateTimeFormatter
object AllowedVersions {
@@ -16,8 +14,8 @@ object AllowedVersions {
fun endDateToMilliseconds(endDate: String): Long? =
try {
- val date = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
- LocalDateTime.of(date, LocalTime.of(0, 0)).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
+ val date = LocalDate.parse(endDate)
+ date.atStartOfDayIn(TimeZone.currentSystemDefault()).toEpochMilliseconds()
} catch (_: Exception) {
null
}
diff --git a/plugins/constraints/src/main/res/values-it-rIT/objectives.xml b/plugins/constraints/src/main/res/values-it-rIT/objectives.xml
index 1bdb7d871fd..35ef521d4f5 100644
--- a/plugins/constraints/src/main/res/values-it-rIT/objectives.xml
+++ b/plugins/constraints/src/main/res/values-it-rIT/objectives.xml
@@ -29,6 +29,7 @@
È necessario leggere il wiki e aumentare maxIOB affinché le azioni di SMB funzionino adeguatamente! Un buon inizio è maxIOB = media bolo posto + 3 x max basale giornalieraUsare SMB è il tuo obiettivo. L\'algoritmo Oref1 è stato progettato per aiutarti anche con i tuoi boli. Non dovresti erogare un bolo completo per il tuo cibo, ma solo una parte di esso e lasciare che AAPS ti dia il resto se necessario. In questo modo hai più spazio di azione per i carboidrati mal calcolati. Lo sapevi che puoi impostare una percentuale del risultato del calcolatore per ridurre la dimensione del bolo?Abilitazione automazione
+ Leggi la documentazione su come funzionano le automazioni. Configura le tue prime semplici regole. Invece di eseguire un\'azione, consenti ad AAPS di visualizzare solo una notifica. Quando sei sicuro che l\'automazione viene attivata al momento giusto, sostituisci la notifica con un\'azione reale. (https://wiki.aaps.app/en/latest/DailyLifeWithAaps/Automations.html)L\'automazione può essere un buon \"servitore\" ma anche un cattivo \"padrone\". Non abusarne. Non cercare di sostituire l\'algoritmo di base. Verifica lo stato dell\'automazione con un messaggio prima dell\'uso.BG disponibile in NS o TidepoolStato micro disponibile in NS o Tidepool
diff --git a/plugins/constraints/src/main/res/values-nl-rNL/exam.xml b/plugins/constraints/src/main/res/values-nl-rNL/exam.xml
index 6386473c850..29840761014 100644
--- a/plugins/constraints/src/main/res/values-nl-rNL/exam.xml
+++ b/plugins/constraints/src/main/res/values-nl-rNL/exam.xml
@@ -63,6 +63,7 @@
https://wiki.aaps.app/nl/latest/SettingUpAaps/YourAapsProfile.htmlVereistenWat is minimaal nodig om AAPS in te stellen en te gebruiken?
+ Methode om AAPS te bouwen. Ofwel via een web browser of een computer met Android Studio geïnstalleerd.Een ondersteunde insulinepomp als je van plan bent een closed loop te gebruiken.Nightscout, om een logboek van alle gegevens bij te houden en instellingen te bekijken.Ervaar met programmeren of code aanpassen.
@@ -96,6 +97,7 @@
Fiasp®NovoRapid®/Novolog®Humalog®
+ Actrapid®/Humulin R®/\"algemene\" menselijke insuline.https://wiki.aaps.app/nl/latest/Configuration/Config-Builder.html#insulineGevoeligheidspluginsGevoeligheidsplugins stellen AndroidAPS in staat om aan te passen aan tijdelijke of kortstondige veranderingen in insulinegevoeligheid (bijvoorbeeld hormonale veranderingen of problemen met insuline-opname bij de infuusplaats).
diff --git a/plugins/constraints/src/main/res/values-nl-rNL/strings.xml b/plugins/constraints/src/main/res/values-nl-rNL/strings.xml
index 08413badaf0..ee61c75c3fe 100644
--- a/plugins/constraints/src/main/res/values-nl-rNL/strings.xml
+++ b/plugins/constraints/src/main/res/values-nl-rNL/strings.xml
@@ -11,6 +11,7 @@
Applicatie is verlopenWe hebben gedetecteerd dat je een ongeldige versie gebruikt. Loop is uitgeschakeld!Versie %1$s is beschikbaar
+ Versie %1$s vervalt op %2$s en schakelt dan naar LGS modusHerberekende data gebruikt
diff --git a/plugins/constraints/src/main/res/values-pl-rPL/exam.xml b/plugins/constraints/src/main/res/values-pl-rPL/exam.xml
index 624b5cc37c0..72c4f364b67 100644
--- a/plugins/constraints/src/main/res/values-pl-rPL/exam.xml
+++ b/plugins/constraints/src/main/res/values-pl-rPL/exam.xml
@@ -63,6 +63,7 @@
https://wiki.aaps.app/en/latest/SettingUpAaps/YourAapsProfile.htmlWymagania wstępneCo jest niezbędne do ustawienia i używania AAPS?
+ Możliwość zbudowania AAPS. Albo przez przeglądarkę lub na komputerze z zainstalowanym Android Studio.Kompatybilna pompa insulinowa, jeśli planujesz uruchomienie pętli zamkniętej.Nightscout, aby zachować dziennik wszystkich danych i przeglądać ustawienia.Doświadczenie w programowaniu lub edycji kodu.
@@ -96,6 +97,7 @@
Fiasp®NovoRapid ® /Novolog ®Humalog®
+ Actrapid®/Humulin R®/\"zwykła\" insulina ludzka.https://wiki.aaps.app/en/latest/SettingUpAaps/ConfigBuilder.html#insulinWtyczki wrażliwościWtyczki wrażliwości pozwalają AAPS dostosować się do tymczasowych lub krótkotrwałych zmian wrażliwości na insulinę (na przykład zmian hormonalnych lub problemów z wchłanianiem w miejscu wkłucia).
diff --git a/plugins/constraints/src/main/res/values-pl-rPL/objectives.xml b/plugins/constraints/src/main/res/values-pl-rPL/objectives.xml
index 7bd4aecfd2f..8ced976b52b 100644
--- a/plugins/constraints/src/main/res/values-pl-rPL/objectives.xml
+++ b/plugins/constraints/src/main/res/values-pl-rPL/objectives.xml
@@ -16,9 +16,12 @@
Wykonaj działanie, aby spełnić rekomendacjęNależy zwrócić uwagę na dostępne zabezpieczenia i w razie potrzeby dostosować parametry bezpieczeństwa.Rozpoczęcie zamknięcia pętli z zawieszeniem podawania bazy przy niskim poziomie cukru
+ Uruchom zamkniętą pętlę w trybie zawieszania niskiej glukozy (gdzie Maksymalna IOB = 0 jest ustawiona automatycznie) na kilka dni bez zbyt wielu zdarzeń LGS (wstrzymania podaży insuliny z powodu niskiej glikemii).Ustawienie MaxIOB na zero zapobiega wystąpieniu hipoglikemii poprzez uniemożliwienie pętli podania insuliny powyżej dawki bazowej (z wyjątkiem sytuacji z ujemnym IOB)Dostrajanie zamkniętej pętli, podniesienie wartości max IOB powyżej 0 i stopniowe obniżanie docelowego poziomu cukru (BG target)Używaj pętli przez kilka dni i przynajmniej jedną noc bez żadnego alarmu niskiego poziomu, przed obniżeniem docelowego poziomu cukru
+ Aktualizuj MaxIOB wraz ze wzrostem i rozwojem dziecka. Nie pozwalaj systemowi na podanie większej ilości insuliny niż można pokryć posiłkami = naprawdę wysoka wartość to zły pomysł. Maksymalna IOB jest obliczana automatycznie w trybie prostym.
+ Maksymalne IOB ustawione poprawnie (nie jest to wymagane w trybie prostym)Dostosuj bazę i wartości parametrów jeśli jest to potrzebne, i wtedy uruchom funkcję autosens1 tydzień sukcesu w działaniu pętli w ciągu dnia z regularnym wprowadzaniem spożywanych węglowodanówJeśli wynik autosens nie oscyluje w okolicach 100%, prawdopodobnie Twój profil nie jest poprawny.
diff --git a/plugins/constraints/src/main/res/values-pl-rPL/strings.xml b/plugins/constraints/src/main/res/values-pl-rPL/strings.xml
index 3b8da95664e..0cb8f35b2a4 100644
--- a/plugins/constraints/src/main/res/values-pl-rPL/strings.xml
+++ b/plugins/constraints/src/main/res/values-pl-rPL/strings.xml
@@ -11,6 +11,7 @@
Aplikacja wygasłaWykryliśmy, że używasz nieprawidlowej wersji. Pętla wyłączona!Wersja %1$s dostępna
+ Wersja %1$s wygasa dnia %2$s, po czym nastąpi przejście w tryb LGSUżyto przeliczonych wartości
diff --git a/plugins/constraints/src/main/res/values-sk-rSK/strings.xml b/plugins/constraints/src/main/res/values-sk-rSK/strings.xml
index cd3b39413d2..4df7f4f1fdb 100644
--- a/plugins/constraints/src/main/res/values-sk-rSK/strings.xml
+++ b/plugins/constraints/src/main/res/values-sk-rSK/strings.xml
@@ -20,7 +20,7 @@
dvojité zápisy\"Ploché\" dáta. Považujú sa za nesprávne.
- Predĺžený bolus obmedzený na %1$.1f JI z dôvodu %2$s
+ Predĺžený bolus obmedzený na %1$.1f U z dôvodu %2$sSacharidy obmedzené na %1$d g: %2$sPumpa nepodporuje dočasné bazályBežiaca vývojárska verzia. Uzavretý okruh je zakázaný.
diff --git a/plugins/constraints/src/main/res/values-vi-rVN/exam.xml b/plugins/constraints/src/main/res/values-vi-rVN/exam.xml
index 6cad8aefbb2..55edeabcf86 100644
--- a/plugins/constraints/src/main/res/values-vi-rVN/exam.xml
+++ b/plugins/constraints/src/main/res/values-vi-rVN/exam.xml
@@ -2,22 +2,22 @@
Điều gì đúng về thời gian hoạt động của Insulin (DIA)?Thời gian tác dụng của Insulin (DIA)
- Bạn nên đặt giá trị DIA trong Cấu hình của mình.
+ Bạn nên đặt giá trị DIA trong Hồ sơ của mình.Giá trị nhỏ nhất được phép là 5 giờ.https://wiki.aaps.app/en/latest/SettingUpAaps/YourAapsProfile.html
- Nếu bạn thấy giá trị DIA mà bạn đã sử dụng trên Pump trước khi dùng AAPS hoạt động tốt, thì không cần thay đổi giá trị này khi bắt đầu chạy vòng kín.
+ Nếu bạn thấy giá trị DIA mà bạn đã sử dụng trên Bơm trước khi dùng AAPS hoạt động tốt, thì không cần thay đổi giá trị này khi bắt đầu chạy vòng kín.Bạn nên tự xác định giá trị DIA phù hợp cho mình.Hypo Temp-TargetTại sao cần đặt mục tiêu tạm thời khi bị hạ đường huyết?
- Để điều chỉnh hạ đường huyết do cài đặt tốc độ basal sai.
+ Để điều chỉnh hạ đường huyết do cài đặt tốc độ liều nền sai.Để ngăn AAPS điều chỉnh quá mức sự tăng đường huyết do carbs tác dụng nhanh được dùng để xử lý hạ đường huyết gây ra.Để điều chỉnh hạ đường huyết do tập thể dục gây ra.
- Để ngăn đường huyết giảm thấp khi đã có tốc độ basal tạm thời 0% đang chạy.
+ Để ngăn đường huyết giảm thấp khi đã có tốc độ liều nền tạm thời 0% đang chạy.https://wiki.aaps.app/en/latest/DailyLifeWithAaps/TempTargets.htmlCác lý do ‘Ngắt kết nối bơm’ trong AAPS
- Điều này không cần thiết vì insulin sẽ không được bơm khi bơm đã được ngắt kết nối vật lý.
- Nó ngăn AAPS tính toán lượng insulin không được bơm khi bơm đã ngắt kết nối vật lý.
- Nó sẽ không dừng việc bơm insulin nếu bơm vẫn được kết nối với cơ thể bạn.
+ Điều này không cần thiết vì insulin sẽ không được tiêm khi bơm đã được ngắt kết nối vật lý.
+ Nó ngăn AAPS tính toán lượng insulin không được tiêm khi bơm đã ngắt kết nối vật lý.
+ Nó sẽ không dừng việc tiêm insulin nếu bơm vẫn được kết nối với cơ thể bạn.Thao tác này sẽ chuyển AAPS sang chế độ vòng lặp mở (open loop).https://wiki.aaps.app/en/latest/DailyLifeWithAaps/AapsScreens.html#loop-statusCài đặt AAPS
@@ -26,7 +26,7 @@
Bạn không cần xuất cài đặt nếu đã ghi chú lại chúng.Hãy xuất cài đặt sau khi bạn hoàn thành một mục tiêu.Hãy xuất cài đặt sau khi bạn thay đổi bất kỳ cài đặt nào.
- Hãy xuất cài đặt sau khi bạn hoàn tất thiết lập ban đầu và đã chỉnh các Tùy chọn(Preferences).
+ Hãy xuất cài đặt của bạn sau khi hoàn tất thiết lập ban đầu và đã đặt các tùy chọn.Hãy xuất cài đặt của bạn ra máy cục bộ bằng menu bảo trì.Tệp cài đặt của bạn nằm trong thư mục Internal Storage/AAPS/preferences trên điện thoại.Hãy sao chép tệp cài đặt của bạn đến một vị trí an toàn bên ngoài điện thoại (ví dụ: dùng lưu trữ đám mây, kết nối cáp với máy tính, gửi email, v.v.)
@@ -40,11 +40,11 @@
Thay thế các cảm biến liên tục bị nhiễu hoặc cho kết quả không chính xác.Xác minh rằng ứng dụng CGM của bạn cung cấp dữ liệu đã được làm mượt (smoothed data).https://wiki.aaps.app/en/latest/CompatibleCgms/SmoothingBloodGlucoseData.html
- Tập luyện và Cấu hình
- Bạn có thể sử dụng các Cấu hình như thế nào để giúp hệ thống xử lý tốt nhất khi tập luyện aerobic?
- Chuyển Cấu hình sang mức dưới 100%.
- Chuyển Cấu hình sang mức hơn 100%.
- Giữ Cấu hình ở mức 100%.
+ Tập luyện và Hồ sơ
+ Bạn có thể sử dụng các Hồ sơ như thế nào để giúp hệ thống xử lý tốt nhất khi tập luyện aerobic?
+ Chuyển Hồ sơ sang mức dưới 100%.
+ Chuyển Hồ sơ sang mức hơn 100%.
+ Giữ Hồ sơ ở mức 100%.Tạm dừng vòng lặp.https://wiki.aaps.app/en/latest/DailyLifeWithAaps/TempTargets.htmlTập luyện và Mục tiêu tạm thời
@@ -70,7 +70,7 @@
https://wiki.aaps.app/en/latest/Getting-Started/ComponentOverview.htmlĐiều kiện cầnĐiều gì là cần thiết để cài đặt và sử dụng AAPS?
- Thông tin đã được xác nhận để thiết lập Cấu hình (ISF, tỷ lệ I:C, basal rate, DIA, v.v.).
+ Thông tin đã được xác nhận để thiết lập Hồ sơ (Độ nhạy insulin, tỷ lệ carb, tỷ lệ liều nền, DIA, v.v.).Một thiết bị Android tương thích (ví dụ: điện thoại, đồng hồ Android đầy đủ chức năng hoặc máy tính bảng).AAPS cần kết nối Internet để chạy ở chế độ vòng lặp kín (closed loop).Một CGM được hỗ trợ và ứng dụng phù hợp để nhận giá trị đường huyết trên điện thoại/thiết bị.
@@ -93,7 +93,7 @@
https://discord.gg/4fQUWHZ4Mwhttps://github.com/nightscout/AndroidAPS/issuesInsulin Plugins
- Bạn nên sử dụng loại insulin nào với plugin Ultra-Rapid Oref?
+ Bạn sử dụng loại insulin nào với Insulin siêu nhanh Oref?Fiasp®NovoRapid®/Novolog®Humalog®
@@ -101,7 +101,7 @@
https://wiki.aaps.app/en/latest/SettingUpAaps/ConfigBuilder.html#insulinPlugin độ nhạy InsulinCác plugin về độ nhạy cho phép AAPS điều chỉnh khi có những thay đổi tạm thời hoặc ngắn hạn trong độ nhạy insulin (ví dụ như thay đổi nội tiết tố hoặc vấn đề hấp thu tại vị trí truyền).
- Các plugin về độ nhạy cung cấp cho người dùng những gợi ý thay đổi về tốc độ nền (basal rates), tỷ lệ I:C và ISF để có thể chỉnh sửa Cấu hình.
+ Các plugin về độ nhạy cung cấp cho người dùng những gợi ý thay đổi về tốc độ nền (basal rates), tỷ lệ I:C và ISF để có thể chỉnh sửa Hồ sơ.Ghi lại việc thay kim (cannula) sẽ đặt lại tỷ lệ Autosens về 100%.Một số tùy chọn plugin có phạm vi thời gian có thể cấu hình, và người dùng có thể tự thiết lập chúng.https://wiki.aaps.app/en/latest/DailyLifeWithAaps/SensitivityDetectionAndCob.html
@@ -111,7 +111,7 @@
Xóa mục nhập sai trong phần Treatments và nhập lại giá trị carb đúng.Tiêm bolus insulin bằng menu mồi dây truyền (infusion set prime).Không cần làm gì – AAPS sẽ tự động điều chỉnh phù hợp.
- Tiêm bolus insulin bằng nút Insulin (bolus) trong phần Tổng quan (Overview).
+ Hãy thực hiện bolus insulin bằng nút Insulin (bolus) trong màn hình Overview.Lỗi trong việc tiêm/nhập insulinBạn nên làm gì nếu nhận được ít insulin hơn so với lịch sử bơm ghi lại, ví dụ do tắc nghẽn, kim truyền (cannula) hỏng hoặc quên gắn lại bơm sau khi tắm?Xóa dữ liệu insulin trong Nightscout Careportal để loại bỏ khỏi lịch sử bơm.
@@ -126,14 +126,14 @@
Tăng IC sẽ làm cho thời gian hấp thu carb được tính toán dài hơnTăng ISF sẽ làm cho thời gian hấp thu carb được tính toán ngắn hơnTăng IC sẽ không ảnh hưởng đến lượng carbs hấp thu được tính toán
- Việc thay đổi tỷ lệ Cấu hình (profile percentage) ảnh hưởng thế nào đến cách tính toán lượng carb còn lại (COB)?
- Đặt Cấu hình ở mức 150% sẽ làm cho thời gian hấp thu carb được tính toán dài hơn
- Cài đặt Cấu hình ở mức 150% sẽ làm cho thời gian hấp thu carb được tính toán ngắn hơn
- Cài đặt Cấu hình ở mức 150% sẽ không ảnh hưởng đến lượng carbs hấp thu được tính toán
+ Việc thay đổi tỷ lệ Hồ sơ (profile percentage) ảnh hưởng thế nào đến cách tính toán lượng carb còn lại (COB)?
+ Đặt Hồ sơ ở mức 150% sẽ làm cho thời gian hấp thu carb được tính toán dài hơn
+ Cài đặt Hồ sơ ở mức 150% sẽ làm cho thời gian hấp thu carb được tính toán ngắn hơn
+ Cài đặt Hồ sơ ở mức 150% sẽ không ảnh hưởng đến lượng carbs hấp thu được tính toánhttps://wiki.aaps.app/en/latest/DailyLifeWithAaps/CobCalculation.htmlGiá trị IOB bị ảnh hưởng bởi các liều nền tạm thời đã được tiêm.
- Basal tạm thời cao sẽ không được bơm khi đường huyết của bạn thấp hơn mục tiêu.
- IOB âm trong một khoảng thời gian dài, khi không có vận động, cho thấy Cấu hình của bạn quá mạnh và cần giảm lượng insulin trong phần cài đặt.
+ Liều nền tạm thời cao sẽ không được bơm khi đường huyết của bạn thấp hơn mục tiêu.
+ IOB âm trong một khoảng thời gian dài, khi không có vận động, cho thấy Hồ sơ của bạn quá mạnh và cần giảm lượng insulin trong phần cài đặt.IOB dương trong một khoảng thời gian dài cho thấy tình trạng kháng insulin hoặc có bữa ăn chưa được ghi nhận.Nhập carbs và bolusChỉ nên sử dụng đơn vị gam để ước tính và ghi lại lượng carbohydrate đã tiêu thụ.
@@ -144,9 +144,9 @@
https://wiki.aaps.app/en/latest/SettingUpAaps/YourAapsProfile.htmle-carbsBạn có thể sử dụng e-carbs (carb mở rộng) cho mục đích gì?
- Để lên lịch nạp carbs trong tương lai, có thể phân bổ theo khoảng thời gian (tương tự như bolus mở rộng phân phối insulin trong một khoảng thời gian).
+ Để lên lịch nạp carbs trong dự kiến, có thể phân bổ theo khoảng thời gian (tương tự như bolus kéo dài phân phối insulin trong một khoảng thời gian).Để ghi lại lượng carb dùng cho vận động ‘carbs tự do’ mà bạn muốn ẩn khỏi AAPS.
- e-carbs (được phân bổ trong tương lai) có thể hỗ trợ AAPS trong việc xử lý các bữa ăn nhiều chất béo/đạm.
+ e-carbs (được phân bổ trong dự kiến) có thể hỗ trợ AAPS trong việc xử lý các bữa ăn nhiều chất béo/đạm.Để ghi lại lượng carbs cứu nguy được dùng để xử lý khi hạ đường huyết.https://wiki.aaps.app/en/latest/DailyLifeWithAaps/ExtendedCarbs.htmlGiám sát từ xa
@@ -160,39 +160,39 @@
Tăng giá trị ISF sẽ dẫn đến việc bơm nhiều insulin hơn để bù cho một lượng carbs nhất định.Giảm giá trị ISF sẽ dẫn đến việc bơm nhiều insulin hơn để điều chỉnh khi đường huyết cao hơn mục tiêu.Tăng hoặc giảm ISF sẽ không ảnh hưởng đến việc bơm insulin khi đường huyết thấp hơn mục tiêu.
- ISF cần được nhập trong phần Tùy chọn (Preferences) của AAPS.
+ Hãy nhập ISF trong Tùy chọn của AAPS.https://wiki.aaps.app/en/latest/SettingUpAaps/YourAapsProfile.html
- Bạn có thể sử dụng nhiều hơn một giá trị tỷ lệ I:C trong Cấu hình của mình.
- Nếu bạn thay đổi ISF trong Cấu hình, bạn cũng luôn cần thay đổi tỷ lệ I:C.
+ Bạn có thể sử dụng nhiều hơn một giá trị tỷ lệ I:C trong Hồ sơ của mình.
+ Nếu bạn thay đổi ISF trong Hồ sơ, bạn cũng luôn cần thay đổi tỷ lệ I:C.Tỷ lệ Insulin trên Carbohydrate (tỷ lệ I:C)Tỷ lệ I:C cao hơn sẽ dẫn đến việc bơm ít insulin hơn cho cùng một lượng carbs.Tỷ lệ I:C thấp hơn sẽ dẫn đến việc bơm ít insulin hơn cho cùng một lượng carbs.https://wiki.aaps.app/en/latest/SettingUpAaps/YourAapsProfile.html
- Chuyển cấu hình
- Khi thiết lập chuyển Cấu hình ở mức 90%, những câu trả lời nào là đúng?
- Tỷ lệ basal sẽ thấp hơn 10%.
+ Chuyển Hồ sơ
+ Khi thiết lập chuyển Hồ sơ ở mức 90%, những câu trả lời nào là đúng?
+ Tỷ lệ liều nền sẽ thấp hơn 10%.ISF sẽ cao hơn 10%.Giá trị tỷ lệ I:C sẽ thấp hơn 10%.Tỷ lệ ISF và I:C sẽ không thay đổi.https://wiki.aaps.app/en/latest/DailyLifeWithAaps/ProfileSwitch-ProfilePercentage.html
- Chuyển Cấu hình
- Khi thiết lập chuyển Cấu hình ở mức 120%, những câu trả lời nào là đúng?
+ Chuyển Hồ sơ
+ Khi thiết lập chuyển Hồ sơ ở mức 120%, những câu trả lời nào là đúng?Mức đường huyết mục tiêu sẽ cao hơn 20%.
- Tỷ lệ basal sẽ cao hơn 20%.
+ Tỷ lệ liều nền sẽ cao hơn 20%.Mức đường huyết mục tiêu sẽ không thay đổi.ISF sẽ cao hơn 20%.
- Chuyển Cấu hình
+ Chuyển Hồ sơNếu bạn thức dậy sớm hơn bình thường 2 giờ, bạn nên thông báo cho AAPS về sự thay đổi lịch trình của mình như thế nào?
- Kích hoạt chuyển Cấu hình với dịch chuyển thời gian là 2
- Kích hoạt chuyển Cấu hình với dịch chuyển thời gian là -2
+ Kích hoạt chuyển Hồ sơ với dịch chuyển thời gian là 2
+ Kích hoạt chuyển Hồ sơ với dịch chuyển thời gian là -2Đặt mục tiêu tạm thời ‘sắp ăn’ (eating soon temporary target).
- Chuyển Cấu hình sang mức lớn hơn 100%.
+ Chuyển Hồ sơ sang mức lớn hơn 100%.https://wiki.aaps.app/en/latest/DailyLifeWithAaps/ProfileSwitch-ProfilePercentage.html
- Thay đổi Cấu hình
- Tốc độ basal, ISF, tỷ lệ I:C, v.v... nên được thiết lập trong Cấu hình.
- Kích hoạt các thay đổi trong cấu hình Nightscout của bạn yêu cầu điện thoại chạy AAPS phải có kết nối Internet.
- Chỉ cần chỉnh sửa Cấu hình để thay đổi các giá trị là đủ để áp dụng các thay đổi.
- Có thể thiết lập nhiều Cấu hình và lựa chọn chúng để thích ứng với các tình huống thay đổi (ví dụ: thay đổi hormone, làm việc theo ca, lối sống ngày thường/cuối tuần).
+ Thay đổi Hồ sơ
+ Tỷ lệ liều nền, ISF, I:C, v.v... nên được thiết lập trong Hồ sơ.
+ Kích hoạt các thay đổi trong Hồ sơ Nightscout của bạn yêu cầu điện thoại chạy AAPS phải có kết nối Internet.
+ Chỉ cần chỉnh sửa Hồ sơ để thay đổi các giá trị là đủ để áp dụng các thay đổi.
+ Có thể thiết lập nhiều Hồ sơ và lựa chọn chúng để thích ứng với các tình huống thay đổi (ví dụ: thay đổi hormone, làm việc theo ca, lối sống ngày thường/cuối tuần).Thuốc khác. Vui lòng đọc tuyên bố dưới đây và đánh dấu vào ô để chấp nhận cam kết.AAPS giảm basal hoặc tạm ngừng bơm insulin để làm tăng đường huyết. Các thuốc thuộc nhóm ức chế SGLT2 (gliflozin) có thể ngăn sự tăng đường huyết và do đó có thể gây ra tình trạng thiếu insulin nguy hiểm dẫn đến DKA.
\nCác tên thương mại thường gặp: Invokana®, Forxiga®, Jardiance®, Steglatro®, Suglat®, Apleway®, Deberza®, Synjardy®, Vokanamet®, Xigduo®.\n\nTôi cam kết rằng sẽ không sử dụng các thuốc này khi đang dùng AAPS hoặc sẽ tắt vòng lặp (loop) trước khi sử dụng các thuốc đó.
diff --git a/plugins/constraints/src/main/res/values-vi-rVN/objectives.xml b/plugins/constraints/src/main/res/values-vi-rVN/objectives.xml
index c516bae9f45..9e8f4e17393 100644
--- a/plugins/constraints/src/main/res/values-vi-rVN/objectives.xml
+++ b/plugins/constraints/src/main/res/values-vi-rVN/objectives.xml
@@ -5,14 +5,14 @@
%1$d. Mục tiêuMục tiêu %1$d chưa được bắt đầuMục tiêu %1$d chưa hoàn thành
- Thiết lập trực quan hóa và theo dõi, cũng như phân tích basal và các tỷ lệ
- Xác minh rằng dữ liệu đường huyết (BG) có sẵn trong Nightscout và dữ liệu insulin từ bơm đang được tải lên
+ Thiết lập trực quan hóa và theo dõi, cũng như phân tích liều nền và các tỷ lệ
+ Xác minh rằng dữ liệu đường huyết có sẵn trong Nightscout và dữ liệu insulin từ bơm đang được tải lênBạn đã thực hiện thiết lập cơ bản cho hệ sinh thái AAPS. Nightscout không bắt buộc để AAPS hoạt động nhưng rất hữu ích cho việc báo cáo hoặc theo dõi bệnh nhân khác. Nếu bạn chỉ dùng Nightscout cho riêng mình thì không cần phải kết nối với NS mọi lúc. Bạn có thể thiết lập để tải dữ liệu, ví dụ chỉ khi có Wi-Fi ở nhà, nhằm tiết kiệm pin.Bắt đầu với chế độ vòng hở (open loop)
- Chạy ở chế độ Vòng hở (Open Loop) trong vài ngày và tự tay thực hiện nhiều basal tạm thời. Thiết lập và sử dụng các mục tiêu tạm thời và mục tiêu tạm thời mặc định (ví dụ cho hoạt động thể chất hoặc xử lý hạ đường huyết bằng carbs)
- Chế độ Vòng hở (Open loop) có thể được sử dụng để đưa ra khuyến nghị nếu bạn không có bơm tương thích hoặc bạn chưa sẵn sàng chuyển sang chế độ vòng kín (closed loop).
- Hiểu về chế độ vòng hở (open loop), bao gồm các khuyến nghị basal tạm thời của nó
- Dựa trên kinh nghiệm đó, quyết định mức basal tối đa nên là bao nhiêu và thiết lập nó trên bơm cũng như trong phần tùy chọn (preferences). Ở chế độ đơn giản (simple mode), giá trị này được tính toán theo khuyến nghị trong wiki và không cần phải tự thiết lập.
+ Chạy ở chế độ Vòng lặp mở (Open Loop) trong vài ngày và tự tay thực hiện nhiều liều nền tạm thời. Thiết lập và sử dụng các mục tiêu tạm thời và mục tiêu tạm thời mặc định (ví dụ cho hoạt động thể chất hoặc xử lý hạ đường huyết bằng carbs)
+ Chế độ Vòng mở có thể được sử dụng để đưa ra khuyến nghị nếu bạn không có bơm tương thích hoặc bạn chưa sẵn sàng chuyển sang chế độ đóng vòng lặp.
+ Hiểu về chế độ vòng hở (open loop), bao gồm các khuyến nghị liều nền tạm thời của nó
+ Dựa trên kinh nghiệm đó, quyết định mức liều nền tối đa nên là bao nhiêu và thiết lập nó trên bơm cũng như trong phần Tùy chọn (preferences). Ở Chế độ đơn giản (simple mode), giá trị này được tính toán theo khuyến nghị trong wiki và không cần phải tự thiết lập.Thực hiện theo khuyến nghịChú ý đến các tính năng an toàn và điều chỉnh các tham số an toàn khi cần thiết.Bắt đầu đóng vòng lặp với chế độ Tạm ngưng khi đường huyết thấp
@@ -22,11 +22,11 @@
Chạy trong vài ngày, và ít nhất một đêm không có cảnh báo hạ đường huyết, trước khi hạ mục tiêu BGCập nhật MaxIOB khi trẻ lớn lên. Đừng để hệ thống bơm nhiều insulin hơn lượng có thể bù bằng thức ăn = đặt giá trị quá cao là một ý tưởng tồi. Trong chế độ đơn giản, MaxIOB được tính tự độngĐặt IOB tối đa đúng cách (Không cần trong chế độ đơn giản)
- Điều chỉnh basal và các tỷ lệ nếu cần, sau đó bật auto-sens
+ Điều chỉnh liều nền và các tỷ lệ nếu cần, sau đó bật auto-sens1 tuần chạy vòng lặp thành công ban ngày với việc nhập carb đều đặn. Trong chế độ đơn giản, mặc định autosens được bật.
- Nếu kết quả autosens của bạn không dao động quanh mức 100% thì có thể cấu hình (profile) của bạn chưa đúng.
+ Nếu kết quả autosens của bạn không dao động quanh mức 100% thì có thể Hồ sơ của bạn chưa đúng.Bật thêm các tính năng để sử dụng ban ngày, chẳng hạn như SMB
- Bạn phải đọc wiki và tăng MaxIOB thì SMB mới hoạt động tốt! Một cách bắt đầu hợp lý là đặt MaxIOB = bolus trung bình mỗi bữa + 3 × basal tối đa trong ngày. Ở chế độ đơn giản, giá trị này được tính tự động theo khuyến nghị trong wiki nên không cần phải cài đặt.
+ Bạn phải đọc wiki và tăng MaxIOB thì SMB mới hoạt động tốt! Một cách bắt đầu hợp lý là đặt MaxIOB = bolus trung bình mỗi bữa + 3 × liều nền tối đa trong ngày. Ở chế độ đơn giản, giá trị này được tính tự động theo khuyến nghị trong wiki nên không cần phải cài đặt.Mục tiêu của bạn là sử dụng SMB. Thuật toán Oref1 được thiết kế để hỗ trợ bạn với các liều bolus. Bạn không nên tiêm toàn bộ bolus cho bữa ăn mà chỉ một phần, rồi để AAPS tiêm phần còn lại nếu cần. Cách này giúp bạn có thêm khoảng an toàn khi ước lượng carb chưa chính xác. Bạn có biết rằng có thể cài đặt phần trăm kết quả của bộ tính bolus để giảm lượng bolus không?Bật tự động hóa (Automation)Đọc tài liệu để hiểu cách tự động hóa hoạt động. Thiết lập các quy tắc đơn giản đầu tiên. Thay vì hành động, hãy để AAPS chỉ hiển thị thông báo. Khi bạn chắc chắn tự động hóa được kích hoạt đúng thời điểm, hãy thay thông báo bằng hành động thật.
@@ -37,28 +37,28 @@
Thực hiện thủ côngHoàn thành: %1$sHọc cách kiểm soát AAPS
- Thực hiện các hành động khác nhau trong AAPS
- Bạn đã học cách sử dụng các thao tác cơ bản của AAPS. Các điều khiển chính nằm trên màn hình Tổng quan (Overview), có thể truy cập bằng nhấp hoặc nhấn giữ; nhiều điều khiển khác nằm ở màn hình Hành động (Action). Bạn cũng nên biết cách đưa màn hình của plugin vào menu cuộn trên cùng hoặc hiển thị trong danh sách plugin đã bật ở góc trên bên trái.
- Đặt Cấu hình 90% trong 10 phút (nhấn giữ tên cấu hình trên màn hình Tổng quan – Overview)
+ Thực hiện các thao tác khác nhau trong AAPS
+ Bạn đã học cách sử dụng các thao tác cơ bản của AAPS. Các điều khiển chính nằm trên màn hình Tổng quan (Overview), có thể truy cập bằng nhấp hoặc nhấn giữ; nhiều điều khiển khác nằm ở màn hình Các thao tác (Action). Bạn cũng nên biết cách đưa màn hình của plugin vào menu cuộn trên cùng hoặc hiển thị trong danh sách plugin đã bật ở góc trên bên trái.
+ Đặt Cấu hình 90% trong 10 phút (nhấn giữ tên Hồ sơ trên màn hình Tổng quan – Overview)Mô phỏng Tắm. Ngắt kết nối bơm trong 1 giờ (nhấn giữ trên Open Loop)… và kết nối lại theo cách tương tự
- Tạo mục tiêu tạm thời tùy chỉnh với thời gian 10 phút (nhấn giữ mục tiêu hiện tại của bạn)
- Trong Config Builder, bật plugin Actions, đặt nó ở chế độ hiển thị và mở nội dung của nó từ menu trên cùng
+ Tạo mục tiêu tạm thời tùy chỉnh với thời gian 10 phút (Nhấn và giữ vào mục tiêu hiện tại của bạn)
+ Trong Xây dựng cấu hình, bật plugin Các thao tác, đặt nó ở chế độ hiển thị và mở nội dung của nó từ menu trên cùngHiển thị nội dung của plugin LoopSử dụng chức năng thu phóng bằng cách nhấn giữ biểu đồ đường huyếtKiểm chứng kiến thức của bạnNghiên cứu các câu hỏi. Bạn sẽ được đưa ra bốn câu trả lời có thể cho mỗi câu hỏi. Có thể có nhiều hơn một đáp án đúng. Vui lòng kiểm tra tất cả những đáp án đúng và chọn XÁC MINH (VERIFY).
- Bạn không cần phải là nhà phát triển, nhưng bạn cần Nightscout để hoàn thành các Mục tiêu (Objectives), một bơm tương thích và một máy tính để xây dựng AAPS lần đầu tiên cũng như cho mỗi lần cập nhật.
+ Bạn không cần phải là nhà phát triển, nhưng bạn cần Nightscout để hoàn thành các Mục tiêu, một bơm tương thích và một máy tính để xây dựng AAPS lần đầu tiên cũng như cho mỗi lần cập nhật.AAPS có thể chạy ở chế độ ngoại tuyến (offline).
- Cấu hình cần được xem xét và cập nhật. Cấu hình càng tốt = kết quả càng tốt.
+ Hồ sơ cần được xem xét và cập nhật. Hồ sơ càng tốt = kết quả càng tốt.DIA trong chế độ vòng kín (looping) có ý nghĩa khác (thời gian cho đến khi toàn bộ insulin được hấp thụ) so với trong liệu pháp bơm insulin cổ điển (thời gian cho đến khi phần lớn insulin được hấp thụ).Bạn đã học được ý nghĩa của giá trị ISF và cách nó ảnh hưởng đến lượng insulin được sử dụng để điều chỉnh đường huyết.Bạn đã học được ý nghĩa của giá trị IC và cách nó ảnh hưởng đến lượng insulin cần thiết để bù cho lượng carbs.
- Mục tiêu tạm thời Hypo (Hypo temp target) chỉ nên được sử dụng để tránh điều chỉnh quá mức sau hạ đường huyết, khi thường có IOB âm tích lũy. Cần xem xét thêm các biện pháp bổ sung để ngăn tình huống này lặp lại trong tương lai.
+ Mục tiêu tạm thời Hypo (Hypo temp target) chỉ nên được sử dụng để tránh điều chỉnh quá mức sau hạ đường huyết, khi thường có IOB âm tích lũy. Cần xem xét thêm các biện pháp bổ sung để ngăn tình huống này lặp lại trong dự kiến.Việc sử dụng tỷ lệ phần trăm không ảnh hưởng đến mục tiêu đường huyết, nhưng basal, ISF và IC sẽ được điều chỉnh để cung cấp nhiều insulin hơn (trên 100%%) hoặc ít insulin hơn (dưới 100%%).
- Bằng cách sử dụng dịch chuyển thời gian trong chuyển đổi Cấu hình, bạn có thể điều chỉnh Cấu hình theo nhịp sinh học để thích ứng với những thay đổi bất thường, như việc thức dậy muộn.
- Chỉ chỉnh sửa Cấu hình thôi là chưa đủ để áp dụng thay đổi. Bạn vẫn cần thực hiện chuyển đổi Cấu hình để kích hoạt các thay đổi.
- Bạn nên giảm lượng insulin trong cơ thể ít nhất 1 giờ trước khi bắt đầu tập thể dục bằng cách chọn Cấu hình dưới 100%.
+ Bằng cách sử dụng dịch chuyển thời gian trong chuyển đổi Hồ sơ, bạn có thể điều chỉnh Hồ sơ theo nhịp sinh học để thích ứng với những thay đổi bất thường, như việc thức dậy muộn.
+ Chỉ chỉnh sửa Hồ sơ thôi là chưa đủ để áp dụng thay đổi. Bạn vẫn cần thực hiện chuyển đổi Hồ sơ để kích hoạt các thay đổi.
+ Bạn nên giảm lượng insulin trong cơ thể ít nhất 1 giờ trước khi bắt đầu tập thể dục bằng cách chọn Hồ sơ dưới 100%.Thiết lập mục tiêu tạm thời cao hơn (higher temp target) ít nhất 1 giờ trước khi tập thể dục cũng giúp giảm lượng insulin trong cơ thể.Khi bạn không tin cậy vào giá trị từ CGM, bạn không nên sử dụng chế độ vòng kín mà không giám sát.AAPS cần biết rằng bơm không được kết nối để tính IOB chính xác.
@@ -68,9 +68,9 @@
Luôn giữ bản xuất (export) cài đặt và file APK đã tạo ở ngoài điện thoại. Điện thoại có thể bị mất, hỏng, v.v. Một nơi tốt để lưu trữ có thể là bất kỳ dịch vụ lưu trữ đám mây nào có thể truy cập từ điện thoại. Trong trường hợp này, bạn có thể khôi phục AAPS trên thiết bị khác chỉ trong vài phút. Thực hành tốt là lưu giữ mật khẩu chính (master password) ở nơi an toàn, vì nếu không có nó thì bản sao lưu sẽ vô dụng. Điều tương tự cũng áp dụng cho các khóa ký (.jks file) và mật khẩu dùng để build AAPS. Những phần còn lại thì không quan trọng – bạn có thể tải lại từ internet bất cứ lúc nào.Nếu bạn nhập sai dữ liệu vào AAPS hoặc dữ liệu không khớp với thực tế, hãy xử lý ngay lập tức. Điều này có thể dẫn đến nguy cơ tiêm quá liều insulin. AAPS luôn cần được cung cấp thông tin chính xác nhất có thể về carbohydrate, insulin, v.v.Nếu bạn phân tích xem AAPS có hoạt động tốt với bạn hay không, việc theo dõi biểu đồ IOB có thể cung cấp cho bạn rất nhiều thông tin hữu ích.
- Việc tính toán COB phụ thuộc vào mối quan hệ giữa ISF và IC. Tăng ISF hoặc giảm IC sẽ dẫn đến thời gian hấp thụ dài hơn. Tuy nhiên, khi chuyển Cấu hình bằng cách thay đổi phần trăm thì cả hai giá trị này đều thay đổi cùng lúc, và do đó thời gian hấp thụ không bị ảnh hưởng.
+ Việc tính toán COB phụ thuộc vào mối quan hệ giữa ISF và IC. Tăng ISF hoặc giảm IC sẽ dẫn đến thời gian hấp thụ dài hơn. Tuy nhiên, khi chuyển Hồ sơ bằng cách thay đổi phần trăm thì cả hai giá trị này đều thay đổi cùng lúc, và do đó thời gian hấp thụ không bị ảnh hưởng.Chỉ được phép nhập carbohydrate theo đơn vị gram.
- E-carbs là sự thay thế cho bolus mở rộng (extended bolus) trong thế giới bơm insulin.
+ E-carbs là sự thay thế cho bolus kéo dài trong thế giới bơm insulin.Giám sát và điều khiển từ xa là có thể, nhưng không phải tất cả các tính năng đều khả dụng từ xa.Trả lời bị vô hiệu hóa cho đến: %1$sCâu trả lời sai!
diff --git a/plugins/constraints/src/main/res/values-vi-rVN/strings.xml b/plugins/constraints/src/main/res/values-vi-rVN/strings.xml
index fc9c537c0fe..1373c28d3e0 100644
--- a/plugins/constraints/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/constraints/src/main/res/values-vi-rVN/strings.xml
@@ -20,14 +20,14 @@
mục nhập képDữ liệu bằng phẳng. Được coi là sai
- Giới hạn liều bolus mở rộng ở %1$.1f U vì %2$s
+ Giới hạn liều bolus kéo dài ở %1$.1f U bởi vì %2$sHạn chế carbs ở mức %1$d g vì %2$s
- Pump không hỗ trợ basal tạm thời
+ Bơm không hỗ trợ liều nền tạm thờiĐang chạy phiên bản phát triển. Vòng lặp kín đã bị vô hiệu hóa.
- Vòng lặp kín bị vô hiệu hóa do đang chạy bolus mở rộng
+ Vòng lặp kín bị vô hiệu hóa do đang chạy bolus kéo dàiSMB luôn bật và SMB sau khi ăn đã bị vô hiệu hóa vì nguồn BG hiện tại không hỗ trợ lọc nâng caoSMB không được phép trong chế độ vòng lặp mở
- giá trị tối đa trong phần Tùy chọn(preferences)
+ giá trị tối đa trong phần Tùy chọngiới hạn cứngAn toàn trong điều trị
diff --git a/plugins/insulin/src/main/res/values-vi-rVN/strings.xml b/plugins/insulin/src/main/res/values-vi-rVN/strings.xml
index 97257e76757..c6a53831cb9 100644
--- a/plugins/insulin/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/insulin/src/main/res/values-vi-rVN/strings.xml
@@ -2,17 +2,17 @@
Lyumjev
- Thiết lập sẵn insulin cho Humalog và NovoRapid / NovoLog
- Thiết lập sẵn insulin Fiasp
- Thiết lập sẵn insulin Lyumjev
+ Thiết lập sẵn cho insulin Humalog và NovoRapid / NovoLog
+ Preset insulin cho Fiasp
+ Preset insulin cho LyumjevCho phép bạn xác định đỉnh hoạt động của insulin và chỉ nên được sử dụng bởi người dùng nâng caoINSThời gian đạt đỉnh IOBThời gian đạt đỉnh [phút]Đỉnh Oref tùy chỉnh
- Rapid-Acting Oref
- Insulin siêu nhanh Oref
- Thời gian tác dụng insulin (DIA) là %1$f quá ngắn – sử dụng %2$f thay thế!
+ Insulin tác dụng nhanh
+ Insulin siêu nhanh
+ DIA %1$f quá ngắn, chuyển sang dùng %2$f!Novorapid, Novolog, HumalogFiasp
diff --git a/plugins/main/build.gradle.kts b/plugins/main/build.gradle.kts
index 2e21a353158..6c724109fec 100644
--- a/plugins/main/build.gradle.kts
+++ b/plugins/main/build.gradle.kts
@@ -39,6 +39,8 @@ dependencies {
api(libs.com.eatthepath.java.otp)
api(libs.com.github.kenglxn.qrgen.android)
+ api(libs.kotlinx.datetime)
+
// Overview
api(libs.com.google.android.flexbox)
diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewDataImpl.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewDataImpl.kt
index 2f56d05c490..c86b204e291 100644
--- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewDataImpl.kt
+++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/overview/OverviewDataImpl.kt
@@ -31,9 +31,15 @@ import app.aaps.core.objects.extensions.isInProgress
import app.aaps.core.objects.extensions.toStringFull
import app.aaps.core.objects.extensions.toStringShort
import com.jjoe64.graphview.series.DataPoint
-import java.util.Calendar
+import kotlinx.datetime.DateTimeUnit
+import kotlinx.datetime.LocalDateTime
+import kotlinx.datetime.TimeZone
+import kotlinx.datetime.plus
+import kotlinx.datetime.toInstant
+import kotlinx.datetime.toLocalDateTime
import javax.inject.Inject
import javax.inject.Singleton
+import kotlin.time.Instant
@Singleton
class OverviewDataImpl @Inject constructor(
@@ -104,15 +110,13 @@ class OverviewDataImpl @Inject constructor(
override fun initRange() {
rangeToDisplay = preferences.get(IntNonKey.RangeToDisplay)
- val calendar = Calendar.getInstance().also {
- it.timeInMillis = System.currentTimeMillis()
- it[Calendar.MILLISECOND] = 0
- it[Calendar.SECOND] = 0
- it[Calendar.MINUTE] = 0
- it.add(Calendar.HOUR, 1)
- }
+ val tz = TimeZone.currentSystemDefault()
+ val now = Instant.fromEpochMilliseconds(System.currentTimeMillis())
+ val local = now.toLocalDateTime(tz)
+ val truncatedHour = LocalDateTime(local.year, local.month, local.day, local.hour, 0)
+ val nextFullHour = truncatedHour.toInstant(tz).plus(1, DateTimeUnit.HOUR, tz)
- toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
+ toTime = nextFullHour.toEpochMilliseconds() + 100000 // a little bit more to avoid wrong rounding - GraphView specific
fromTime = toTime - T.hours(rangeToDisplay.toLong()).msecs()
endTime = toTime
}
diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPlugin.kt
index 8930390e0e5..aa5c35d4b95 100644
--- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPlugin.kt
+++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPlugin.kt
@@ -349,7 +349,7 @@ class SmsCommunicatorPlugin @Inject constructor(
"RESTART" ->
if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.smscommunicator_remote_command_not_allowed)))
- else if (divided.size == 1) processRestart()
+ else if (divided.size == 1) processRestart(receivedSms)
else sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrong_format)))
else ->
@@ -579,8 +579,21 @@ class SmsCommunicatorPlugin @Inject constructor(
}
}
- private fun processRestart() {
- configBuilder.exitApp("SMS", Sources.SMS, true)
+ private fun processRestart(receivedSms: Sms) {
+ val passCode = generatePassCode()
+ val reply = rh.gs(R.string.smscommunicator_restart_reply_with_code, passCode)
+ receivedSms.processed = true
+ messageToConfirm = authRequestProvider.get().with(receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
+ override fun run() {
+ uel.log(
+ Action.EXIT_AAPS, Sources.SMS,
+ rh.gs(R.string.smscommunicator_restarting),
+ ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_restarting))
+ )
+ sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.smscommunicator_restarting)))
+ configBuilder.exitApp("SMS", Sources.SMS, true)
+ }
+ })
}
private fun processPUMP(divided: Array, receivedSms: Sms) {
diff --git a/plugins/main/src/main/res/values-cs-rCZ/strings.xml b/plugins/main/src/main/res/values-cs-rCZ/strings.xml
index fc37bcf5875..107809d4d9f 100644
--- a/plugins/main/src/main/res/values-cs-rCZ/strings.xml
+++ b/plugins/main/src/main/res/values-cs-rCZ/strings.xml
@@ -67,6 +67,8 @@
K pozastavení smyčky na %1$d minut odpověz SMS s kódem %2$sChcete-li obnovit smyčku, odpovězte SMS s kódem %1$sChcete-li zakázat smyčku, odpovězte SMS s kódem %1$s
+ Chcete-li restartovat AAPS, odpovězte pomocí SMS s kódem %1$s
+ AAPS se restartujeDočasný bazál %1$.2fU/h na %2$d minut spuštěnProdloužený bolus %1$.2fU na %2$d min úspěšně spuštěnSacharidy %1$d g byly úspěšně zadány
diff --git a/plugins/main/src/main/res/values-es-rES/strings.xml b/plugins/main/src/main/res/values-es-rES/strings.xml
index 17d3da2ce24..453328fa943 100644
--- a/plugins/main/src/main/res/values-es-rES/strings.xml
+++ b/plugins/main/src/main/res/values-es-rES/strings.xml
@@ -67,6 +67,8 @@
Para suspender el bucle durante %1$d minutos, responde con el código %2$sPara reanudar el bucle, responde con el código %1$sPara desactivar el bucle, responder con el código %1$s
+ Para reiniciar AAPS, responde con el código %1$s
+ AAPS se está reiniciandoBasal temporal %1$.2fU/h durante %2$d minutos iniciada correctamenteBolo extendido de %1$.2fU durante %2$d minutos se inició correctamenteCarbohidratos %1$d g ingresados correctamente
diff --git a/plugins/main/src/main/res/values-it-rIT/strings.xml b/plugins/main/src/main/res/values-it-rIT/strings.xml
index 93e2c15cde3..37d9bef97e0 100644
--- a/plugins/main/src/main/res/values-it-rIT/strings.xml
+++ b/plugins/main/src/main/res/values-it-rIT/strings.xml
@@ -67,6 +67,8 @@
Per sospendere il loop per %1$d minuti rispondi col codice %2$sPer riprendere il loop rispondi col codice %1$sPer disabilitare il loop rispondi col codice %1$s
+ Per riprendere il loop rispondi col codice %1$s
+ AAPS si sta riavviandoBasale temporanea %1$.2fU/h per %2$d min avviata con successoBolo esteso %1$.2fU/h per %2$d min avviato con successoCHO %1$d g inseriti con successo
diff --git a/plugins/main/src/main/res/values-nb-rNO/strings.xml b/plugins/main/src/main/res/values-nb-rNO/strings.xml
index a87cb62f0d0..1e77c6379ba 100644
--- a/plugins/main/src/main/res/values-nb-rNO/strings.xml
+++ b/plugins/main/src/main/res/values-nb-rNO/strings.xml
@@ -67,6 +67,8 @@
For å pause loop i %1$d minutter, svar med kode %2$sFor å gjenoppta loop, svar med kode %1$sFor å deaktivere loop, svar med kode %1$s
+ For å restarte AAPS svar med kode %1$s
+ AAPS restarterVellykket start av midl. basal %1$.2fE/t i %2$d minutterVellykket start av forlenget bolus %1$.2fE i %2$d minutterVellykket registrering av %1$dg KH
@@ -162,7 +164,7 @@
Forlenget bolusAvbryt forlenget bolusVerktøy
- Rotasjon av stedsområder
+ Rotasjon av stedHistorikkSensoralder:
diff --git a/plugins/main/src/main/res/values-nl-rNL/strings.xml b/plugins/main/src/main/res/values-nl-rNL/strings.xml
index 999a800e51a..16254b7757e 100644
--- a/plugins/main/src/main/res/values-nl-rNL/strings.xml
+++ b/plugins/main/src/main/res/values-nl-rNL/strings.xml
@@ -57,6 +57,7 @@
Pomp verbinding verbrokenPomp opnieuw verbondenCommando\'s op afstand zijn niet toegestaan
+ Opdracht op afstand is niet mogelijkBolus op afstand niet beschikbaar. Probeer het later opnieuw.Om een basaal van %1$.2f E/uur gedurende %2$d min te starten, antwoord met code %3$sOm naar profiel %1$s %2$d%% te wisselen antwoord met code %3$s
@@ -66,6 +67,8 @@
Om de loop te onderbreken gedurende %1$d minuten antwoord met de code %2$sOm loop te hervatten antwoord met code %1$sOm loop uit te schakelen antwoord met code %1$s
+ Om AAPS te herstarten, antwoord met code %1$s
+ AAPS wordt opnieuw opgestartTijdelijk basaal %1$.2fE/uur voor %2$d minuten succesvol gestartVertraagde bolus %1$.2fE voor %2$d minuten succesvol gestartKoolhydraten %1$d g succesvol ingevoerd
@@ -128,6 +131,7 @@
ProfielLP
+ Definieer een profiel dat jouw insuline behoeften beschrijft.nieuwe toevoegen aan lijstWilt u van profiel wisselen en gemaakte wijzigingen aan het huidige profiel negeren?Huidige wijzigingen eerst opslaan of resetten
@@ -160,6 +164,7 @@
Vertraagde bolusAnnuleer vertraagde bolusHulpmiddelen
+ Site rotatieHistoriek vensterSensorleeftijd:
diff --git a/plugins/main/src/main/res/values-pl-rPL/strings.xml b/plugins/main/src/main/res/values-pl-rPL/strings.xml
index f27596e204a..4d985582d97 100644
--- a/plugins/main/src/main/res/values-pl-rPL/strings.xml
+++ b/plugins/main/src/main/res/values-pl-rPL/strings.xml
@@ -57,6 +57,7 @@
Pompa odłączonaPompa ponownie podłączonaZdalne komendy nie są dozwolone
+ Zdalne polecenie nie jest możliweBolus zdalny niedostępny. Spróbuj ponownie później.Aby rozpocząć bazę %1$.2f U/h przez %2$d min. odpowiedz kodem %3$sAby przełączyć profil na %1$s %2$d%% odpowiedz kodem %3$s
@@ -128,6 +129,7 @@
ProfilLP
+ Zdefiniuj profil opisujący zapotrzebowanie na insulinę.dodaj nowy do listyCzy chcesz przełączyć profil i porzucić zmiany wprowadzone w bieżącym profilu?Najpierw zapisz lub wycofaj bieżące zmiany
@@ -150,6 +152,8 @@
DIACELBAS
+ Twój algorytm potrafi dostarczyć dynamiczne obliczenia ISF. Wartości poniżej są używane tylko awaryjnie w przypadku braku danych lub wyłącznie jako wartości referencyjne
+ Twój algorytm potrafi dostarczyć dynamiczne obliczenia IC. Wartości poniżej są używane tylko awaryjnie w przypadku braku danych lub wyłącznie jako wartości referencyjneAkcjeNiektóre przyciski umożliwiające szybki dostęp do typowych funkcji
@@ -158,6 +162,7 @@
Bolus PrzedłużonyAnuluj bolus przedłużony Narzędzia
+ Zmiana miejscaPrzegląd historiiSensorczas:
@@ -212,6 +217,7 @@
Wyświetla bieżący stan twojej pętli i przyciski dla większości typowych działańPrzyciskiWysyła kalibrację do xDrip+ (upewnij się, że \'Akceptuj kalibracje\' są włączone w xDrip+ w sekcji \'Ustawienia innych aplikacji\').
+ Otwiera xDrip+ lub aplikację Dexcom (możesz wrócić do AAPS androidowym przyciskiem \"cofnij\").NiedostępneNaruszenie ograniczeńZmień wprowadzone dane!
diff --git a/plugins/main/src/main/res/values-ru-rRU/strings.xml b/plugins/main/src/main/res/values-ru-rRU/strings.xml
index 9d97b0698a2..6aa95ed1aec 100644
--- a/plugins/main/src/main/res/values-ru-rRU/strings.xml
+++ b/plugins/main/src/main/res/values-ru-rRU/strings.xml
@@ -67,6 +67,8 @@
Для приостановки цикла на %1$d мин ответьте кодом %2$sЧтобы возобновить цикл ответьте кодом %1$sЧтобы отключить цикл ответьте кодом %1$s
+ Для перезапуска AAPS ответьте кодом %1$s
+ AAPS перезапускаетсяВрем. базал %1$.2f%% на %2$d мин. начат успешноПролонгированный болюс %1$.2fед. на %2$d мин. начат успешноУглеводы %1$d г введены успешно
diff --git a/plugins/main/src/main/res/values-sk-rSK/strings.xml b/plugins/main/src/main/res/values-sk-rSK/strings.xml
index 397bdc3b526..9ebf830f1b1 100644
--- a/plugins/main/src/main/res/values-sk-rSK/strings.xml
+++ b/plugins/main/src/main/res/values-sk-rSK/strings.xml
@@ -32,10 +32,10 @@
Vypršal časový limit pri čakaní na dokončenie predchádzajúcej komunikácie s pumpouPovolené telefónne čísla+421XXXXXXXXX;+421YYYYYYYYY
- Pre podanie bolusu %1$.2fJI odpovedz SMS kódom %2$s
- Pre podanie bolusu k jedlu %1$.2fJI odpovedz SMS kódom %2$s
+ Pre podanie bolusu %1$.2fU odpovedz SMS kódom %2$s
+ Pre podanie bolusu k jedlu %1$.2fU odpovedz SMS kódom %2$sPre nastavenie dočasného cieľa %1$s odpovedz SMS kódom %2$s
- Pre zrušenie dočasného bazálu odpovedzte SMS s kódom %1$s
+ Pre zrušenie dočasného bazálu odpovedzte SMS kódom %1$sPre vypnutie služby SMS komunikátora odpovedz SMS kódom %1$s.\n\n\Majte na pamäti, že opätovná reaktivácia je možná len priamo na AAPS master telefóne.SMS komunikátor zastavený. Na jeho reaktiváciu, použite AAPS na master telefóne.Pre odoslanie kalibrácie %1$.2f odpovedz SMS kódom %2$s
@@ -43,39 +43,41 @@
Minimálny počet minút, ktorý musí uplynúť medzi jedným vzdialeným bolusom a tým nasledujúcimAspoň koľko minút musí uplynúť, medzi jedným vzdialeným bolusom a tým nasledujúcimPre vašu bezpečnosť, musíte pridať aspoň 2 telefónne čísla, aby ste zmenili toto prednastavenie.
- Bolus %1$.2f JI podaný úspešne
- Bolus na jedlo %1$.2f JI podaný úspešne
+ Bolus %1$.2f U podaný úspešne
+ Bolus na jedlo %1$.2f U podaný úspešneCieľ %1$s na %2$d minútCieľ %1$s na %2$d minút bol úspešne nastavenýDočasný cieľ úspešne zrušenýPovoliť príkazy na diaľku cez SMSUzavretý okruh bol deaktivovanýUzavretý okruh je aktivovaný
- Ak chcete pripojiť pumpu, odpovedzte pomocou SMS s kódom %1$s
+ Ak chcete pripojiť pumpu, odpovedzte pomocou SMS kódom %1$sPripojenie k pumpe zlyhalo
- Ak chcete odpojiť pumpu na %1$d minút, odpovedzte pomocou SMS s kódom %2$s
+ Ak chcete odpojiť pumpu na %1$d minút, odpovedzte pomocou SMS kódom %2$sPumpa odpojenáPumpa bola znovu pripojenáPríkazy na diaľku nie sú povolenéPríkaz na diaľku nie je možnýDiaľkovo ovládaný bolus nie je momentálne povolený. Skúste to neskôr.
- Pre spustenie bazálu %1$.2f JI/h na %2$d min odpovedzte SMS s kódom %3$s
- Pre prepnutie profilu na %1$s %2$d%% odpovedzte SMS s kódom %3$s
- Pre spustenie predĺženého bolusu %1$.2f JI na %2$d min odpovedzte SMS s kódom %3$s
- Pre zadanie %1$dg na %2$s odpovedz SMS kódom %3$s
- Pre spustenie bazálu %1$d%% na %2$d min odpovedzte SMS s kódom %3$s
- Pre pozastavenie uzavretého okruhu na %1$d minút odpovedaj SMS s kódom %2$s
+ Pre spustenie bazálu %1$.2f U/h na %2$d min odpovedzte SMS kódom %3$s
+ Pre prepnutie profilu na %1$s %2$d%% odpovedzte SMS kódom %3$s
+ Pre spustenie predĺženého bolusu %1$.2f U na %2$d min odpovedzte SMS kódom %3$s
+ Pre zadanie %1$dg na %2$s odpovedzte SMS kódom %3$s
+ Pre spustenie bazálu %1$d%% na %2$d min odpovedzte SMS kódom %3$s
+ Pre pozastavenie uzavretého okruhu na %1$d minút odpovedzte SMS kódom %2$sPre obnovenie uzavretého okruhu, odpovedzte SMS s kódom %1$s
- Pre zakázanie uzavretého okruhu, odpovedzte SMS s kódom %1$s
- Dočasný bazál %1$.2fJI/h spustený na %2$d minút
- Predĺžený bolus %1$.2fJI na %2$d min úspešne spustený
+ Pre zakázanie uzavretého okruhu, odpovedzte SMS kódom %1$s
+ Ak chcete reštartovať AAPS, odpovedzte SMS kódom %1$s
+ AAPS sa reštartuje
+ Dočasný bazál %1$.2fU/h spustený na %2$d minút
+ Predĺžený bolus %1$.2fU na %2$d min úspešne spustenýSacharidy %1$d g zadané úspešneZadanie %1$dg sacharidov sa nepodariloDočasný bazál %1$d%% na %2$d minút úspešne spustenýSpustenie dočasného bazálu zlyhaloSpustenie predĺženého bolusu zlyhalo
- Na zastavenie dočasného bazálu odpovedzte SMS s kódom %1$s
- Na zastavenie predĺženého bolusu odpovedzte SMS s kódom %1$s
+ Na zastavenie dočasného bazálu odpovedzte SMS kódom %1$s
+ Na zastavenie predĺženého bolusu odpovedzte SMS kódom %1$sDočasný bazál zrušenýPredĺžený bolus zastavenýZrušenie dočasného bazálu zlyhalo
@@ -186,8 +188,8 @@
Prah kritickej úrovne batérie senzora [%]Prah upozornenia na vek batérie v pumpe [h]Prah kritického veku batérie v pumpe [h]
- Prah upozornenia na úroveň hladiny zásobníka [JI]
- Prah kritickej úrovne hladiny zásobníka [JI]
+ Prah upozornenia na úroveň hladiny zásobníka [U]
+ Prah kritickej úrovne hladiny zásobníka [U]Prah upozornenia na úroveň batérie v pumpe [%]Prah kritickej úrovne batérie v pumpe [%]Kopírovať nastavenia z NS
diff --git a/plugins/main/src/main/res/values-vi-rVN/strings.xml b/plugins/main/src/main/res/values-vi-rVN/strings.xml
index b3478fbd901..cbe63743bd1 100644
--- a/plugins/main/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/main/src/main/res/values-vi-rVN/strings.xml
@@ -4,32 +4,32 @@
Giao tiếp SMSSMSĐiều khiển AAPS từ xa bằng lệnh SMS.
- từ ứng dụng Authenticator cho: %1$s kèm theo mã PIN
+ từ ứng dụng Xác thực cho: %1$s kèm theo mã PINMã PIN bắt buộc bổ sung ở cuối tokenCác chữ số bổ sung cần được ghi nhớ và gắn vào cuối mỗi mật khẩu dùng một lần (OTP) được tạoCài đặt xác thựcMã kiểm tra:OTP + PIN
- Mã xác minh gồm 6 chữ số hiển thị trong ứng dụng Authenticator (gọi là OTP) kèm theo 3 chữ số hoặc nhiều hơn của mã PIN bắt buộc.
- Đặt lại Xác thực (Authenticator)
+ Mã xác thực gồm 6 chữ số hiển thị trong ứng dụng Authenticator (gọi là OTP) kèm theo 3 chữ số hoặc nhiều hơn của mã PIN bắt buộc.
+ Đặt lại các xác thựcĐặt lại khóa Xác thực
- Bạn có chắc chắn muốn đặt lại khóa Authenticator không? Thao tác này sẽ làm vô hiệu hóa tất cả các Authenticator đã được cấu hình, và bạn sẽ cần thiết lập lại chúng.
- Đã tạo khóa Authenticator mới! Hãy dùng mã QR mới để cấu hình lại.
+ Bạn có chắc chắn muốn đặt lại khóa Xác thực không? Thao tác này sẽ làm vô hiệu hóa tất cả các xác thực đã được cấu hình, và bạn sẽ cần thiết lập lại chúng.
+ Đã tạo khóa xác thực mới! Hãy dùng mã QR mới để cấu hình lại.Đang xuất khóa bí mật OTP
- Bạn có chắc chắn muốn sao chép mã bí mật OTP vào bộ nhớ tạm không?\n\nBạn chỉ cần làm điều này nếu ứng dụng Authenticator gặp sự cố khi quét mã QR, bạn muốn nhập thủ công hoặc muốn cấu hình thiết bị OTP phần cứng bằng ứng dụng chuyên dụng.
+ Bạn có chắc chắn muốn sao chép mã bí mật OTP vào bộ nhớ tạm không?\n\nBạn chỉ cần làm điều này nếu ứng dụng Xác thực gặp sự cố khi quét mã QR, bạn muốn nhập thủ công hoặc muốn cấu hình thiết bị OTP phần cứng bằng ứng dụng chuyên dụng.Mã bí mật OTP (dạng Base32) đã được xuất và sao chép vào bộ nhớ tạm. Hãy dán vào ứng dụng Authenticator hoặc thiết bị ghi OTP phần cứng!
- 1. Cài đặt Xác thực (Authenticator)
+ 1. Cài đặt xác thực2. Quét mã để thiết lập mã OTP cho AAPS3. Kiểm tra Mật khẩu dùng một lần (OTP)
- Đặt lại Xác thực (Authenticator)
+ Đặt lại các xác thựcTrên mỗi điện thoại follower, cài ứng dụng Authenticator hỗ trợ TOTP (RFC 6238). Ví dụ miễn phí phổ biến:\n • Authy\n • Google Authenticator\n • LastPass Authenticator\n • FreeOTP Authenticator
- Việc đặt lại Authenticator sẽ làm vô hiệu hóa tất cả các Authenticator đã được cấu hình. Bạn sẽ cần thiết lập lại chúng!
+ Việc đặt lại Xác thực sẽ làm vô hiệu hóa tất cả các xác thực đã được cấu hình. Bạn sẽ cần thiết lập lại chúng!ĐỒNG ÝKÍCH THƯỚC KHÔNG HỢP LỆ!Mã PIN saiMÃ OTP SAISai mã, lệnh đã hủy.
- Quá thời gian chờ do pump chưa hoàn tất giao tiếp trước đó
+ Quá thời gian chờ do Bơm chưa hoàn tất giao tiếp trước đóCác số điện thoại được phép+XXXXXXXXXX;+YYYYYYYYYYĐể tiêm liều bolus %1$.2fU, hãy trả lời với mã %2$s
@@ -54,32 +54,34 @@
Để kết nối bơm, hãy trả lời với mã %1$sKhông thể kết nối với bơmĐể ngắt kết nối bơm trong %1$d phút, hãy trả lời với mã %2$s
- Pump đã ngắt kết nối
+ Bơm đã ngắt kết nốiPump đã kết nối lạiLệnh điều khiển từ xa không được phépKhông thể thực hiện lệnh điều khiển từ xaBolus từ xa hiện không khả dụng. Vui lòng thử lại sau.
- Để bắt đầu liều basal %1$.2f U/h trong %2$d phút, hãy trả lời với mã %3$s
- Để chuyển pCấu hình sang %1$s %2$d%%, hãy trả lời với mã %3$s
- Để bắt đầu liều bolus mở rộng %1$.2f U trong %2$d phút, hãy trả lời với mã %3$s
+ Để bắt đầu liều liều nền %1$.2f U/h trong %2$d phút, hãy trả lời với mã %3$s
+ Để chuyển Hồ sơ sang %1$s %2$d%%, hãy trả lời với mã %3$s
+ Để bắt đầu liều bolus kéo dài %1$.2f U trong %2$d phút, hãy trả lời với mã %3$sĐể nhập %1$d g lúc %2$s, hãy trả lời với mã %3$s
- Để bắt đầu liều basal %1$d%% trong %2$d phút, hãy trả lời với mã %3$s
+ Để bắt đầu liều liều nền %1$d%% trong %2$d phút, hãy trả lời với mã %3$sĐể tạm dừng vòng lặp trong %1$d phút, hãy trả lời với mã %2$sĐể tiếp tục vòng lặp, hãy trả lời với mã %1$sĐể vô hiệu hóa vòng lặp, hãy trả lời với mã %1$s
- Basal tạm thời %1$.2f U/h trong %2$d phút đã được khởi động thành công
- Bolus mở rộng %1$.2f U trong %2$d phút đã được khởi động thành công
+ Để khởi động lại AAPS, hãy trả lời với mã %1$s
+ AAPS đang khởi động lại
+ Liều nền tạm thời %1$.2f U/h trong %2$d phút đã được khởi động thành công
+ Liều Bolus kéo dài %1$.2f U trong %2$d phút đã được khởi động thành côngĐã nhập %1$d g carb thành côngNhập %1$d g carb thất bại
- Basal tạm thời %1$d%% trong %2$d phút đã được khởi động thành công
- Khởi động basal tạm thời thất bại
- Không thể khởi động liều bolus mở rộng
- Để dừng basal tạm thời, hãy trả lời với mã %1$s
- Để dừng liều bolus mở rộng, hãy trả lời với mã %1$s
- Đã hủy liều basal tạm thời
- Đã hủy liều Bolus mở rộng
- Hủy liều basal tạm thời thất bại
- Hủy liều bolus mở rộng thất bại
+ Liều nền tạm thời %1$d%% trong %2$d phút đã được khởi động thành công
+ Khởi động liều nền tạm thời thất bại
+ Không thể khởi động liều bolus kéo dài
+ Để dừng liều nền tạm thời, hãy trả lời với mã %1$s
+ Để dừng liều bolus kéo dài, hãy trả lời với mã %1$s
+ Đã hủy liều liều nền tạm thời
+ Đã hủy liều Bolus kéo dài
+ Hủy liều liều nền tạm thời thất bại
+ Hủy liều bolus kéo dài thất bạiLệnh không xác định hoặc trả lời saiĐang có một liều bolus khác trong hàng chờ. Vui lòng thử lại sau.Thời lượng không đúng
@@ -104,7 +106,7 @@
cách đây %1$d phútTạm dừng (%1$d phút)Đọc trạng thái thất bại
- Đã tạo chuyển đổi Cấu hình
+ Đã tạo chuyển đổi Hồ sơThời gian TBR phải là bội số của %1$d phút và lớn hơn 0.Mã QR để thiết lập mật khẩu dùng một lầnVòng lặp đã tắt
@@ -127,50 +129,50 @@
Chủ đề sángSử dụng giao diện của thiết bị
- Cấu hình
+ Hồ sơLP
- Tạo một cấu hình phản ánh nhu cầu insulin của bạn.
+ Tạo một Hồ sơ phản ánh nhu cầu insulin của bạn.thêm mới vào danh sách
- Bạn có muốn chuyển sang Cấu hình khác và hủy các thay đổi đã thực hiện trên Cấu hình hiện tại không?
+ Bạn có muốn chuyển sang Hồ sơ khác và hủy các thay đổi đã thực hiện trên Hồ sơ hiện tại không?Lưu hoặc đặt lại các thay đổi hiện tại trước
- Xóa Cấu hình hiện tại không?
+ Xóa Hồ sơ hiện tại không?Đơn vị:
- Thiếu tên Cấu hình
+ Thiếu tên Hồ sơLỗi trong các giá trị IC
- Lỗi trong các giá trị Basal
+ Lỗi trong các giá trị liều nềnLỗi trong các giá trị mục tiêu TargetLỗi trong các giá trị ISF
- Một số tên Cấu hình có chứa dấu chấm. \nNS không hỗ trợ điều này. \nCác Cấu hình sẽ không được tải lên NS.
- NS từ chối Cấu hình không hợp lệ: %1$s
+ Một số tên Hồ sơ có chứa dấu chấm. \nNS không hỗ trợ điều này. \nCác Hồ sơ sẽ không được tải lên NS.
+ NS từ chối Hồ sơ không hợp lệ: %1$sHiển thịLỗi
- Chọn Cấu hình để chỉnh sửa
- Tên Cấu hình:
- thêm cấu hình mới
- nhân bản cấu hình hiện tại
- xóa Cấu hình hiện tại
+ Chọn Hồ sơ để chỉnh sửa
+ Tên Hồ sơ:
+ thêm Hồ sơ mới
+ nhân bản Hồ sơ hiện tại
+ xóa Hồ sơ hiện tạiDIATARGBASThuật toán của bạn có thể tính toán ISF động. Các giá trị bên dưới chỉ được dùng như dự phòng khi thiếu dữ liệu hoặc chỉ để tham khảoThuật toán của bạn có thể tính toán IC động. Các giá trị bên dưới chỉ được dùng như dự phòng khi thiếu dữ liệu hoặc chỉ để tham khảo
- Actions
+ Các thao tácMột số nút để truy cập nhanh các tính năng thường dùngACT
- Basal tạm thời
- Bolus mở rộng
- Hủy liều Bolus mở rộng
+ Liều nền tạm thời
+ Bolus kéo dài
+ Hủy liều Bolus kéo dàiCông cụ
- Chuyển vị trí tiêm
- Trình xem lịch sử
+ Chuyển vị trí
+ Xem lịch sửCảm biến
- tuổi:
- mức độ:
+ đã dùng:
+ còn lại:Insulin
- Pin Pump
+ Pin BơmKim truyền
- Việc sử dụng tính năng bolus mở rộng sẽ tạm dừng chế độ vòng lặp kín trong thời gian bolus mở rộng chạy. Bạn có thực sự muốn tiếp tục không?
+ Việc sử dụng tính năng bolus kéo dài sẽ tạm dừng chế độ vòng lặp kín trong thời gian bolus kéo dài chạy. Bạn có thực sự muốn tiếp tục không?cannula agepatch pump agePatch pump
@@ -210,7 +212,7 @@
chất lượng đường huyếtđường máuquá hạn
- Chấp nhận basal tạm thời mới:
+ Chấp nhận liều nền tạm thời mới:CGMOverviewHOME
@@ -272,10 +274,10 @@
Tác động lên đường huyếtThay đổi độ nhạyĐộ lệch
- Lượng carb đang hấp thụ
- Insulin đang còn tác dụng
- Basal
- Insulin tuyệt đối”
+ Carb còn tác dụng
+ Insulin còn tác dụng
+ Liều nền
+ Insulin tuyệt đốiĐộ nhạy thay đổiPREDBAS
@@ -297,7 +299,7 @@
Các nút luôn được hiển thị ở phía dưới màn hìnhMàn hình lớnGiao diện
- cách sử dụng:
+ đã sử dụng:Hiển thị thông báo liên tục với tóm tắt ngắn gọn về hoạt động của vòng lặp
diff --git a/plugins/main/src/main/res/values-zh-rTW/strings.xml b/plugins/main/src/main/res/values-zh-rTW/strings.xml
index bfbd36b32e4..12d716db760 100644
--- a/plugins/main/src/main/res/values-zh-rTW/strings.xml
+++ b/plugins/main/src/main/res/values-zh-rTW/strings.xml
@@ -67,6 +67,8 @@
要暫停循環 %1$d 分鐘請回覆代碼 %2$s要恢復循環請回覆代碼 %1$s要停用循環請回覆代碼 %1$s
+ To restart AAPS reply with code %1$s
+ AAPS 正在重新啟動臨時基礎速率 %1$.2fU/h 持續 %2$d 分鐘已成功開始延長注射 %1$.2fU 持續 %2$d 分鐘已成功開始碳水化合物 %1$d g 已成功輸入
@@ -297,7 +299,7 @@
按鈕總是顯示在螢幕底部大顯示外觀
- 使用情況:
+ 使用量:顯示持續通知,簡要概述您的循環正在執行的操作
diff --git a/plugins/main/src/main/res/values/strings.xml b/plugins/main/src/main/res/values/strings.xml
index 91bfc9c8dc2..3f6575a196b 100644
--- a/plugins/main/src/main/res/values/strings.xml
+++ b/plugins/main/src/main/res/values/strings.xml
@@ -69,6 +69,8 @@
To suspend loop for %1$d minutes reply with code %2$sTo resume loop reply with code %1$sTo disable loop reply with code %1$s
+ To restart AAPS reply with code %1$s
+ AAPS is restartingTemp basal %1$.2fU/h for %2$d min started successfullyExtended bolus %1$.2fU for %2$d min started successfullyCarbs %1$d g entered successfully
diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPluginTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPluginTest.kt
index 5e36cd6274a..988d712814b 100644
--- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPluginTest.kt
+++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/general/smsCommunicator/SmsCommunicatorPluginTest.kt
@@ -155,6 +155,11 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
whenever(rh.gs(R.string.smscommunicator_remote_command_not_allowed)).thenReturn("Remote command is not allowed")
whenever(rh.gs(R.string.sms_wrong_code)).thenReturn("Wrong code. Command cancelled.")
+ whenever(rh.gs(eq(R.string.smscommunicator_restart_reply_with_code), any())).thenAnswer { i: InvocationOnMock ->
+ "To restart AAPS reply with code ${i.arguments[1]}"
+ }
+ whenever(rh.gs(R.string.smscommunicator_restarting)).thenReturn("AAPS is restarting")
+ whenever(rh.gsNotLocalised(R.string.smscommunicator_restarting)).thenReturn("AAPS is restarting")
whenever(rh.gs(R.string.sms_iob)).thenReturn("IOB:")
whenever(rh.gs(R.string.sms_last_bg)).thenReturn("Last BG:")
whenever(rh.gs(R.string.sms_min_ago)).thenReturn("%1\$dmin ago")
@@ -581,11 +586,29 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() {
assertThat(smsCommunicatorPlugin.messages[2].text).isEqualTo(passCode)
assertThat(smsCommunicatorPlugin.messages[3].text).isEqualTo("Pump disconnected")
- //RESTART
+ //RESTART - requires confirmation
+ smsCommunicatorPlugin.messages = ArrayList()
+ sms = Sms("1234", "RESTART")
+ smsCommunicatorPlugin.processSms(sms)
+ assertThat(sms.ignored).isFalse()
+ assertThat(smsCommunicatorPlugin.messages[0].text).isEqualTo("RESTART")
+ assertThat(smsCommunicatorPlugin.messages[1].text).contains("To restart AAPS reply with code")
+ passCode = smsCommunicatorPlugin.messageToConfirm?.confirmCode!!
+ smsCommunicatorPlugin.processSms(Sms("1234", passCode))
+ assertThat(smsCommunicatorPlugin.messages[2].text).isEqualTo(passCode)
+ assertThat(smsCommunicatorPlugin.messages[3].text).isEqualTo("AAPS is restarting")
+
+ //RESTART - wrong code
smsCommunicatorPlugin.messages = ArrayList()
sms = Sms("1234", "RESTART")
smsCommunicatorPlugin.processSms(sms)
assertThat(smsCommunicatorPlugin.messages[0].text).isEqualTo("RESTART")
+ assertThat(smsCommunicatorPlugin.messages[1].text).contains("To restart AAPS reply with code")
+ whenever(otp.checkOTP(anyString())).thenReturn(OneTimePasswordValidationResult.ERROR_WRONG_OTP)
+ smsCommunicatorPlugin.processSms(Sms("1234", "WRONG_CODE"))
+ assertThat(smsCommunicatorPlugin.messages[2].text).isEqualTo("WRONG_CODE")
+ assertThat(smsCommunicatorPlugin.messages[3].text).isEqualTo("Wrong code. Command cancelled.")
+ whenever(otp.checkOTP(anyString())).thenReturn(OneTimePasswordValidationResult.OK)
//HELP
smsCommunicatorPlugin.messages = ArrayList()
diff --git a/plugins/sensitivity/src/main/res/values-vi-rVN/strings.xml b/plugins/sensitivity/src/main/res/values-vi-rVN/strings.xml
index ad031d3154a..647a81a5778 100644
--- a/plugins/sensitivity/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/sensitivity/src/main/res/values-vi-rVN/strings.xml
@@ -13,11 +13,11 @@
Thời gian (giờ) mà dự kiến toàn bộ carb từ bữa ăn sẽ được hấp thụKhoảng thời gian cho autosens [giờ]Số giờ trong quá khứ được dùng để phát hiện độ nhạy (không tính thời gian hấp thụ carb)
- Giá trị mặc định: 1,2\nĐây là giới hạn hệ số nhân cho autosens (và sắp tới là autotune) để đặt mức giới hạn tối đa 20%% đối với tỷ lệ autosens. Điều này sẽ quyết định autosens có thể điều chỉnh basal tối đa bao nhiêu, điều chỉnh ISF xuống thấp nhất bao nhiêu, và đặt mục tiêu BG thấp đến mức nào.
- Giá trị mặc định: 0,7\nĐây là giới hạn an toàn phía ngược lại của autosens, đặt mức trần cho việc autosens có thể điều chỉnh basal xuống thấp nhất bao nhiêu, cũng như điều chỉnh ISF và mục tiêu BG lên cao nhất bao nhiêu.
+ Giá trị mặc định: 1,2\nĐây là giới hạn hệ số nhân cho autosens (và sắp tới là autotune) để đặt mức giới hạn tối đa 20%% đối với tỷ lệ autosens. Điều này sẽ quyết định autosens có thể điều chỉnh liều nền tối đa bao nhiêu, điều chỉnh ISF xuống thấp nhất bao nhiêu, và đặt mục tiêu BG thấp đến mức nào.
+ Giá trị mặc định: 0,7\nĐây là giới hạn an toàn phía ngược lại của autosens, đặt mức trần cho việc autosens có thể điều chỉnh liều nền xuống thấp nhất bao nhiêu, cũng như điều chỉnh ISF và mục tiêu BG lên cao nhất bao nhiêu.Tỷ lệ autosens tối đaTỷ lệ autosens tối thiểu
- Giá trị mặc định: 3,0 (AMA) hoặc 8,0 (SMB). Đây là cài đặt cho mức ảnh hưởng hấp thụ carb mặc định trong mỗi 5 phút. Giá trị mặc định là 3mg/dl/5 phút. Thông số này ảnh hưởng đến tốc độ giảm của COB, và lượng hấp thụ carb được giả định khi tính toán dự đoán đường huyết trong tương lai, trong trường hợp đường huyết giảm nhiều hơn dự kiến hoặc không tăng như mong đợi.
+ Giá trị mặc định: 3,0 (AMA) hoặc 8,0 (SMB). Đây là cài đặt cho mức ảnh hưởng hấp thụ carb mặc định trong mỗi 5 phút. Giá trị mặc định là 3mg/dl/5 phút. Thông số này ảnh hưởng đến tốc độ giảm của COB, và lượng hấp thụ carb được giả định khi tính toán dự đoán đường huyết trong dự kiến, trong trường hợp đường huyết giảm nhiều hơn dự kiến hoặc không tăng như mong đợi.Thời gian tối đa hấp thụ của bữa ăn [giờ]Thời điểm mà mọi bữa ăn được coi là đã hấp thụ xong. Lượng carb còn lại sẽ bị cắt bỏ.
diff --git a/plugins/source/src/main/res/values-nl-rNL/strings.xml b/plugins/source/src/main/res/values-nl-rNL/strings.xml
index 3ba9cfee7d2..ed89d7771eb 100644
--- a/plugins/source/src/main/res/values-nl-rNL/strings.xml
+++ b/plugins/source/src/main/res/values-nl-rNL/strings.xml
@@ -5,6 +5,7 @@
NS BGDownload BG waardes van NightscoutxDrip+ BG
+ Ontvang BG waarden van xDrip+ en compatibele apps (Juggluco etc.).BYODABYODAOntvang BG waarden van de \'Build Your Own Dexcom App\' (BYODA).
@@ -30,6 +31,12 @@
richtingInterval BG generatie minuten
+ Syai
+ Ontvang glucose-gegevens van de Syai/Ottai App.
+ SI App
+ Ontvang glucose gegevens van Patched Sibionic SI App.
+ Sino App
+ Ontvang glucose gegevens van Patched Sino App.
diff --git a/plugins/source/src/main/res/values-pl-rPL/strings.xml b/plugins/source/src/main/res/values-pl-rPL/strings.xml
index b01ccf69fe6..28d57d4d03a 100644
--- a/plugins/source/src/main/res/values-pl-rPL/strings.xml
+++ b/plugins/source/src/main/res/values-pl-rPL/strings.xml
@@ -5,6 +5,7 @@
NS BGPobieraj wartości BG z NightscoutxDrip+ BG
+ Otrzymuj glikemię z xDrip+ i kompatybilnych aplikacji (Juggluco itp.).Dexcom PatchedDEX.PATCH.Pobieraj glikemię ze spatchowanej aplikacji Dexcom.
@@ -24,9 +25,18 @@
Losowa glikemiaGeneruj losowe odczyty glukozy (wyłącznie do celów demonstracyjnych)BG
+ Ustawienia źródła glikemii
+ Akceptuj start sensora
+ Utwórz zdarzenie \"CGM Sensor Insert\" w Careportal automatycznie po odebraniu informacji o starcie sensora z lokalnego źródła glikemiikierunekInterwał generowania glikemii w minutach
+ Syai
+ Otrzymuj glikemię z aplikacji Syai/Ottai.
+ SI App
+ Otrzymuj glikemię z patchowanej aplikacji Sibionic SI.
+ Sino App
+ Otrzymuj glikemię z patchowanej aplikacji Sino.
diff --git a/plugins/source/src/main/res/values-zh-rTW/strings.xml b/plugins/source/src/main/res/values-zh-rTW/strings.xml
index ae5ee26fb0f..f5b04987fb5 100644
--- a/plugins/source/src/main/res/values-zh-rTW/strings.xml
+++ b/plugins/source/src/main/res/values-zh-rTW/strings.xml
@@ -31,7 +31,7 @@
方向血糖生成間隔(分鐘)
- Syai
+ Syai / 歐態從 Syai / 與歐態應用程式接收血糖資料。SI App
diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/nsclientV3/NSClientV3Plugin.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/nsclientV3/NSClientV3Plugin.kt
index e3a4a03c379..4ed7f2e4b07 100644
--- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/nsclientV3/NSClientV3Plugin.kt
+++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/nsclientV3/NSClientV3Plugin.kt
@@ -225,13 +225,18 @@ class NSClientV3Plugin @Inject constructor(
.observeOn(aapsSchedulers.io)
.subscribe({ ev ->
rxBus.send(EventNSClientNewLog("● CONNECTIVITY", ev.blockingReason))
- nsClientV3Service?.let { service ->
- if (ev.connected) {
- when {
- isAllowed && service.storageSocket == null -> setClient() // socket must be created
- !isAllowed && service.storageSocket != null -> stopService()
- }
- if (isAllowed) executeLoop("CONNECTIVITY", forceNew = false)
+ if (ev.connected && isAllowed) {
+ val service = nsClientV3Service
+ if (service == null || service.storageSocket == null)
+ setClient() // (re)create client and WS; WS_CONNECT callback will trigger executeLoop
+ executeLoop("CONNECTIVITY", forceNew = false)
+ // Trigger upload of data that accumulated while offline.
+ // executeLoop may skip when WS is enabled and initial load is done,
+ // but pending outbound data still needs to be pushed.
+ executeUpload("CONNECTIVITY", forceNew = false)
+ } else if (ev.connected && !isAllowed) {
+ nsClientV3Service?.let { service ->
+ if (service.storageSocket != null) stopService()
}
}
rxBus.send(EventNSClientUpdateGuiStatus())
@@ -377,8 +382,8 @@ class NSClientV3Plugin @Inject constructor(
try {
if (nsClientV3Service != null) context.unbindService(serviceConnection)
} catch (_: Exception) {
- nsClientV3Service = null
}
+ nsClientV3Service = null
}
override fun resend(reason: String) {
diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPlugin.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPlugin.kt
index 47b8f5265ab..253b47bfe3e 100644
--- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPlugin.kt
+++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPlugin.kt
@@ -27,6 +27,7 @@ import app.aaps.core.keys.BooleanKey
import app.aaps.core.keys.StringKey
import app.aaps.core.keys.interfaces.Preferences
import app.aaps.core.utils.HtmlHelper
+import app.aaps.core.validators.DefaultEditTextValidator
import app.aaps.core.validators.preferences.AdaptiveStringPreference
import app.aaps.core.validators.preferences.AdaptiveSwitchPreference
import app.aaps.plugins.sync.R
@@ -133,15 +134,54 @@ class TidepoolPlugin @Inject constructor(
super.onStop()
}
+ /**
+ * Check if connectivity settings allow upload
+ * Separates connectivity constraints from auth state management
+ */
+ private fun isConnectivityAllowed(): Boolean = isAllowed
+
+ /**
+ * Initiate upload with improved state management
+ *
+ * Key improvement: Check connectivity BEFORE auth state
+ * - If blocked by connectivity: skip silently without changing auth state
+ * - If allowed: handle auth state transitions normally
+ * - Auth state no longer gets "stuck" in BLOCKED when connectivity is restored
+ */
private fun doUpload(from: String?) {
- //aapsLogger.debug(LTag.TIDEPOOL, "doUpload from $from")
+ aapsLogger.debug(LTag.TIDEPOOL, "doUpload from=$from isAllowed=${isConnectivityAllowed()} status=${authFlowOut.connectionStatus}")
+
+ // IMPROVEMENT: Check connectivity first, before examining auth state
+ // This prevents mixing connectivity constraints with auth state
+ if (!isConnectivityAllowed()) {
+ aapsLogger.debug(LTag.TIDEPOOL, "doUpload $from: Blocked by connectivity settings")
+ // Send status event so user knows why upload is blocked (rate limited to avoid spam)
+ if (rateLimit.rateLimit("tidepool-connectivity-blocked-notification", T.mins(5).secs().toInt())) {
+ rxBus.send(EventTidepoolStatus("Upload blocked by connectivity settings (check WiFi/cellular/battery restrictions)"))
+ }
+ // Don't change auth state - just skip this upload attempt
+ // When connectivity is restored, next doUpload() will proceed normally
+ return
+ }
+
+ // IMPROVEMENT: Clean auth state machine without BLOCKED
+ // Connectivity is handled above, so we only deal with authentication states here
return when (authFlowOut.connectionStatus) {
+ // Authentication needed
AuthFlowOut.ConnectionStatus.NOT_LOGGED_IN -> tidepoolUploader.doLogin(true, "doUpload $from NOT_LOGGED_IN")
AuthFlowOut.ConnectionStatus.FAILED -> tidepoolUploader.doLogin(true, "doUpload $from FAILED")
AuthFlowOut.ConnectionStatus.NO_SESSION -> tidepoolUploader.doLogin(true, "doUpload $from NO_SESSION")
+
+ // Ready to upload
AuthFlowOut.ConnectionStatus.SESSION_ESTABLISHED -> tidepoolUploader.doUpload(from)
- else -> aapsLogger.debug(LTag.TIDEPOOL, "doUpload $from do nothing ${authFlowOut.connectionStatus}")
+ // Transient states - wait for completion
+ AuthFlowOut.ConnectionStatus.FETCHING_TOKEN -> aapsLogger.debug(LTag.TIDEPOOL, "doUpload $from: Already fetching token")
+
+ // REMOVED: BLOCKED case - connectivity is now checked separately above
+ // This prevents the state machine from getting stuck when connectivity changes
+
+ else -> aapsLogger.debug(LTag.TIDEPOOL, "doUpload $from: Unhandled state ${authFlowOut.connectionStatus}")
}
}
@@ -172,36 +212,54 @@ class TidepoolPlugin @Inject constructor(
}
}
+ /**
+ * IMPROVED: Status shows connectivity state for better UX
+ * If blocked by connectivity settings, shows "BLOCKED (connectivity)"
+ * Otherwise shows actual auth state
+ */
override val status: String
- get() = authFlowOut.connectionStatus.name
+ get() = if (!isConnectivityAllowed()) {
+ "BLOCKED (connectivity)"
+ } else {
+ authFlowOut.connectionStatus.name
+ }
+
+ /**
+ * IMPROVED: Write permission requires both connectivity AND auth
+ */
override val hasWritePermission: Boolean
- get() = authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.SESSION_ESTABLISHED
+ get() = isConnectivityAllowed() &&
+ authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.SESSION_ESTABLISHED
+
+ /**
+ * IMPROVED: Connected requires both connectivity AND auth
+ */
override val connected: Boolean
- get() = authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.SESSION_ESTABLISHED
+ get() = isConnectivityAllowed() &&
+ authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.SESSION_ESTABLISHED
override fun addPreferenceScreen(preferenceManager: PreferenceManager, parent: PreferenceScreen, context: Context, requiredKey: String?) {
- if (requiredKey != null && requiredKey != "tidepool_connection_options" && requiredKey != "tidepool_advanced") return
+ if (requiredKey != null && requiredKey != "tidepool_connection_options") return
val category = PreferenceCategory(context)
parent.addPreference(category)
category.apply {
key = "tidepool_settings"
title = rh.gs(R.string.tidepool)
initialExpandedChildrenCount = 0
+ // Add direct preference to make category expandable (like NSClient pattern)
+ // Without this, category with only nested PreferenceScreens is not clickable
+ addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = TidepoolBooleanKey.UseTestServers, summary = R.string.summary_tidepool_dev_servers, title = R.string.title_tidepool_dev_servers))
addPreference(preferenceManager.createPreferenceScreen(context).apply {
key = "tidepool_connection_options"
title = rh.gs(R.string.connection_settings_title)
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.NsClientUseCellular, title = R.string.ns_cellular))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.NsClientUseRoaming, title = R.string.ns_allow_roaming))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.NsClientUseWifi, title = R.string.ns_wifi))
- addPreference(AdaptiveStringPreference(ctx = context, stringKey = StringKey.NsClientWifiSsids, dialogMessage = R.string.ns_wifi_allowed_ssids, title = R.string.ns_wifi_ssids))
+ addPreference(AdaptiveStringPreference(ctx = context, stringKey = StringKey.NsClientWifiSsids, dialogMessage = R.string.ns_wifi_allowed_ssids, title = R.string.ns_wifi_ssids, validatorParams = DefaultEditTextValidator.Parameters(emptyAllowed = true)))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.NsClientUseOnBattery, title = R.string.ns_battery))
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = BooleanKey.NsClientUseOnCharging, title = R.string.ns_charging))
})
- addPreference(preferenceManager.createPreferenceScreen(context).apply {
- key = "tidepool_advanced"
- title = rh.gs(app.aaps.core.ui.R.string.advanced_settings_title)
- addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = TidepoolBooleanKey.UseTestServers, summary = R.string.summary_tidepool_dev_servers, title = R.string.title_tidepool_dev_servers))
- })
+ // Advanced screen removed - UseTestServers moved to top level
}
}
}
\ No newline at end of file
diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/auth/AuthFlowOut.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/auth/AuthFlowOut.kt
index a2ac8fb7b72..f0da1c1781b 100644
--- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/auth/AuthFlowOut.kt
+++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/auth/AuthFlowOut.kt
@@ -96,14 +96,22 @@ class AuthFlowOut @Inject constructor(
}
@Synchronized fun initAuthState() {
- //aapsLogger.debug(LTag.TIDEPOOL, "initAuthState")
authState = AuthState()
- // Set from configuration if exists
- if (preferences.get(TidepoolStringNonKey.ServiceConfiguration).isNotEmpty())
- authState = AuthState(AuthorizationServiceConfiguration.fromJson(preferences.get(TidepoolStringNonKey.ServiceConfiguration)))
- // Check if we have an authorized state
- if (preferences.get(TidepoolStringNonKey.AuthState).isNotEmpty()) {
- authState = AuthState.jsonDeserialize(preferences.get(TidepoolStringNonKey.AuthState))
+ try {
+ // Set from configuration if exists
+ val serviceConfig = preferences.get(TidepoolStringNonKey.ServiceConfiguration)
+ if (serviceConfig.isNotEmpty())
+ authState = AuthState(AuthorizationServiceConfiguration.fromJson(serviceConfig))
+ // Check if we have an authorized state
+ val savedAuthState = preferences.get(TidepoolStringNonKey.AuthState)
+ if (savedAuthState.isNotEmpty()) {
+ authState = AuthState.jsonDeserialize(savedAuthState)
+ }
+ } catch (e: Exception) {
+ aapsLogger.error(LTag.TIDEPOOL, "Failed to restore auth state, resetting", e)
+ authState = AuthState()
+ preferences.put(TidepoolStringNonKey.AuthState, "")
+ preferences.put(TidepoolStringNonKey.ServiceConfiguration, "")
}
aapsLogger.debug(LTag.TIDEPOOL, "Using auth state : ${authState.jsonSerializeString()}")
}
diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/comm/TidepoolUploader.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/comm/TidepoolUploader.kt
index affbc1c4130..eb26cd6005c 100644
--- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/comm/TidepoolUploader.kt
+++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/tidepool/comm/TidepoolUploader.kt
@@ -93,18 +93,43 @@ class TidepoolUploader @Inject constructor(
session = null
}
+ /**
+ * IMPROVED: Simplified login without connectivity checks
+ *
+ * Connectivity is now checked by TidepoolPlugin.doUpload() BEFORE calling this method.
+ * This separation of concerns makes the code clearer and prevents state machine deadlock.
+ *
+ * Old behavior:
+ * - Checked connectivity here and set BLOCKED state
+ * - Auth state could get stuck in BLOCKED
+ *
+ * New behavior:
+ * - Assumes caller already checked connectivity
+ * - Only handles authentication state transitions
+ * - No BLOCKED state to get stuck in
+ */
@Synchronized
fun doLogin(doUpload: Boolean = false, from: String?) {
- //aapsLogger.debug(LTag.TIDEPOOL, "doLogin $from")
- if (!isAllowed) {
- authFlowOut.updateConnectionStatus(AuthFlowOut.ConnectionStatus.BLOCKED)
- aapsLogger.debug(LTag.TIDEPOOL, "Blocked by connectivity settings")
- return
- }
- if (authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.SESSION_ESTABLISHED || authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.FETCHING_TOKEN) {
- aapsLogger.debug(LTag.TIDEPOOL, "Already connected")
+ aapsLogger.debug(LTag.TIDEPOOL, "doLogin from=$from doUpload=$doUpload currentStatus=${authFlowOut.connectionStatus}")
+
+ // IMPROVEMENT: Removed connectivity check - caller's responsibility
+ // This prevents mixing connectivity constraints with auth state
+ //
+ // REMOVED CODE:
+ // if (!isAllowed) {
+ // authFlowOut.updateConnectionStatus(AuthFlowOut.ConnectionStatus.BLOCKED)
+ // aapsLogger.debug(LTag.TIDEPOOL, "Blocked by connectivity settings")
+ // return
+ // }
+
+ // Check if already in a connected or connecting state
+ if (authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.SESSION_ESTABLISHED ||
+ authFlowOut.connectionStatus == AuthFlowOut.ConnectionStatus.FETCHING_TOKEN) {
+ aapsLogger.debug(LTag.TIDEPOOL, "Already connected or connecting")
return
}
+
+ // Proceed with authentication
handleTokenLoginAndStartSession(doUpload, from)
}
diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/WearPlugin.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/WearPlugin.kt
index bed229d395c..8167b0dc542 100644
--- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/WearPlugin.kt
+++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/wear/WearPlugin.kt
@@ -91,7 +91,7 @@ class WearPlugin @Inject constructor(
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventOverviewBolusProgress ->
if (!BolusProgressData.isSMB || preferences.get(BooleanKey.WearNotifyOnSmb)) {
- if (isEnabled()) rxBus.send(EventMobileToWear(EventData.BolusProgress(percent = BolusProgressData.percent, status = BolusProgressData.status)))
+ if (isEnabled()) rxBus.send(EventMobileToWear(EventData.BolusProgress(percent = BolusProgressData.percent, status = BolusProgressData.wearStatus)))
}
}, fabricPrivacy::logException)
disposable += rxBus
diff --git a/plugins/sync/src/main/res/values-nl-rNL/strings.xml b/plugins/sync/src/main/res/values-nl-rNL/strings.xml
index 0b374d378ef..262b7e7811f 100644
--- a/plugins/sync/src/main/res/values-nl-rNL/strings.xml
+++ b/plugins/sync/src/main/res/values-nl-rNL/strings.xml
@@ -21,12 +21,16 @@
Niet ondersteunde versie van NightscoutOAPSUPLD
+ NSClient storing. Overweg een herstart van NS en NSClient.NSCLIENT heeft geen schrijfrechten. Verkeerde API secret?NSv3
+ NSClientNSv1URL:Herstart
+ NSClientV1
+ NSClientV3Nightscout URLVoer je Nightscout URL in (bijv. https://jouwwebsitenaam.jouwplatform.dom)Nightscout API secret
@@ -45,12 +49,19 @@
Ontvang profiel opslagSynchroniseer profielen van NS profiel editorOntvang tijdelijke doelen
+ Accepteer tijdelijke doelen ingevoerd in NS of NSClientOntvang profielwissels
+ Accepteer profielwisselingen zoals ingevoerd in NS of NSClient
+ Ontvang Running mode gebeurtenissen
+ Accepteer Running mode gebeurtenissen ingevoerd via NS of AAPSClientOntvang TBR en EBAccepteer TBR en EB ingevoerd vanaf een andere bronOntvang insuline
+ Accepteer insuline zoals ingevoerd in NS of AAPSClient (insuline wordt niet toegediend, het wordt alleen in IOB calculatie meegenomen)Ontvang koolhydraten
+ Accepteer koolhydraten ingevoerd in NS of AAPSClientAccepteer behandelingen
+ Accepteer therapie gebeurtenissen (cannula, insuline, batterijwissel etc) ingevoerd via NS of AAPSClientOntvang / backfill CGM gegevensAccepteer CGM data van NSVertraag uploads
@@ -64,6 +75,7 @@
Verbind met websocketsInschakelen betekent: snellere updates, ontvangen van alarmen, aankondigingen en een hoger batterijverbruik, vergelijkbaar met v1. Alle andere uploaders naar NS moeten gebruik maken van het v3 protocol.
+ Indien ingeschakeld zullen uploads naar de test servers gaan in plaats van de standaard serversGebruik integratie (test) serversTidepoolTDP
@@ -112,6 +124,7 @@
Min BG buiten bereik!Max BG buiten bereik!Ongeldig bereik: Laag streefdoel (%1$s) kan niet groter zijn dan hoog streefdoel (%2$s)
+ Tijdelijk streefdoel:\n\nMin: %1$s\nMax: %2$s\nDuur: %3$d minutenTijdelijk streefdoel:\n\nDoel: %1$s\nDuur: %2$d minutenTijdelijk streefdoel:\n\nReden: %1$s\nDoel: %2$s\nDuur: %3$d minutenNiet geslaagd - controleer de telefoon
@@ -144,6 +157,7 @@
guGeen actieve profielwissel!
+ Profiel: %1$s\nTijdsverschuiving: %2$d h\nPercentage: %3$d%%\nDuur: %4$d minStreefdoelen zijn alleen van toepassing in de APS modus!Geen geschiedenisgegevens!Tijdelijk streefdoel
@@ -156,6 +170,7 @@
Laatste resultaat niet beschikbaar!GESLOTEN LOOPOPEN LOOP
+ LGSLOOP UITGESCHAKELDAPSLaatst uitgevoerd
@@ -164,4 +179,24 @@
VandaaggewogenVolledige synchronisatie? Het kan enige tijd duren en tot het is voltooid zie je geen nieuwe gegevens in xDrip+.
+ AAPSClient wordt niet ondersteund voor deze actie
+ Deze actie vereist een tijdsduur
+ Pomp is onderbroken!
+ Profiel ongeldig!
+ Probeer het opnieuw.
+ Ongeldige loop status aangevraagd
+ LOOP STATUS
+ %1$s\nDuur: %2$d min
+ Gesloten
+ LGS
+ Open
+ Onderbroken
+ Hervat
+ Uitgeschakeld
+ Pomp is onderbroken
+ Superbolus
+ Ongeldig
+ Pomp verbinding verbroken
+ Sleutel aanvragen
+ Optionele sleutel om de HTTP communicatie tussen het Garmin apparaat en AAPS te beveiligen.
diff --git a/plugins/sync/src/main/res/values-pl-rPL/strings.xml b/plugins/sync/src/main/res/values-pl-rPL/strings.xml
index 09d82369c08..fe05207b474 100644
--- a/plugins/sync/src/main/res/values-pl-rPL/strings.xml
+++ b/plugins/sync/src/main/res/values-pl-rPL/strings.xml
@@ -21,12 +21,16 @@
Niewspierana wersja NightscoutOAPSUPLD
+ Usterka NSClient. Spróbuj zrestartować NS i NSClient.NSCLIENT nie ma uprawnień do zapisu. Błędny API secret?NSv3
+ NSClientNSv1URL:Restart
+ NSClientV1
+ NSClientV3Nightscout URLWprowadź swój adres URL Nightscout (np.: https://twojastrona.twojaplatforma.domena.pl)Nightscout API secret
@@ -45,12 +49,19 @@
Odbieraj zapisane profileSynchronizuj profile z edytorem profilów NSOdbieraj cele tymczasowe
+ Akceptuj cele tymczasowe wprowadzone przez NS lub AAPSClientOdbieraj zmiany profilu
+ Akceptuj zmiany profilu wprowadzone przez NS lub AAPSClient
+ Odbieraj zmiany trybu pracy
+ Akceptuj zdarzenia o zmianie trybu pracy wprowadzone przez NS lub AAPSClientOtrzymuj TBR i EBAkceptuj TBR (bazy tymczasowe) i EB (bolusy przedłużone) wprowadzone przez inną instancjęOdbieraj wpisy o insulinie
+ Akceptuj wpisy o insulinie wprowadzone przez NS lub AAPSClient (insulina nie zostanie podana, jedynie obliczona do IOB)Odbieraj wpisy o węglowodanach
+ Akceptuj węglowodany wprowadzone przez NS lub AAPSClientOdbieraj zdarzenia związane z leczeniem
+ Akceptuj zdarzenia związane z leczeniem (kaniula, insulina, zmiana baterii itp.) wprowadzone przez NS lub AAPSClientOdbieraj/uzupełnij dane CGMAkceptuj dane CGM z NSWysyłaj dane wolniej
@@ -64,6 +75,7 @@
Połącz używając websocketsWłączenie tej opcji oznacza: szybsze aktualizacje, otrzymywanie alarmów i powiadomień z NS oraz większe zużycie baterii, podobne do v1. Wszystkie inne źródła nadające do NS muszą używać protokołu v3.
+ Jeśli ta opcja jest włączona, dane przesyłane są na serwery testowe zamiast zwykłychUżyj serwerów integracyjnych (testowych)TidepoolTDP
@@ -106,9 +118,15 @@
Wybrany szybki bolus nie jest już dostępny, odśwież swój kafelekSzybki bolus: %1$s\nInsulina: %2$.2fU\nWęgle: %3$dgWybranaa akcja użytkownika %1$s nie jest już dostępna, odśwież swój kafelek
+ Anulować bieżący cel tymczasowy?Różne jednostki używane na zegarku i telefonie!
+ Zerowy cel tymczasowy - anulować bieżący cel tymczasowy?Min-BG poza zakresem!Max-BG poza zakresem!
+ Nieprawidłowy zakres: Niski cel (%1$s) nie może być większy niż wysoki cel (%2$s)
+ Cel tymczasowy:\n\nMin: %1$s\nMax: %2$s\nCzas trwania: %3$d min
+ Cel tymczasowy:\n\nCel: %1$s\nCzas trwania: %2$d min
+ Cel tymczasowy:\n\nPowód: %1$s\nCel: %2$s\nCzas trwania: %3$d minnie udało się - proszę sprawdzić telefonUstawienia WearSterowanie z zegarka
@@ -139,6 +157,7 @@
ghNie ustawiono aktywnego profilu!
+ Profil: %1$s\nPrzesunięcie czasu: %2$d h\nProcent: %3$d%%\nCzas trwania: %4$d minCele mają zastosowanie tylko w trybie APS!Brak danych historycznych!Cel tymczasowy
@@ -151,6 +170,7 @@
Ostatni wynik niedostępny!ZAMKNIĘTA PĘTLAOTWARTA PĘTLA
+ LGSPĘTLA WYŁĄCZONAAPSOstatnie uruchomienie
@@ -159,4 +179,24 @@
DziśważoneWykonać pełną synchronizację? Może ona trochę potrwać i aż do jej zakończenia nie zobaczysz nowych danych w xDrip+.
+ AAPSClient nie jest obsługiwany dla tej akcji
+ Ta akcja wymaga podania czasu trwania
+ Pompa jest wstrzymana!
+ Nieprawidłowy profil!
+ Proszę spróbować ponownie.
+ Żądanie nieprawidłowego stanu pętli
+ STAN PĘTLI
+ %1$s\nCzas trwania: %2$d min
+ Zamknięta
+ LGS
+ Otwarta
+ Zawieszona
+ Wznowiona
+ Wyłączona
+ Pompa wstrzymana
+ Superbolus
+ Nieprawidłowy
+ Pompa odłączona
+ Klucz zapytania
+ Opcjonalny klucz do zabezpieczenia komunikacji HTTP między urządzeniem Garmin a AAPS.
diff --git a/plugins/sync/src/main/res/values-ru-rRU/strings.xml b/plugins/sync/src/main/res/values-ru-rRU/strings.xml
index afab0c11bf3..5e5a7d378fd 100644
--- a/plugins/sync/src/main/res/values-ru-rRU/strings.xml
+++ b/plugins/sync/src/main/res/values-ru-rRU/strings.xml
@@ -69,7 +69,7 @@
Создать уведомления из оповещений NSСоздать уведомления из оповещений NSПорог оповещения об устаревших данных [min] (мин)
- Порог тревоги об устаревших данных [min] (мин)
+ Порог оповещения об устаревших данных [min] (мин)Передать в NS запись о начале работы приложенияКопировать настройки NS (если есть)?Подключаться к веб-сокету
diff --git a/plugins/sync/src/main/res/values-sk-rSK/strings.xml b/plugins/sync/src/main/res/values-sk-rSK/strings.xml
index ec7387eaf9f..30c5bd80d30 100644
--- a/plugins/sync/src/main/res/values-sk-rSK/strings.xml
+++ b/plugins/sync/src/main/res/values-sk-rSK/strings.xml
@@ -114,9 +114,9 @@
(Žiadne hodinky nie sú pripojené)Stav pumpyStav uzavretého okruhu
- Kalkulačka: \nInzulín: %1$.2fJI\nSacharidy: %2$dg
+ Kalkulačka: \nInzulín: %1$.2fU\nSacharidy: %2$dgVybraný rýchly bolus už nie je k dispozícii, obnovte prosím dlaždicu
- Rýchly bolus: %1$s\nInzulín: %2$.2fJI\nSacharidy: %3$dg
+ Rýchly bolus: %1$s\nInzulín: %2$.2fU\nSacharidy: %3$dgVybratá akcia užívateľa %1$s už viac nie je dostupná, prosím obnovte svoju dlaždicuZrušenie bežiaceho dočasného cieľa?Použité rozdielne jednotky v hodinkách a v telefóne!
@@ -153,7 +153,7 @@
Zoznam polí zahrnutých do ciferníkapokus o načítanie dát z pumpy.CDD: Stále staré dáta! Nie je možné načítať z pumpy.
- JI
+ UghNie je nastavený žiadny aktívny profil!
@@ -164,7 +164,7 @@
až doŠTANDARDNÝ ROZSAHcieľ
- Rýchlosť: %1$.2fJI/h (%2$.2f%%) \nTrvanie %3$d min
+ Rýchlosť: %1$.2fU/h (%2$.2f%%) \nTrvanie %3$d minNie je vybraný žiadny profilPoužiť iba v APS móde!Posledný výsledok nie je k dispozícii!
@@ -175,7 +175,7 @@
APSPosledné spustenieNaposledy vykonané
- %1$.2fJI %1$.0f%%
+ %1$.2fU %1$.0f%%DnesváženýÚplná synchronizácia? Môže to chvíľu trvať a kým neskončí, neuvidíte nové dáta v xDrip+.
diff --git a/plugins/sync/src/main/res/values-vi-rVN/oh_strings.xml b/plugins/sync/src/main/res/values-vi-rVN/oh_strings.xml
index fc773044f69..e351b22ca25 100644
--- a/plugins/sync/src/main/res/values-vi-rVN/oh_strings.xml
+++ b/plugins/sync/src/main/res/values-vi-rVN/oh_strings.xml
@@ -25,12 +25,12 @@
Dữ liệu đã được tải lênGiá trị đường huyếtLiều bolus
- Liều Bolus mở rộng
+ Liều Bolus kéo dàiCarbohydratesSự kiện Careportal (trừ ghi chú)
- Chuyển Cấu hình
+ Chuyển Hồ sơTổng liều dùng hàng ngày
- Basal tạm thời
+ Tỷ lệ liều nền tạm thờiMục tiêu Tạm thờiCài đặtPhiên bản ứng dụng
diff --git a/plugins/sync/src/main/res/values-vi-rVN/strings.xml b/plugins/sync/src/main/res/values-vi-rVN/strings.xml
index c099b99cb5e..02d1e9a8491 100644
--- a/plugins/sync/src/main/res/values-vi-rVN/strings.xml
+++ b/plugins/sync/src/main/res/values-vi-rVN/strings.xml
@@ -43,19 +43,19 @@
Xóa nhật kýĐồng bộ toàn bộĐồng bộ toàn bộ? Quá trình này có thể mất nhiều giờ và cho đến khi hoàn tất, bạn sẽ không thấy dữ liệu mới trong NS.
- Synchronization
- Cấu hình, bolus, carb và basal tạm thời được tải lên NS
+ Đồng bộ hóa
+ Hồ sơ, bolus, carb và liều nền tạm thời được tải lên NSTải dữ liệu lên NS
- Nhận dữ liệu cấu hình đã lưu
- Đồng bộ cấu hình từ trình chỉnh sửa cấu hình của NS
+ Nhận dữ liệu Hồ sơ đã lưu
+ Đồng bộ Hồ sơ từ trình chỉnh sửa Hồ sơ của NSNhận mục tiêu tạm thờiChấp nhận mục tiêu tạm thời từ NS hoặc AAPSClient
- Nhận chuyển đổi cấu hình
- Chấp nhận chuyển đổi cấu hình được nhập qua NS hoặc AAPSClient
+ Nhận chuyển đổi Hồ sơ
+ Chấp nhận chuyển đổi Hồ sơ được nhập qua NS hoặc AAPSClientNhận sự kiện Running modeChấp nhận sự kiện Running mode từ NS hoặc AAPSClientNhận TBR và EB
- Chấp nhận basal tạm thời (TBR) và bolus mở rộng (EB) được nhập từ một phiên bản khác
+ Chấp nhận liều nền tạm thời (TBR) và bolus mở rộng (EB) được nhập từ một phiên bản khácNhận insulinChấp nhận insulin được nhập qua NS hoặc AAPSClient (không được bơm, chỉ tính vào IOB)Nhận carb
@@ -112,7 +112,7 @@
WEARTheo dõi và điều khiển AAPS từ đồng hồ WearOS.(Không có đồng hồ kết nối)
- Trạng thái Pump
+ Trạng thái BơmTrạng thái vòng lặpCalc. Wizard:\nInsulin: %1$.2fU\nCarbs: %2$dgQuickwizard đã chọn không còn khả dụng nữa, vui lòng làm mới ô của bạn
@@ -156,8 +156,8 @@
Ugh
- Không có chuyển đổi cấu hình nào hoạt động!
- Cấu hình: %1$s\nDịch chuyển thời gian: %2$d giờ\nPhần trăm: %3$d%%\nThời lượng: %4$d phút
+ Không có chuyển đổi Hồ sơ nào hoạt động!
+ Hồ sơ: %1$s\nDịch chuyển thời gian: %2$d giờ\nPhần trăm: %3$d%%\nThời lượng: %4$d phútCác mục tiêu chỉ áp dụng trong chế độ APS!Không có dữ liệu lịch sử!Mục tiêu tạm thời
@@ -165,7 +165,7 @@
PHẠM VI MẶC ĐỊNHmục tiêuTốc độ: %1$.2fU/giờ (%2$.2f%%) \nThời gian: %3$d phút
- Không có cấu hình nào được tải
+ Không có Hồ sơ nào được tảiChỉ áp dụng trong chế độ APS!Kết quả không khả dụng!ĐÓNG VÒNG LẶP
@@ -182,7 +182,7 @@
AAPSClient không được hỗ trợ cho hành động nàyHành động này yêu cầu thời gian thực hiệnBơm đã tạm dừng!
- Cấu hình không hợp lệ!
+ Hồ sơ không hợp lệ!Vui lòng thử lại.Trạng thái vòng lặp không hợp lệTRẠNG THÁI VÒNG LẶP
@@ -196,7 +196,7 @@
Bơm đã tạm dừngSuperbolusKhông hợp lệ
- Pump đã ngắt kết nối
+ Bơm đã ngắt kết nốiRequest KeyKhóa tùy chọn giúp bảo mật kết nối HTTP giữa Garmin và AAPS.
diff --git a/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPluginTest.kt b/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPluginTest.kt
index 151adbe449d..9b5a715a7be 100644
--- a/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPluginTest.kt
+++ b/plugins/sync/src/test/kotlin/app/aaps/plugins/sync/tidepool/TidepoolPluginTest.kt
@@ -1,16 +1,24 @@
package app.aaps.plugins.sync.tidepool
+import app.aaps.core.interfaces.logging.L
import app.aaps.core.interfaces.ui.UiInteraction
import app.aaps.plugins.sync.nsclient.ReceiverDelegate
+import app.aaps.plugins.sync.nsShared.events.EventConnectivityOptionChanged
import app.aaps.plugins.sync.tidepool.auth.AuthFlowOut
import app.aaps.plugins.sync.tidepool.comm.TidepoolUploader
import app.aaps.plugins.sync.tidepool.comm.UploadChunk
import app.aaps.plugins.sync.tidepool.utils.RateLimit
import app.aaps.shared.tests.TestBaseWithProfile
import com.google.common.truth.Truth.assertThat
+import net.openid.appauth.AuthState
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.Mock
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
class TidepoolPluginTest : TestBaseWithProfile() {
@@ -19,6 +27,8 @@ class TidepoolPluginTest : TestBaseWithProfile() {
@Mock lateinit var receiverDelegate: ReceiverDelegate
@Mock lateinit var uiInteraction: UiInteraction
@Mock lateinit var authFlowOut: AuthFlowOut
+ @Mock lateinit var l: L
+ @Mock lateinit var authState: AuthState
private lateinit var tidepoolPlugin: TidepoolPlugin
private lateinit var rateLimit: RateLimit
@@ -36,4 +46,41 @@ class TidepoolPluginTest : TestBaseWithProfile() {
tidepoolPlugin.addPreferenceScreen(preferenceManager, screen, context, null)
assertThat(screen.preferenceCount).isGreaterThan(0)
}
+
+ @Test
+ fun notLoggedInStateTriggersLoginWhenConnectivityRestored() {
+ whenever(authFlowOut.authState).thenReturn(authState)
+ whenever(receiverDelegate.allowed).thenReturn(true)
+ whenever(authFlowOut.connectionStatus).thenReturn(AuthFlowOut.ConnectionStatus.NOT_LOGGED_IN)
+
+ val realUploader = TidepoolUploader(aapsLogger, rxBus, context, preferences, uploadChunk,
+ dateUtil, receiverDelegate, config, l, authFlowOut)
+ val plugin = TidepoolPlugin(aapsLogger, rh, preferences, aapsSchedulers, rxBus, context,
+ fabricPrivacy, realUploader, uploadChunk, rateLimit,
+ receiverDelegate, uiInteraction, authFlowOut)
+ plugin.onStart()
+ rxBus.send(EventConnectivityOptionChanged("Connected", true))
+
+ verify(authFlowOut).updateConnectionStatus(eq(AuthFlowOut.ConnectionStatus.FETCHING_TOKEN), eq("Connecting"))
+ plugin.onStop()
+ }
+
+ @Test
+ fun uploadSkippedWhenConnectivityNotAllowed() {
+ whenever(authFlowOut.authState).thenReturn(authState)
+ whenever(receiverDelegate.allowed).thenReturn(false)
+ whenever(authFlowOut.connectionStatus).thenReturn(AuthFlowOut.ConnectionStatus.NOT_LOGGED_IN)
+
+ val realUploader = TidepoolUploader(aapsLogger, rxBus, context, preferences, uploadChunk,
+ dateUtil, receiverDelegate, config, l, authFlowOut)
+ val plugin = TidepoolPlugin(aapsLogger, rh, preferences, aapsSchedulers, rxBus, context,
+ fabricPrivacy, realUploader, uploadChunk, rateLimit,
+ receiverDelegate, uiInteraction, authFlowOut)
+ plugin.onStart()
+ rxBus.send(EventConnectivityOptionChanged("Blocked", false))
+
+ // When connectivity is not allowed, doUpload should return early without attempting login
+ verify(authFlowOut, never()).updateConnectionStatus(eq(AuthFlowOut.ConnectionStatus.FETCHING_TOKEN), any())
+ plugin.onStop()
+ }
}
diff --git a/pump/combov2/src/main/res/values-sk-rSK/strings.xml b/pump/combov2/src/main/res/values-sk-rSK/strings.xml
index d55c047f5d2..393e8a0ec48 100644
--- a/pump/combov2/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/combov2/src/main/res/values-sk-rSK/strings.xml
@@ -66,7 +66,7 @@ Pokiaľ po viac ako ~5 minútach nie je nadviazané žiadne spojenie:\n\n
Nastavenie bazálneho profiluNastavenie %1$d%% dočasného bazálu na %2$d minútZrušenie prebiehajúceho dočasného bazálu
- Podávanie %1$.1f JI
+ Podávanie %1$.1f UNačítavam CDD históriuAktualizácia dátumu a času v pumpeNačítavam stav pumpy
@@ -75,7 +75,7 @@ Pokiaľ po viac ako ~5 minútach nie je nadviazané žiadne spojenie:\n\n
Povoliť podrobné logovanie ComboZískávanie bazálneho profilu; čítanie %1$d. faktoraNastavenie bazálneho profilu; zapisovanie %1$d. faktora
- Podávanie bolusu (podané %1$.1f z %2$.1f JI)
+ Podávanie bolusu (podané %1$.1f z %2$.1f U)Nie je možné podať bolus - pumpa je pozastavenáNedostatok inzulínu v zásobníkuBolus zrušený
diff --git a/pump/combov2/src/main/res/values-vi-rVN/strings.xml b/pump/combov2/src/main/res/values-vi-rVN/strings.xml
index 8dc4625a878..099562d7e3d 100644
--- a/pump/combov2/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/combov2/src/main/res/values-vi-rVN/strings.xml
@@ -8,7 +8,7 @@
Lỗi ComboGọi đường dây nóng để cập nhậtLỗi Bluetooth, hãy ghép đôi lại
- Hết insulin trong ống chứa
+ Bình chứa insulin rỗngHết PinTắc kim/ống dẫn insulinKết thúc chế độ bơm dự phòng
@@ -18,7 +18,7 @@
Kết thúc chế độ bơm cho mượnLỗi ống chứa insulinBộ dây truyền chưa được làm đầy
- Không hỗ trợ liều bolus mở rộng
+ Không hỗ trợ liều bolus kéo dàiAccu-Check Combo v2Ghép đôi với bơmHủy ghép đôi bơm
@@ -28,7 +28,7 @@
Bắt đầu ghép nốiĐang ghép nối ComboCác bước để thực hiện ghép đôi với Combo:\n\n
-1. Trên bơm, vào Cài đặt Bluetooth.\n
+1. Trên bơm, vào Bluetooth Settings\n
2. Kiểm tra xem có thiết bị nào đã được ghép đôi chưa; nếu có, vào màn hình \"Delete device\" trên bơm để delete/unpair thiết bị đó.\n
3. Vào màn hình \"Add device\" trên bơm và bắt đầu quá trình ghép đôi trên bơm.\n
4. Nhấn nút \"Start pairing\" bên dưới để khởi động quá trình ghép đôi trong AndroidAPS.\n
@@ -62,8 +62,8 @@ Nếu sau khoảng 5 phút vẫn chưa thiết lập được kết nối:\n\n
Bị tạm dừngBơm đã tạm dừngĐang thực thi lệnh
- Đang lấy cấu hình basal
- Đang cài đặt cấu hình basal
+ Đang lấy Hồ sơ liều nền
+ Đang cài đặt Hồ sơ liều nềnĐang cài đặt TBR %1$d%% trong %2$d phútĐang hủy TBR hiện tạiĐang tiêm bolus %1$.1f U
@@ -73,8 +73,8 @@ Nếu sau khoảng 5 phút vẫn chưa thiết lập được kết nối:\n\n
Mã PIN không hợp lệ. Kiểm tra xem có nhập sai không. Nếu tình trạng này tiếp diễn, hãy hủy và thử ghép nối lại.Thời gian quét (tính bằng giây)Bật ghi nhật ký chi tiết Combo
- Đang lấy cấu hình basal; đã đọc %1$d hệ số
- Đang thiết lập cấu hình basal; đã ghi %1$d hệ số
+ Đang lấy Hồ sơ liều nền; đã đọc %1$d hệ số(s)
+ Đang thiết lập Hồ sơ liều nền; đã ghi %1$d hệ số(s)Đang tiêm bolus (%1$.1f trong %2$.1f U đã tiêm)Không thể tiêm – bơm đang bị tạm ngưngInsulin trong bình chứa không đủ
@@ -83,7 +83,7 @@ Nếu sau khoảng 5 phút vẫn chưa thiết lập được kết nối:\n\n
Liều Bolus chưa được tiêmKhông thể truy cập dữ liệu bơm; cần ghép nối lại bơmPhát hiện các liều bolus không được ghi nhận. Hủy bolus vì lý do an toàn.
- Hồ sơ basal đang kích hoạt không đúng; profile 1 phải là hồ sơ đang kích hoạt, không phải profile %1$d
+ Hồ sơ liều nền đang hoạt động không đúng; Hồ sơ 1 phải là Hồ sơ đang kích hoạt, không phải Hồ sơ %1$dCảnh báo Combo không được nhận dạngCảnh báo Combo%1$d%% (%2$d phút còn lại)
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/PumpPluginAbstract.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/PumpPluginAbstract.kt
index d7a52fed1a1..0282d0aa277 100644
--- a/pump/common/src/main/kotlin/app/aaps/pump/common/PumpPluginAbstract.kt
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/PumpPluginAbstract.kt
@@ -3,9 +3,13 @@ package app.aaps.pump.common
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
+import android.os.SystemClock
+import android.text.format.DateFormat
+import app.aaps.core.interfaces.utils.DateUtil
import app.aaps.core.data.pump.defs.ManufacturerType
import app.aaps.core.data.pump.defs.PumpDescription
import app.aaps.core.data.pump.defs.PumpType
+import app.aaps.core.data.pump.defs.TimeChangeType
import app.aaps.core.interfaces.constraints.PluginConstraints
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
@@ -24,17 +28,29 @@ import app.aaps.core.interfaces.rx.AapsSchedulers
import app.aaps.core.interfaces.rx.bus.RxBus
import app.aaps.core.interfaces.rx.events.EventAppExit
import app.aaps.core.interfaces.rx.events.EventCustomActionsChanged
+import app.aaps.core.interfaces.rx.events.EventOverviewBolusProgress
+import app.aaps.core.interfaces.utils.DecimalFormatter
import app.aaps.core.interfaces.utils.fabric.FabricPrivacy
+import app.aaps.core.keys.interfaces.LongNonPreferenceKey
import app.aaps.core.keys.interfaces.NonPreferenceKey
import app.aaps.core.keys.interfaces.Preferences
import app.aaps.pump.common.data.PumpStatus
+import app.aaps.pump.common.defs.PumpDriverAction
import app.aaps.pump.common.defs.PumpDriverState
+import app.aaps.pump.common.driver.PumpDriverConfiguration
+import app.aaps.pump.common.driver.PumpDriverConfigurationCapable
+import app.aaps.pump.common.driver.refresh.PumpDataRefreshAction
+import app.aaps.pump.common.driver.refresh.PumpDataRefreshType
+import app.aaps.pump.common.sync.PumpDbEntryCarbs
import app.aaps.pump.common.sync.PumpSyncEntriesCreator
import app.aaps.pump.common.sync.PumpSyncStorage
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import io.reactivex.rxjava3.disposables.CompositeDisposable
+import org.json.JSONException
+import org.json.JSONObject
import javax.inject.Provider
+import app.aaps.core.ui.R as Rc
/**
* Created by andy on 23.04.18.
@@ -54,21 +70,37 @@ abstract class PumpPluginAbstract protected constructor(
var aapsSchedulers: AapsSchedulers,
var pumpSync: PumpSync,
var pumpSyncStorage: PumpSyncStorage,
+ val pumpDriverConfigurationInternal: PumpDriverConfiguration,
+ var decimalFormatter: DecimalFormatter,
+ var dateUtil: DateUtil,
protected val pumpEnactResultProvider: Provider
-) : PumpPluginBase(pluginDescription, ownPreferences, aapsLogger, rh, preferences, commandQueue), Pump, PluginConstraints, PumpSyncEntriesCreator {
+) : PumpPluginBase(pluginDescription = pluginDescription,
+ ownPreferences = ownPreferences,
+ aapsLogger = aapsLogger,
+ rh = rh,
+ preferences = preferences,
+ commandQueue = commandQueue),
+ Pump, PluginConstraints,
+ PumpDriverConfigurationCapable, /*Constraints,*/ PumpSyncEntriesCreator {
protected val disposable = CompositeDisposable()
// Pump capabilities
final override var pumpDescription = PumpDescription()
- //protected set
- protected var serviceConnection: ServiceConnection? = null
+ protected open var serviceConnection: ServiceConnection? = null
protected var serviceRunning = false
protected var pumpState = PumpDriverState.NotInitialized
protected var displayConnectionMessages = false
+ protected var timeChangeType: TimeChangeType? = null
+ protected var hasTimeDateOrTimeZoneChanged = false
+ protected var isDriverInitialized = false
+ protected var firstRun = true
+ protected var isRefresh = false
+ protected val statusRefreshMap: MutableMap = mutableMapOf()
var pumpType: PumpType = PumpType.GENERIC_AAPS
+ get() = field
set(value) {
field = value
pumpDescription.fillFor(value)
@@ -78,27 +110,33 @@ abstract class PumpPluginAbstract protected constructor(
abstract fun initPumpStatusData()
+ open fun hasService(): Boolean {
+ return pumpDriverConfigurationInternal.hasService
+ }
+
override fun onStart() {
super.onStart()
initPumpStatusData()
- serviceConnection?.let { serviceConnection ->
+ if (hasService()) {
val intent = Intent(context, serviceClass)
- context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
+ context.bindService(intent, serviceConnection!!, Context.BIND_AUTO_CREATE)
disposable.add(
- rxBus
- .toObservable(EventAppExit::class.java)
- .observeOn(aapsSchedulers.io)
- .subscribe({ context.unbindService(serviceConnection) }, fabricPrivacy::logException)
- )
+ rxBus
+ .toObservable(EventAppExit::class.java)
+ .observeOn(aapsSchedulers.io)
+ .subscribe({ context.unbindService(serviceConnection!!) }, fabricPrivacy::logException)
+ )
}
serviceRunning = true
onStartScheduledPumpActions()
}
override fun onStop() {
- aapsLogger.debug(LTag.PUMP, model().model() + " onStop()")
- serviceConnection?.let { serviceConnection ->
- context.unbindService(serviceConnection)
+ aapsLogger.debug(LTag.PUMP, model().model + " onStop()")
+ if (hasService()) {
+ serviceConnection?.let { serviceConnection ->
+ context.unbindService(serviceConnection)
+ }
}
serviceRunning = false
disposable.clear()
@@ -166,6 +204,12 @@ abstract class PumpPluginAbstract protected constructor(
override val lastDataTime: Long get() = pumpStatusData.lastConnection
+ override val lastBolusAmount: Double?
+ get() = pumpStatusData.lastBolusAmount
+
+ override val lastBolusTime: Long?
+ get() = if (pumpStatusData.lastBolusTime==null) null else pumpStatusData.lastBolusTime!!.time
+
// base basal rate, not temp basal
override val baseBasalRate: Double
get() {
@@ -204,10 +248,7 @@ abstract class PumpPluginAbstract protected constructor(
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver)
}
- // Status to be passed to NS
- // public JSONObject getJSONStatus(Profile profile, String profileName) {
- // return pumpDriver.getJSONStatus(profile, profileName);
- // }
+
open fun deviceID(): String {
aapsLogger.debug(LTag.PUMP, "deviceID [PumpPluginAbstract] - Not implemented.")
return "FakeDevice"
@@ -225,6 +266,7 @@ abstract class PumpPluginAbstract protected constructor(
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver)
}
+
@Synchronized
override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult {
// Insulin value must be greater than 0
@@ -238,13 +280,51 @@ abstract class PumpPluginAbstract protected constructor(
}
}
+ protected fun incrementStatistics(statsKey: LongNonPreferenceKey) {
+ preferences.inc(statsKey)
+ }
+
+ // TODO check deliverTreatmentMy
+ @Synchronized
+ fun deliverTreatmentMy(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult {
+ return try {
+ if (detailedBolusInfo.insulin == 0.0 && detailedBolusInfo.carbs == 0.0) {
+ // neither carbs nor bolus requested
+ aapsLogger.error("deliverTreatment: Invalid input")
+ pumpEnactResultProvider.get().success(false).enacted(false)
+ .bolusDelivered(0.0)
+ .comment(app.aaps.core.ui.R.string.invalid_input)
+ } else if (detailedBolusInfo.insulin > 0) {
+ // bolus needed, ask pump to deliver it
+ deliverBolus(detailedBolusInfo)
+ } else {
+ detailedBolusInfo.timestamp = System.currentTimeMillis()
+
+ // no bolus required, carb only treatment
+ pumpSyncStorage.addCarbs(PumpDbEntryCarbs(detailedBolusInfo, this))
+
+ val bolusingEvent = EventOverviewBolusProgress(
+ rh = rh, id = detailedBolusInfo.id, percent = 100 )
+ // bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, detailedBolusInfo.carbs.toInt(), detailedBolusInfo.bolusType === BS.Type.SMB, detailedBolusInfo.id)
+ // bolusingEvent.percent = 100
+ rxBus.send(bolusingEvent)
+ aapsLogger.debug(LTag.PUMP, "deliverTreatment: Carb only treatment.")
+ pumpEnactResultProvider.get().success(true).enacted(true)
+ .bolusDelivered(0.0)
+ .comment(Rc.string.ok)
+ }
+ } finally {
+ triggerUIChange()
+ }
+ }
+
protected fun refreshCustomActionsList() {
rxBus.send(EventCustomActionsChanged())
}
override fun manufacturer(): ManufacturerType = pumpType.manufacturer()
override fun model(): PumpType = pumpType
- override fun canHandleDST(): Boolean = false
+ override fun canHandleDST(): Boolean = pumpDriverConfigurationInternal.canHandleDST
protected abstract fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult
@@ -257,4 +337,160 @@ abstract class PumpPluginAbstract protected constructor(
pumpDescription.fillFor(pumpType)
this.pumpType = pumpType
}
+
+ protected fun databaseOperationAfterPumpAction(pumpDriverAction: PumpDriverAction) {
+
+ }
+
+ var logPrefix : String = pumpDriverConfigurationInternal.logPrefix
+
+ override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) {
+ aapsLogger.warn(LTag.PUMP, logPrefix + "Time or TimeZone changed (type=$timeChangeType). ")
+ this.timeChangeType = timeChangeType
+ this.hasTimeDateOrTimeZoneChanged = true
+ }
+
+ override fun getPumpDriverConfiguration(): PumpDriverConfiguration {
+ return this.pumpDriverConfigurationInternal
+ }
+
+ protected fun getTimeInFutureFromMinutes(minutes: Int): Long {
+ return System.currentTimeMillis() + getTimeInMs(minutes)
+ }
+
+ protected fun getTimeInMs(minutes: Int): Long {
+ return minutes * 60 * 1000L
+ }
+
+
+ // PumpDataRefreshCapable
+
+ protected fun startRefreshOfPumpCommands() {
+
+ // check status every minute (if any status needs refresh we send readStatus command)
+ Thread {
+ do {
+ SystemClock.sleep(60000)
+ if (this.isDriverInitialized && !isInPreventConnectMode()) {
+ val statusRefresh = workWithStatusRefresh(
+ PumpDataRefreshAction.GetData, null, null
+ )
+ if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) {
+ if (!commandQueue.statusInQueue()) {
+ commandQueue.readStatus("Scheduled Status Refresh", null)
+ }
+ }
+ doCustomScheduledActions()
+ }
+ } while (serviceRunning)
+ }.start()
+
+ }
+
+
+ @Synchronized
+ protected fun workWithStatusRefresh(
+ action: PumpDataRefreshAction,
+ statusRefreshType: PumpDataRefreshType?,
+ time: Long?,
+ customParameter: Any? = null
+ ): HashMap? {
+ return when (action) {
+ PumpDataRefreshAction.Add -> {
+ statusRefreshMap[statusRefreshType] = time
+ null
+ }
+
+ PumpDataRefreshAction.AddSameAsOther -> {
+ val statusRefreshType2 = customParameter as PumpDataRefreshType
+ val timeFromType = statusRefreshMap[statusRefreshType2]
+ statusRefreshMap[statusRefreshType] = timeFromType
+ null
+ }
+
+ PumpDataRefreshAction.GetData -> {
+ HashMap(statusRefreshMap)
+ }
+
+ PumpDataRefreshAction.Delete -> {
+ statusRefreshMap.remove(statusRefreshType)
+ null
+ }
+ }
+ }
+
+
+ protected open fun doCustomScheduledActions() {
+
+ }
+
+
+ protected fun doWeHaveAnyStatusNeededRefereshing(statusRefresh: Map?): Boolean {
+ aapsLogger.debug(LTag.PUMP, "Do we have status needed to refresh: $statusRefresh, currentTime=${System.currentTimeMillis()}")
+ for ((key, value) in statusRefresh!!) {
+ if (value==null) {
+ aapsLogger.error(LTag.PUMP, "We got key ($key}) with value null.")
+ continue
+ }
+ if (value!! > 0 && System.currentTimeMillis() > value) {
+ return true
+ }
+ }
+ return hasTimeDateOrTimeZoneChanged
+ }
+
+ // protected fun scheduleNextRefresh(refreshType: PumpDataRefreshType) {
+ // scheduleNextRefresh(refreshType, 0)
+ // }
+
+ protected fun scheduleNextRefresh(refreshType: PumpDataRefreshType, additionalTimeInMinutes: Int = 0) {
+ val refreshTime = getRefreshTime(refreshType)
+
+ if (refreshTime>0) {
+ workWithStatusRefresh(
+ PumpDataRefreshAction.Add, refreshType,
+ getTimeInFutureFromMinutes(refreshTime + additionalTimeInMinutes)
+ )
+ } else if (refreshTime==-1) {
+ val statusRefresh = workWithStatusRefresh(
+ PumpDataRefreshAction.GetData, null,
+ null)!!
+
+ if (statusRefresh.containsKey(refreshType)) {
+ workWithStatusRefresh(
+ PumpDataRefreshAction.Delete, refreshType,
+ -1
+ )
+ }
+ }
+ }
+
+ protected fun scheduleNextRefreshWithSpecifiedTime(refreshType: PumpDataRefreshType, whenToRefresh: Long) {
+ workWithStatusRefresh(
+ PumpDataRefreshAction.Add, refreshType,
+ whenToRefresh
+ )
+ }
+
+ protected fun scheduleNextRefreshAtSameTimeAsOtherType(refreshType: PumpDataRefreshType, refreshTypeToCopy: PumpDataRefreshType) {
+ workWithStatusRefresh(
+ action = PumpDataRefreshAction.AddSameAsOther,
+ statusRefreshType = refreshType,
+ time = null,
+ customParameter = refreshTypeToCopy
+ )
+ }
+
+
+ // this method needs to be overwriten in your driver and implement PumpDataRefreshCapable
+ open fun getRefreshTime(pumpDataRefreshType: PumpDataRefreshType): Int {
+ return -1
+ }
+
+
+ open fun isInPreventConnectMode(): Boolean {
+ return false
+ }
+
+
}
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/data/PumpStatus.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/data/PumpStatus.kt
index 6edc8036626..10a421de0fb 100644
--- a/pump/common/src/main/kotlin/app/aaps/pump/common/data/PumpStatus.kt
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/data/PumpStatus.kt
@@ -1,7 +1,9 @@
package app.aaps.pump.common.data
import app.aaps.core.data.pump.defs.PumpType
+import app.aaps.core.interfaces.pump.DetailedBolusInfo
import app.aaps.pump.common.defs.PumpRunningState
+import app.aaps.pump.common.defs.TempBasalPair
import java.util.Date
/**
@@ -14,38 +16,96 @@ abstract class PumpStatus(var pumpType: PumpType) {
var lastConnection = 0L
var previousConnection = 0L // here should be stored last connection of previous session (so needs to be
- // read before lastConnection is modified for first time).
- // last bolus
- var lastBolusTime: Date? = null
- var lastBolusAmount: Double? = null
+ // bolus
+ var lastBolusTime: Date? = null // legacy
+ var lastBolusAmount: Double? = null // legqacy
+ var lastBolus: DetailedBolusInfo? = null
// other pump settings
- var activeProfileName = "0"
var reservoirRemainingUnits = 0.0
var reservoirFullUnits = 0
var batteryRemaining : Int? = null // percent, so 0-100
var batteryVoltage: Double? = null
+ var units: String? = null // Constants.MGDL or Constants.MMOL
// iob
var iob: String? = null
+ // basal profile
+ var basalsByHour: DoubleArray? = null
+ var activeProfileName = "1"
+
// TDD
var dailyTotalUnits: Double? = null
var maxDailyTotalUnits: String? = null
- var units: String? = null // GlucoseUnit.MGDL.asText or GlucoseUnit.MMOL.asText
+
+
+ // state
var pumpRunningState = PumpRunningState.Running
- var basalsByHour: DoubleArray? = null
+
+ // temp basal
+ var currentTempBasal: TempBasalPair? = null
+ get() = field
+ set(value) {
+ if (value!=null) {
+ if (value.start==null) {
+ this.currentTempBasalEstimatedEnd = System.currentTimeMillis() + (value.durationMinutes * 60 * 1000)
+ } else {
+ this.currentTempBasalEstimatedEnd = value.start!! + (value.durationMinutes * 60 * 1000)
+ }
+ } else {
+ this.currentTempBasalEstimatedEnd = null
+ }
+ field = value
+ }
+
+ var currentTempBasalInternal: TempBasalPair? = null
+
+
+ var currentTempBasalEstimatedEnd: Long? = null
+ var tempBasalLegacyMode = false
+
+ // time
+ var pumpTime: PumpTimeDifferenceDto? = null
+
+
+ // TODO refactor to use TempBasalPair - remove this
var tempBasalStart: Long? = null
var tempBasalAmount: Double? = 0.0
- var tempBasalLength: Int? = 0
+ var tempBasalPercent: Int? = 100
+ var tempBasalDuration: Int? = 0
var tempBasalEnd: Long? = null
- var pumpTime: PumpTimeDifferenceDto? = null
+
+
+// OLD - Start
+// var units: String? = null // Constants.MGDL or Constants.MMOL
+// var pumpRunningState = PumpRunningState.Running
+// var basalsByHour: DoubleArray? = null
+// var tempBasalStart: Long? = null
+// var tempBasalAmount: Double? = 0.0
+// var tempBasalLength: Int? = 0
+// var tempBasalEnd: Long? = null
+// var pumpTime: PumpTimeDifferenceDto? = null
+// OLD - End
fun setLastCommunicationToNow() {
lastDataTime = System.currentTimeMillis()
lastConnection = System.currentTimeMillis()
+ updateLastConnectionInFragment()
+ }
+
+ fun clearTbr() {
+ this.currentTempBasal = null
+ this.currentTempBasalEstimatedEnd = null
}
abstract val errorInfo: String?
-}
\ No newline at end of file
+ /**
+ * This needs to be overriden by any pump status implementation
+ */
+ open fun updateLastConnectionInFragment() {
+
+ }
+
+}
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/defs/PumpDriverAction.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/defs/PumpDriverAction.kt
new file mode 100644
index 00000000000..48f3dd736b0
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/defs/PumpDriverAction.kt
@@ -0,0 +1,8 @@
+package app.aaps.pump.common.defs
+
+enum class PumpDriverAction {
+
+ Bolus,
+ SetProfile
+
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/defs/TempBasalPair.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/defs/TempBasalPair.kt
index c04edb14494..d9b78d9e634 100644
--- a/pump/common/src/main/kotlin/app/aaps/pump/common/defs/TempBasalPair.kt
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/defs/TempBasalPair.kt
@@ -1,22 +1,34 @@
package app.aaps.pump.common.defs
+import app.aaps.pump.common.driver.connector.commands.data.AdditionalResponseDataInterface
import com.google.gson.annotations.Expose
-open class TempBasalPair {
+open class TempBasalPair constructor(
+ @Expose var insulinRate : Double,
+ @Expose var isPercent : Boolean,
+ @Expose var durationMinutes : Int,
+ @Expose var start: Long? = null ) : AdditionalResponseDataInterface {
- @Expose var insulinRate = 0.0
- @Expose var durationMinutes = 0
- @Expose var isPercent = false
- private var start: Long? = null
- private var end: Long? = null
+ @Expose private var end: Long? = null
+ var isActive: Boolean = false
+ var id: Long? = null
- constructor()
- constructor(insulinRate: Double, isPercent: Boolean, durationMinutes: Int) {
- this.insulinRate = insulinRate
- this.isPercent = isPercent
- this.durationMinutes = durationMinutes
+ init {
+ if (start!=null) {
+ this.end = start!! + (durationMinutes * 60 * 1000)
+ }
}
+ constructor(insulinRate: Double, isPercent: Boolean, durationMinutes: Int):
+ this(insulinRate, isPercent, durationMinutes, null)
+
+
+ // constructor(insulinRate: Double, isPercent: Boolean, durationMinutes: Int) {
+ // this.insulinRate = insulinRate
+ // this.isPercent = isPercent
+ // this.durationMinutes = durationMinutes
+ // }
+
fun setStartTime(startTime: Long?) {
start = startTime
}
@@ -26,7 +38,7 @@ open class TempBasalPair {
}
override fun toString(): String {
- return ("TempBasalPair [" + "Rate=" + insulinRate + ", DurationMinutes=" + durationMinutes + ", IsPercent="
- + isPercent + "]")
+ val unit = if (isPercent) " %" else " U"
+ return ("TempBasalPair [rate=${insulinRate}${unit},duration=" + durationMinutes + ",id=$id]")
}
}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/PumpDriverConfiguration.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/PumpDriverConfiguration.kt
new file mode 100755
index 00000000000..612160cdc82
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/PumpDriverConfiguration.kt
@@ -0,0 +1,25 @@
+package app.aaps.pump.common.driver
+
+import app.aaps.core.data.pump.defs.PumpType
+import app.aaps.pump.common.driver.ble.PumpBLESelector
+import app.aaps.pump.common.driver.db.PumpDriverDatabaseOperation
+import app.aaps.pump.common.driver.history.PumpHistoryDataProvider
+
+interface PumpDriverConfiguration {
+
+ fun getPumpBLESelector(): PumpBLESelector?
+
+ fun getPumpHistoryDataProvider(): PumpHistoryDataProvider?
+
+ fun getPumpDriverDatabaseOperation(): PumpDriverDatabaseOperation
+
+ fun getPumpType(): PumpType
+
+ var logPrefix : String
+
+ var canHandleDST : Boolean
+
+ var hasService: Boolean
+
+
+}
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/PumpDriverConfigurationCapable.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/PumpDriverConfigurationCapable.kt
new file mode 100755
index 00000000000..4fb24b71372
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/PumpDriverConfigurationCapable.kt
@@ -0,0 +1,7 @@
+package app.aaps.pump.common.driver
+
+interface PumpDriverConfigurationCapable {
+
+ fun getPumpDriverConfiguration(): PumpDriverConfiguration
+
+}
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/ble/PumpBLESelector.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/ble/PumpBLESelector.kt
new file mode 100644
index 00000000000..f7592be6770
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/ble/PumpBLESelector.kt
@@ -0,0 +1,119 @@
+package app.aaps.pump.common.driver.ble
+
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.le.ScanFilter
+import android.bluetooth.le.ScanSettings
+import android.content.Context
+import app.aaps.pump.common.driver.ui.PumpBLEConfigActivity
+
+interface PumpBLESelector {
+
+ /**
+ * Called on resume
+ */
+ fun onResume()
+
+ /**
+ * Called on destroy
+ */
+ fun onDestroy()
+
+ /**
+ * This method is called when device is being removed (it can be empty if you don't need to do any special action, but if you
+ * have to unbound (for example), then this is method where to call it. For unbounding removeBond is available
+ */
+ fun removeDevice(device: BluetoothDevice)
+
+ /**
+ * Cleanup method after device was removed
+ */
+ fun cleanupAfterDeviceRemoved()
+
+ /**
+ * operations when scan failed
+ */
+ fun onScanFailed(context: Context, errorCode: Int)
+
+ /**
+ * operations when scan starts
+ */
+ fun onStartLeDeviceScan(context: Context)
+
+ /**
+ * operations when scan stops
+ */
+ fun onStopLeDeviceScan(context: Context)
+
+ /**
+ * operations when scan was stopped manually (press on button)
+ */
+ fun onManualStopLeDeviceScan(context: Context)
+
+ /**
+ * operations when on non manual stop of scan (on timeout)
+ */
+ fun onNonManualStopLeDeviceScan(context: Context)
+
+ /**
+ * get Scan Filters
+ */
+ fun getScanFilters(): List?
+
+ /**
+ * get Scan Settings
+ */
+ fun getScanSettings(): ScanSettings?
+
+ /**
+ * filter device on search (for cases where we can't do it with Scan Filters
+ */
+ fun filterDevice(device: BluetoothDevice): BluetoothDevice?
+
+ /**
+ * operations when device selected
+ */
+ fun onDeviceSelected(bluetoothDevice: BluetoothDevice, bleAddress: String, deviceName: String, activity: PumpBLEConfigActivity)
+
+ /**
+ * when we select device, do we destroy the activity
+ */
+ fun onDeviceSelectedClosesActivity(): Boolean
+
+ /**
+ * If pump has no name, this name will be used
+ */
+ fun getUnknownPumpName(): String
+
+ /**
+ * get Address of Currently selected pump, empty string if none
+ */
+ fun currentlySelectedPumpAddress(): String
+
+ /**
+ * get Name of Currently selected pump, getUnknownPumpName() string if none
+ */
+ fun currentlySelectedPumpName(): String
+
+ /**
+ * Get Translation Text
+ */
+ fun getText(key: PumpBLESelectorText): String
+
+ /**
+ * Get Additional Permissions (if you module needs special BT permissions, need to add them here)
+ *
+ * Normally covered permissions would be: ACCESS_COARSE_LOCATION, BLUETOOTH_CONNECT, BLUETOOTH_SCAN
+ */
+ fun getAdditionalPermissions() : List
+
+}
+
+enum class PumpBLESelectorText {
+ SCAN_TITLE,
+ INSTRUCTIONS_TEXT,
+ SELECTED_PUMP_TITLE,
+ REMOVE_TITLE,
+ REMOVE_TEXT,
+ NO_SELECTED_PUMP,
+ PUMP_CONFIGURATION
+}
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/connector/commands/data/AdditionalResponseDataInterface.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/connector/commands/data/AdditionalResponseDataInterface.kt
new file mode 100644
index 00000000000..d234960c294
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/connector/commands/data/AdditionalResponseDataInterface.kt
@@ -0,0 +1,4 @@
+package app.aaps.pump.common.driver.connector.commands.data
+
+interface AdditionalResponseDataInterface {
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/connector/defs/PumpCommandType.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/connector/defs/PumpCommandType.kt
new file mode 100755
index 00000000000..898a365c7fd
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/connector/defs/PumpCommandType.kt
@@ -0,0 +1,36 @@
+package app.aaps.pump.common.driver.connector.defs
+
+import androidx.annotation.StringRes
+import app.aaps.pump.common.R
+
+enum class PumpCommandType(@param:StringRes val resourceId: Int) {
+
+ SetBolus(R.string.pump_cmd_desc_set_bolus),
+ GetBolus(R.string.pump_cmd_desc_get_bolus),
+ CancelBolus(R.string.pump_cmd_desc_cancel_bolus),
+
+ GetFirmwareVersion(R.string.pump_cmd_desc_get_firmware),
+
+ SetTemporaryBasal(R.string.pump_cmd_desc_set_tbr),
+ GetTemporaryBasal(R.string.pump_cmd_desc_get_tbr),
+ CancelTemporaryBasal(R.string.pump_cmd_desc_cancel_tbr),
+
+ GetBasalProfile(R.string.pump_cmd_desc_get_basal_profile),
+ SetBasalProfile(R.string.pump_cmd_desc_set_basal_profile),
+
+ GetPumpStatus(R.string.pump_cmd_desc_get_pump_status),
+
+ GetRemainingInsulin(R.string.pump_cmd_desc_get_remaining_insulin),
+ GetSettings(R.string.pump_cmd_desc_get_settings),
+ GetBatteryStatus(R.string.pump_cmd_desc_get_battery_status),
+
+ GetTime(R.string.pump_cmd_desc_get_time),
+ SetTime(R.string.pump_cmd_desc_set_time),
+
+ CustomCommand(R.string.pump_cmd_desc_custom),
+
+ GetHistory(R.string.pump_cmd_desc_get_history),
+ GetHistoryWithParameters(R.string.pump_cmd_desc_get_history_params),
+ ;
+
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/db/PumpDriverDatabaseOperation.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/db/PumpDriverDatabaseOperation.kt
new file mode 100644
index 00000000000..71df6e00cfd
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/db/PumpDriverDatabaseOperation.kt
@@ -0,0 +1,3 @@
+package app.aaps.pump.common.driver.db
+
+interface PumpDriverDatabaseOperation
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpDataConverter.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpDataConverter.kt
new file mode 100644
index 00000000000..153ca21ccb1
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpDataConverter.kt
@@ -0,0 +1,4 @@
+package app.aaps.pump.common.driver.history
+
+interface PumpDataConverter {
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryDataProvider.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryDataProvider.kt
new file mode 100644
index 00000000000..587d16c23d7
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryDataProvider.kt
@@ -0,0 +1,92 @@
+package app.aaps.pump.common.driver.history
+
+import androidx.annotation.StringRes
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.pump.common.R
+import app.aaps.pump.common.defs.PumpHistoryEntryGroup
+
+interface PumpHistoryDataProvider {
+
+ /**
+ * Get Data, specified with PumpHistoryPeriod
+ */
+ fun getData(period: PumpHistoryPeriod): List
+
+ /**
+ * Get Initial Period
+ */
+ fun getInitialPeriod(): PumpHistoryPeriod
+
+ /**
+ * Get InitialData
+ */
+ fun getInitialData(): List
+
+ /**
+ * Get Allowed Pump History Groups (for specific pump)
+ */
+ fun getAllowedPumpHistoryGroups(): List
+
+ /**
+ * Get Spinner Width in pixels (same as specifying 150dp)
+ */
+ fun getSpinnerWidthInPixels(): Int
+
+ /**
+ * Get Translation Text
+ */
+ fun getText(key: PumpHistoryText): String
+
+ /**
+ * For filtering of items
+ */
+ fun isItemInSelection(itemGroup: PumpHistoryEntryGroup, targetGroup: PumpHistoryEntryGroup): Boolean
+
+}
+
+enum class PumpHistoryPeriod(
+ @StringRes var resourceId: Int,
+ var isHours: Boolean = false,
+ var translated: String? = null
+) {
+
+ TODAY(R.string.time_today),
+ LAST_HOUR(R.string.time_last_hour, true),
+ LAST_3_HOURS(R.string.time_last_3_hours, true),
+ LAST_6_HOURS(R.string.time_last_6_hours, true),
+ LAST_12_HOURS(R.string.time_last_12_hours, true),
+ LAST_24_HOURS(R.string.time_last_24_hours, true),
+ LAST_2_DAYS(R.string.time_last_2_days),
+ LAST_4_DAYS(R.string.time_last_4_days),
+ LAST_WEEK(R.string.time_last_week),
+ LAST_MONTH(R.string.time_last_month),
+ ALL(R.string.history_group_all);
+
+ fun getDisplayValue(): String {
+ return if (translated==null)
+ name
+ else
+ translated!!
+ }
+
+ companion object {
+
+ @JvmStatic private var translatedList: MutableList = mutableListOf()
+
+ fun doTranslation(rh: ResourceHelper) {
+ if (translatedList.isNotEmpty()) return
+ for (pumpHistoryPeriod in PumpHistoryPeriod.entries) {
+ pumpHistoryPeriod.translated = rh.gs(pumpHistoryPeriod.resourceId)
+ translatedList.add(pumpHistoryPeriod)
+ }
+ }
+ }
+
+
+}
+
+enum class PumpHistoryText {
+
+ PUMP_HISTORY
+
+}
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryDataProviderAbstract.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryDataProviderAbstract.kt
new file mode 100644
index 00000000000..c06d173057f
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryDataProviderAbstract.kt
@@ -0,0 +1,48 @@
+package app.aaps.pump.common.driver.history
+
+import app.aaps.pump.common.defs.PumpHistoryEntryGroup
+import java.util.Calendar
+import java.util.GregorianCalendar
+
+abstract class PumpHistoryDataProviderAbstract : PumpHistoryDataProvider {
+
+ override fun getInitialData(): List {
+ return getData(getInitialPeriod())
+ }
+
+ override fun getSpinnerWidthInPixels(): Int {
+ return 150
+ }
+
+ protected fun getStartingTimeForData(period: PumpHistoryPeriod): Long {
+ val gregorianCalendar = GregorianCalendar()
+
+ if (!period.isHours) {
+ gregorianCalendar.set(Calendar.HOUR_OF_DAY, 0)
+ gregorianCalendar.set(Calendar.MINUTE, 0)
+ gregorianCalendar.set(Calendar.SECOND, 0)
+ gregorianCalendar.set(Calendar.MILLISECOND, 0)
+ }
+
+ when (period) {
+ PumpHistoryPeriod.TODAY -> return gregorianCalendar.timeInMillis
+ PumpHistoryPeriod.ALL -> return 0L
+ PumpHistoryPeriod.LAST_2_DAYS -> gregorianCalendar.add(Calendar.DAY_OF_MONTH, -1)
+ PumpHistoryPeriod.LAST_4_DAYS -> gregorianCalendar.add(Calendar.DAY_OF_MONTH, -3)
+ PumpHistoryPeriod.LAST_WEEK -> gregorianCalendar.add(Calendar.WEEK_OF_YEAR, -1)
+ PumpHistoryPeriod.LAST_MONTH -> gregorianCalendar.add(Calendar.MONTH, -1)
+ PumpHistoryPeriod.LAST_HOUR -> gregorianCalendar.add(Calendar.HOUR_OF_DAY, -1)
+ PumpHistoryPeriod.LAST_3_HOURS -> gregorianCalendar.add(Calendar.HOUR_OF_DAY, -3)
+ PumpHistoryPeriod.LAST_6_HOURS -> gregorianCalendar.add(Calendar.HOUR_OF_DAY, -6)
+ PumpHistoryPeriod.LAST_12_HOURS -> gregorianCalendar.add(Calendar.HOUR_OF_DAY, -12)
+ PumpHistoryPeriod.LAST_24_HOURS -> gregorianCalendar.add(Calendar.HOUR_OF_DAY, -24)
+ }
+
+ return gregorianCalendar.timeInMillis
+ }
+
+ override fun isItemInSelection(itemGroup: PumpHistoryEntryGroup, targetGroup: PumpHistoryEntryGroup): Boolean {
+ return itemGroup === targetGroup
+ }
+
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryEntry.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryEntry.kt
new file mode 100644
index 00000000000..19b20ee6008
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/history/PumpHistoryEntry.kt
@@ -0,0 +1,18 @@
+package app.aaps.pump.common.driver.history
+
+import app.aaps.core.interfaces.resources.ResourceHelper
+import app.aaps.pump.common.defs.PumpHistoryEntryGroup
+
+interface PumpHistoryEntry {
+
+ fun prepareEntryData(resourceHelper: ResourceHelper, pumpDataConverter: PumpDataConverter)
+
+ fun getEntryDateTime(): String
+
+ fun getEntryType(): String
+
+ fun getEntryValue(): String
+
+ fun getEntryTypeGroup(): PumpHistoryEntryGroup
+
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshAction.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshAction.kt
new file mode 100644
index 00000000000..bc242515ff1
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshAction.kt
@@ -0,0 +1,8 @@
+package app.aaps.pump.common.driver.refresh
+
+enum class PumpDataRefreshAction {
+ Add,
+ GetData,
+ Delete,
+ AddSameAsOther // this can be used if you want to add refresh that happens at same time as some other refreshType
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshCapable.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshCapable.kt
new file mode 100644
index 00000000000..5429b556ec6
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshCapable.kt
@@ -0,0 +1,6 @@
+package app.aaps.pump.common.driver.refresh
+
+interface PumpDataRefreshCapable {
+ fun getRefreshTime(pumpDataRefreshType: PumpDataRefreshType): Int
+ fun isInPreventConnectMode(): Boolean
+}
\ No newline at end of file
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshType.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshType.kt
new file mode 100755
index 00000000000..40301b0b7d7
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/refresh/PumpDataRefreshType.kt
@@ -0,0 +1,20 @@
+package app.aaps.pump.common.driver.refresh
+
+import app.aaps.pump.common.driver.connector.defs.PumpCommandType
+
+/**
+ * Created by andy on 04.07.2022.
+ */
+enum class PumpDataRefreshType(val commandType: PumpCommandType?) {
+ PumpHistory(PumpCommandType.GetHistory),
+ Configuration(PumpCommandType.GetSettings),
+ RemainingInsulin(PumpCommandType.GetRemainingInsulin),
+ BatteryStatus(PumpCommandType.GetBatteryStatus),
+ PumpTime(PumpCommandType.GetTime),
+ PumpStatus(PumpCommandType.GetPumpStatus),
+ GetTemporaryBasal(PumpCommandType.GetTemporaryBasal),
+ Custom_1(null),
+ Custom_2(null),
+ Custom_3(null),
+ Custom_4(null),
+}
diff --git a/pump/common/src/main/kotlin/app/aaps/pump/common/driver/ui/PumpBLEConfigActivity.kt b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/ui/PumpBLEConfigActivity.kt
new file mode 100644
index 00000000000..f5c93976175
--- /dev/null
+++ b/pump/common/src/main/kotlin/app/aaps/pump/common/driver/ui/PumpBLEConfigActivity.kt
@@ -0,0 +1,372 @@
+package app.aaps.pump.common.driver.ui
+
+import android.Manifest
+import android.annotation.SuppressLint
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.BluetoothLeScanner
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanFilter
+import android.bluetooth.le.ScanResult
+import android.bluetooth.le.ScanSettings
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Bundle
+import android.os.Handler
+import android.os.HandlerThread
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.AdapterView.OnItemClickListener
+import android.widget.BaseAdapter
+import android.widget.TextView
+import androidx.core.app.ActivityCompat
+import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
+import app.aaps.core.interfaces.plugin.ActivePlugin
+import app.aaps.core.interfaces.pump.BlePreCheck
+import app.aaps.core.interfaces.rx.bus.RxBus
+import app.aaps.core.interfaces.sharedPreferences.SP
+import app.aaps.core.ui.activities.TranslatedDaggerAppCompatActivity
+import app.aaps.core.ui.dialogs.OKDialog
+import app.aaps.core.ui.toast.ToastUtils
+import app.aaps.pump.common.R
+import app.aaps.pump.common.databinding.PumpBleConfigActivityBinding
+import app.aaps.pump.common.driver.PumpDriverConfigurationCapable
+import app.aaps.pump.common.driver.ble.PumpBLESelector
+import app.aaps.pump.common.driver.ble.PumpBLESelectorText
+import org.apache.commons.lang3.StringUtils
+import javax.inject.Inject
+import kotlin.also
+import kotlin.collections.set
+import kotlin.plus
+
+@SuppressLint("MissingPermission")
+open class PumpBLEConfigActivity : TranslatedDaggerAppCompatActivity() {
+
+ @Inject lateinit var activePlugin: ActivePlugin
+ @Inject lateinit var sp: SP
+ @Inject lateinit var blePreCheck: BlePreCheck
+ @Inject lateinit var context: Context
+ @Inject lateinit var aapsLogger: AAPSLogger
+ @Inject lateinit var rxBus: RxBus
+
+ private lateinit var binding: PumpBleConfigActivityBinding
+ lateinit var bleSelector: PumpBLESelector
+
+ private var settings: ScanSettings? = null
+ private var filters: List? = null
+ private var bleScanner: BluetoothLeScanner? = null
+ private var deviceListAdapter = LeDeviceListAdapter()
+ val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
+ val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
+ var scanning = false
+ private val devicesMap: MutableMap = kotlin.collections.HashMap()
+
+ private val stopScanAfterTimeoutRunnable = Runnable {
+ if (scanning) {
+ stopLeDeviceScan(false)
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = PumpBleConfigActivityBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ if (!blePreCheck.prerequisitesCheck(this)) {
+ aapsLogger.error(TAG, "prerequisitesCheck failed.")
+ finish()
+ return
+ }
+
+ // Configuration
+ val activePump = activePlugin.activePump
+
+ if (activePump is PumpDriverConfigurationCapable) {
+ val pumpBLESelector = activePump.getPumpDriverConfiguration().getPumpBLESelector()
+ if (pumpBLESelector==null) {
+ throw kotlin.RuntimeException("PumpBLESelector needs to be implemented for PumpBLEConfigActivity to be used.")
+ } else {
+ bleSelector = pumpBLESelector
+ }
+ } else {
+ throw kotlin.RuntimeException("PumpBLEConfigActivity can be used only with PumpDriverConfigurationCapable pump driver.")
+ }
+
+ if (!blePreCheck.prerequisitesCheck(this, bleSelector.getAdditionalPermissions())) {
+ aapsLogger.error(TAG, "prerequisitesCheck failed.")
+ ToastUtils.errorToast(context, context.getString(app.aaps.core.ui.R.string.need_connect_permission))
+ finish()
+ return
+ }
+
+ binding.pumpBleConfigCurrentlySelectedText.text = bleSelector.getText(PumpBLESelectorText.SELECTED_PUMP_TITLE)
+ binding.pumpBleConfigScanTitle.text = bleSelector.getText(PumpBLESelectorText.SCAN_TITLE)
+ binding.pumpBleConfigInstructionsText.text = bleSelector.getText(PumpBLESelectorText.INSTRUCTIONS_TEXT)
+
+ title = bleSelector.getText(PumpBLESelectorText.PUMP_CONFIGURATION)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.setDisplayShowHomeEnabled(true)
+
+ binding.pumpBleConfigScanDeviceList.adapter = deviceListAdapter
+ binding.pumpBleConfigScanDeviceList.onItemClickListener = OnItemClickListener { _: AdapterView<*>?, view: View, _: Int, _: Long ->
+ // stop scanning if still active
+ if (scanning) {
+ stopLeDeviceScan(true)
+ }
+ val bleAddress = (view.findViewById(R.id.pump_ble_config_scan_item_device_address) as TextView).text.toString()
+ val deviceName = (view.findViewById(R.id.pump_ble_config_scan_item_device_name) as TextView).text.toString()
+
+ if (devicesMap.containsKey(bleAddress)) {
+ aapsLogger.debug(TAG, "Device FOUND in deviceMap: $bleAddress")
+ val bluetoothDevice = devicesMap[bleAddress]
+ bleSelector.onDeviceSelected(bluetoothDevice!!, bleAddress, deviceName, this)
+ setResult(RESULT_OK)
+
+ if (bleSelector.onDeviceSelectedClosesActivity()) {
+ finish()
+ }
+ } else {
+ aapsLogger.debug(TAG, "Device NOT found in deviceMap: $bleAddress")
+ }
+
+ finish()
+ }
+ binding.pumpBleConfigScanStart.setOnClickListener { startLeDeviceScan() }
+ binding.pumpBleConfigButtonScanStop.setOnClickListener {
+ if (scanning) {
+ stopLeDeviceScan(true)
+ }
+ }
+
+ binding.pumpBleConfigButtonRemove.setOnClickListener {
+ OKDialog.showConfirmation(
+ this@PumpBLEConfigActivity,
+ bleSelector.getText(PumpBLESelectorText.REMOVE_TITLE),
+ bleSelector.getText(PumpBLESelectorText.REMOVE_TEXT),
+ Runnable {
+ val deviceAddress: String = binding.pumpBleConfigCurrentlySelectedPumpAddress.text.toString()
+ aapsLogger.debug(TAG, "Removing device as selected: $deviceAddress")
+ if (devicesMap.containsKey(deviceAddress)) {
+ val bluetoothDevice = devicesMap[deviceAddress]
+ aapsLogger.debug(TAG, "Device can be detected near, so trying to remove bond if possible.")
+ bleSelector.removeDevice(bluetoothDevice!!)
+ } else {
+ val remoteDevice = bluetoothAdapter?.getRemoteDevice(deviceAddress)
+ if (remoteDevice != null) {
+ bleSelector.removeDevice(remoteDevice)
+ }
+ }
+ bleSelector.cleanupAfterDeviceRemoved()
+ updateCurrentlySelectedBTDevice()
+ })
+ }
+ }
+
+ fun updateCurrentlySelectedBTDevice() {
+ val address = bleSelector.currentlySelectedPumpAddress()
+ if (StringUtils.isEmpty(address)) {
+ binding.pumpBleConfigCurrentlySelectedPumpName.text = bleSelector.getText(PumpBLESelectorText.NO_SELECTED_PUMP)
+ binding.pumpBleConfigCurrentlySelectedPumpAddress.visibility = View.GONE
+ binding.pumpBleConfigButtonRemove.visibility = View.GONE
+ } else {
+ binding.pumpBleConfigCurrentlySelectedPumpAddress.visibility = View.VISIBLE
+ binding.pumpBleConfigButtonRemove.visibility = View.VISIBLE
+ binding.pumpBleConfigCurrentlySelectedPumpName.text = bleSelector.currentlySelectedPumpName()
+ binding.pumpBleConfigCurrentlySelectedPumpAddress.text = address
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean =
+ when (item.itemId) {
+ android.R.id.home -> {
+ finish()
+ true
+ }
+
+ else -> super.onOptionsItemSelected(item)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ bleSelector.onResume()
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
+ if (bluetoothAdapter?.isEnabled != true) bluetoothAdapter?.enable()
+ prepareForScanning()
+ updateCurrentlySelectedBTDevice()
+ } else {
+ ToastUtils.errorToast(context, context.getString(app.aaps.core.ui.R.string.need_connect_permission))
+ finish()
+ }
+
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (scanning) {
+ stopLeDeviceScan(false)
+ }
+ bleSelector.onDestroy()
+ }
+
+ protected fun prepareForScanning() {
+ bleScanner = bluetoothAdapter?.bluetoothLeScanner
+ settings = bleSelector.getScanSettings()
+ filters = bleSelector.getScanFilters()
+ }
+
+ private val bleScanCallback: ScanCallback = object : ScanCallback() {
+
+ override fun onScanResult(callbackType: Int, scanRecord: ScanResult) {
+ aapsLogger.debug(TAG, scanRecord.toString())
+ runOnUiThread { if (addDevice(scanRecord)) deviceListAdapter.notifyDataSetChanged() }
+ }
+
+ override fun onBatchScanResults(results: List) {
+ runOnUiThread {
+ var added = false
+ for (result in results) {
+ aapsLogger.debug(TAG, "SCAN: " + result.advertisingSid + " name=" + result.device.address)
+ if (addDevice(result)) added = true
+ }
+ if (added)
+ deviceListAdapter.notifyDataSetChanged()
+ }
+ }
+
+ private fun addDevice(result: ScanResult): Boolean {
+ var device = result.device
+
+ device = bleSelector.filterDevice(device)
+
+ if (device == null) {
+ return false
+ }
+
+ deviceListAdapter.addDevice(result)
+ if (!devicesMap.containsKey(device.address)) {
+ devicesMap[device.address] = device
+ }
+ return true
+ }
+
+ override fun onScanFailed(errorCode: Int) {
+ aapsLogger.error(TAG, "Scan Failed - Error Code: $errorCode")
+ bleSelector.onScanFailed(this@PumpBLEConfigActivity, errorCode)
+ }
+ }
+
+ private fun startLeDeviceScan() {
+ if (bleScanner == null) {
+ aapsLogger.error(LTag.PUMPBTCOMM, "startLeDeviceScan failed: bleScanner is null")
+ return
+ }
+ deviceListAdapter.clear()
+ deviceListAdapter.notifyDataSetChanged()
+ handler.postDelayed(stopScanAfterTimeoutRunnable, SCAN_PERIOD_MILLIS)
+ runOnUiThread {
+ binding.pumpBleConfigScanStart.isEnabled = false
+ binding.pumpBleConfigButtonScanStop.visibility = View.VISIBLE
+ }
+ scanning = true
+ bleScanner?.startScan(filters, settings, bleScanCallback)
+ aapsLogger.debug(LTag.PUMPBTCOMM, "startLeDeviceScan: Scanning Start")
+ bleSelector.onStartLeDeviceScan(this@PumpBLEConfigActivity)
+ }
+
+ private fun stopLeDeviceScan(manualStop: Boolean) {
+ if (scanning) {
+ scanning = false
+ bleScanner?.stopScan(bleScanCallback)
+ aapsLogger.debug(LTag.PUMPBTCOMM, "stopLeDeviceScan: Scanning Stop")
+ bleSelector.onStopLeDeviceScan(this@PumpBLEConfigActivity)
+ handler.removeCallbacks(stopScanAfterTimeoutRunnable)
+ }
+ if (manualStop) {
+ bleSelector.onManualStopLeDeviceScan(this@PumpBLEConfigActivity)
+ } else {
+ bleSelector.onNonManualStopLeDeviceScan(this@PumpBLEConfigActivity)
+ }
+
+ runOnUiThread {
+ binding.pumpBleConfigScanStart.isEnabled = true
+ binding.pumpBleConfigButtonScanStop.visibility = View.GONE
+ }
+ }
+
+ private inner class LeDeviceListAdapter : BaseAdapter() {
+
+ private var devicesList: ArrayList = arrayListOf()
+ private var devicesMap: MutableMap = mutableMapOf()
+
+ fun addDevice(result: ScanResult) {
+ if (!devicesList.contains(result.device)) {
+ devicesList.add(result.device)
+ }
+ devicesMap[result.device] = result.rssi
+ notifyDataSetChanged()
+ }
+
+ fun clear() {
+ devicesList.clear()
+ devicesMap.clear()
+ notifyDataSetChanged()
+ }
+
+ override fun getCount(): Int {
+ val c = devicesList.size
+ aapsLogger.info(TAG, "D: count=$c")
+ return c
+ }
+
+ override fun getItem(i: Int): Any = devicesList[i]
+ override fun getItemId(i: Int): Long = i.toLong()
+
+ override fun getView(i: Int, convertView: View?, viewGroup: ViewGroup?): View {
+ var v = convertView
+ val holder: ViewHolder
+ if (v == null) {
+ v = View.inflate(applicationContext, R.layout.pump_ble_config_scan_item, null)
+ holder = ViewHolder()
+ holder.deviceAddress = v.findViewById(R.id.pump_ble_config_scan_item_device_address)
+ holder.deviceName = v.findViewById(R.id.pump_ble_config_scan_item_device_name)
+ v.tag = holder
+ } else {
+ // reuse view if already exists
+ holder = v.tag as ViewHolder
+ }
+
+ val device = devicesList[i]
+ var deviceName = device.name
+ if (StringUtils.isBlank(deviceName)) {
+ deviceName = bleSelector.getUnknownPumpName()
+ }
+ deviceName += " [" + devicesMap[device] + "]"
+ val currentlySelectedAddress = bleSelector.currentlySelectedPumpAddress() // TODO
+ if (currentlySelectedAddress == device.address) {
+ deviceName += " (" + resources.getString(R.string.ble_config_scan_selected) + ")"
+ }
+ holder.deviceName?.text = deviceName
+ holder.deviceAddress?.text = device.address
+ return v!!
+ }
+ }
+
+ internal class ViewHolder {
+
+ var deviceName: TextView? = null
+ var deviceAddress: TextView? = null
+ }
+
+ companion object {
+
+ private val TAG = LTag.PUMPBTCOMM
+ private const val SCAN_PERIOD_MILLIS: Long = 15000
+ }
+}
diff --git a/pump/common/src/main/res/layout/pump_ble_config_activity.xml b/pump/common/src/main/res/layout/pump_ble_config_activity.xml
index b72fbd7e3f7..6f69ba1ab73 100644
--- a/pump/common/src/main/res/layout/pump_ble_config_activity.xml
+++ b/pump/common/src/main/res/layout/pump_ble_config_activity.xml
@@ -4,6 +4,12 @@
android:orientation="vertical"
android:padding="5dp">
+
+
+ android:orientation="horizontal"
+ android:paddingTop="24dp">
+ tools:context="app.aaps.pump.common.driver.ui.PumpHistoryActivity">
+
diff --git a/pump/common/src/main/res/values-bg-rBG/strings.xml b/pump/common/src/main/res/values-bg-rBG/strings.xml
index 9ea955378ea..13d0d01f318 100644
--- a/pump/common/src/main/res/values-bg-rBG/strings.xml
+++ b/pump/common/src/main/res/values-bg-rBG/strings.xml
@@ -10,6 +10,7 @@
В процес на работаПрекратеноИзпълнение на команда
+
БазалиКонфигурации
diff --git a/pump/common/src/main/res/values-ca-rES/strings.xml b/pump/common/src/main/res/values-ca-rES/strings.xml
index ae909f01011..aa4df8be5e9 100644
--- a/pump/common/src/main/res/values-ca-rES/strings.xml
+++ b/pump/common/src/main/res/values-ca-rES/strings.xml
@@ -4,6 +4,7 @@
Operació no compatible amb la bomba i/o controlador.En pausa
+
ConfiguracionsAvisos
diff --git a/pump/common/src/main/res/values-cs-rCZ/strings.xml b/pump/common/src/main/res/values-cs-rCZ/strings.xml
index 30a1b9782cd..f3bc39504a2 100644
--- a/pump/common/src/main/res/values-cs-rCZ/strings.xml
+++ b/pump/common/src/main/res/values-cs-rCZ/strings.xml
@@ -10,6 +10,7 @@
ZaneprázdněnýPozastavenoProvádění příkazu
+
BazályKonfigurace
diff --git a/pump/common/src/main/res/values-da-rDK/strings.xml b/pump/common/src/main/res/values-da-rDK/strings.xml
index ae5335a3b59..af0ee21b91a 100644
--- a/pump/common/src/main/res/values-da-rDK/strings.xml
+++ b/pump/common/src/main/res/values-da-rDK/strings.xml
@@ -10,6 +10,7 @@
OptagetSat på pauseUdfører Kommando
+
BasalerKonfigurationer
diff --git a/pump/common/src/main/res/values-de-rDE/strings.xml b/pump/common/src/main/res/values-de-rDE/strings.xml
index aaafc020c3d..3be50262249 100644
--- a/pump/common/src/main/res/values-de-rDE/strings.xml
+++ b/pump/common/src/main/res/values-de-rDE/strings.xml
@@ -10,6 +10,7 @@
BeschäftigtAngehaltenBefehl ausführen
+
BasalKonfigurationen
diff --git a/pump/common/src/main/res/values-el-rGR/strings.xml b/pump/common/src/main/res/values-el-rGR/strings.xml
index a99fda0dba0..f8b1de79b3e 100644
--- a/pump/common/src/main/res/values-el-rGR/strings.xml
+++ b/pump/common/src/main/res/values-el-rGR/strings.xml
@@ -10,6 +10,14 @@
ΑπασχολημένοΣε αναστολήΕκτέλεση εντολής
+
+ Λήψη ρυθμίσεων
+ Λήψη λογισμικού αντλίας
+ Λήψη προφίλ βασικού ρυθμού
+ Ρύθμιση βασικού προφίλ
+ Λήψη προσωρινού βασικού ρυθμού
+ Ακύρωση προσωρινού βασικού ρυθμού
+ Ρύθμιση προσωρινού βασικού ρυθμούΒασικοίΡύθμιση παραμέτρων
diff --git a/pump/common/src/main/res/values-es-rES/strings.xml b/pump/common/src/main/res/values-es-rES/strings.xml
index 7f105a75d17..94744e850cc 100644
--- a/pump/common/src/main/res/values-es-rES/strings.xml
+++ b/pump/common/src/main/res/values-es-rES/strings.xml
@@ -10,6 +10,25 @@
OcupadoSuspendidoEjecutando comando
+
+ Obtener ajustes
+ Obtener firmware de la bomba
+ Obtener perfil basal
+ Establecer perfil basal
+ Obtener basal temporal
+ Cancelar basal temporal
+ Establecer basal temporal
+ Establecer bolo
+ Obtener bolo
+ Cancelar Bolo
+ Obtener insulina restante
+ Obtener estado de la batería
+ Obtener hora
+ Establecer hora
+ Consultar estado de la bomba
+ Obtener historial
+ Obtener historial %s
+ Comando personalizadoBasalesConfiguraciones
@@ -31,6 +50,7 @@
Últimas 3 horasÚltimas 6 horasÚltimas 12 horas
+ Últimas 24 horasÚltimos 2 díasÚltimos 4 díasÚltima semana
diff --git a/pump/common/src/main/res/values-fr-rFR/strings.xml b/pump/common/src/main/res/values-fr-rFR/strings.xml
index 2c0314b7d24..06a7625d406 100644
--- a/pump/common/src/main/res/values-fr-rFR/strings.xml
+++ b/pump/common/src/main/res/values-fr-rFR/strings.xml
@@ -10,6 +10,7 @@
OccupéSuspenduExécution de la commande
+
BasalesConfigurations
diff --git a/pump/common/src/main/res/values-hr-rHR/strings.xml b/pump/common/src/main/res/values-hr-rHR/strings.xml
index cdf2250057d..f83e0389ca6 100644
--- a/pump/common/src/main/res/values-hr-rHR/strings.xml
+++ b/pump/common/src/main/res/values-hr-rHR/strings.xml
@@ -9,6 +9,7 @@
ZauzetSuspendiranIzvršavanje naredbe
+
SviBolusi
diff --git a/pump/common/src/main/res/values-hu-rHU/strings.xml b/pump/common/src/main/res/values-hu-rHU/strings.xml
index 84982f50c2d..0ee549efc38 100644
--- a/pump/common/src/main/res/values-hu-rHU/strings.xml
+++ b/pump/common/src/main/res/values-hu-rHU/strings.xml
@@ -2,6 +2,7 @@
+
BázisStatisztikák
diff --git a/pump/common/src/main/res/values-it-rIT/strings.xml b/pump/common/src/main/res/values-it-rIT/strings.xml
index 5f70f1b6358..3a1f422a3d3 100644
--- a/pump/common/src/main/res/values-it-rIT/strings.xml
+++ b/pump/common/src/main/res/values-it-rIT/strings.xml
@@ -10,6 +10,25 @@
OccupatoSospesoEsecuzione comando
+
+ Ottieni le impostazioni
+ Ottieni Firmware Micro
+ Ottieni profilo basale
+ Imposta profilo basale
+ Ottieni basale temporanea
+ Cancella basale temporanea
+ Imposta basale temporanea
+ Imposta bolo
+ Ottieni boli
+ Cancella bolo
+ Ottieni insulina rimanente
+ Ottieni stato batteria
+ Ottieni ora
+ Imposta ora
+ Ottieni stato micro
+ Ottieni Storico
+ Ottieni Storico %s
+ Comando personalizzatoBasaliConfigurazioni
@@ -31,6 +50,7 @@
Ultime 3 oreUltime 6 oreUltime 12 ore
+ Ultime 24 oreUltimi 2 giorniUltimi 4 giorniUltima settimana
diff --git a/pump/common/src/main/res/values-iw-rIL/strings.xml b/pump/common/src/main/res/values-iw-rIL/strings.xml
index ae7c75fa655..d5d563c4220 100644
--- a/pump/common/src/main/res/values-iw-rIL/strings.xml
+++ b/pump/common/src/main/res/values-iw-rIL/strings.xml
@@ -10,6 +10,7 @@
עסוקמושההמבצע פקודה
+
בזאליםתצורות
diff --git a/pump/common/src/main/res/values-ko-rKR/strings.xml b/pump/common/src/main/res/values-ko-rKR/strings.xml
index 9acbbf2335c..0d0a1dffb0e 100644
--- a/pump/common/src/main/res/values-ko-rKR/strings.xml
+++ b/pump/common/src/main/res/values-ko-rKR/strings.xml
@@ -10,6 +10,7 @@
사용 중중지됨명령 실행 중
+
Basal환경설정
diff --git a/pump/common/src/main/res/values-lt-rLT/strings.xml b/pump/common/src/main/res/values-lt-rLT/strings.xml
index e79bab0bdf6..9ca8d225b86 100644
--- a/pump/common/src/main/res/values-lt-rLT/strings.xml
+++ b/pump/common/src/main/res/values-lt-rLT/strings.xml
@@ -10,6 +10,7 @@
UžimtaSustabdytaKomanda vykdoma
+
BazėNustatymai
diff --git a/pump/common/src/main/res/values-nb-rNO/strings.xml b/pump/common/src/main/res/values-nb-rNO/strings.xml
index 2de26e6ac2b..d940f0a94a5 100644
--- a/pump/common/src/main/res/values-nb-rNO/strings.xml
+++ b/pump/common/src/main/res/values-nb-rNO/strings.xml
@@ -10,6 +10,25 @@
OpptattPausetUtfører kommando
+
+ Hent innstillinger
+ Hent pumpens firmware
+ Hent basalprofil
+ Angi basalprofil
+ Hent midlertidig basal
+ Avbryt midlertidig basal
+ Angi midlertidig basal
+ Angi bolus
+ Hent bolus
+ Avbryt bolus
+ Hent gjenværende insulinmengde
+ Hent batteristatus
+ Hent tid
+ Angi tid
+ Hent pumpestatus
+ Hent historikk
+ Hent historikk %s
+ Egendefinert kommandoBasaldoserKonfigurasjoner
@@ -31,6 +50,7 @@
Siste 3 timerSiste 6 timerSiste 12 timer
+ Siste 24 timerSiste 2 dagerSiste 4 dagerSiste uke
diff --git a/pump/common/src/main/res/values-nl-rNL/strings.xml b/pump/common/src/main/res/values-nl-rNL/strings.xml
index acb43b27061..001692595dd 100644
--- a/pump/common/src/main/res/values-nl-rNL/strings.xml
+++ b/pump/common/src/main/res/values-nl-rNL/strings.xml
@@ -10,6 +10,25 @@
BezigOnderbrokenCommando uitvoeren
+
+ Instellingen ophalen
+ Firmware van de pomp ophalen
+ Basaal profiel ophalen
+ Basaal profiel Instellen
+ Tijdelijke basaal ophalen
+ Tijdelijk basaal annuleren
+ Tijdelijke basaal instellen
+ Bolus instellen
+ Bolus ophalen
+ Bolus annuleren
+ Resterende insuline ophalen
+ Batterijstatus ophalen
+ Tijd ophalen
+ Tijd instellen
+ Pomp status ophalen
+ Historie ophalen
+ Historie ophalen %s
+ Aangepast commandoBasaalstandenInstellingen
@@ -20,6 +39,7 @@
BolussenVullenAlarmen
+ GlucoseBasisAndersAlle gebeurtenissen
@@ -30,18 +50,21 @@
Laatste 3 uurLaatste 6 uurLaatste 12 uur
+ Laatste 24 uurAfgelopen 2 dagenAfgelopen 4 dagenVorige weekVorige maandScannen
+ StopGeselecteerdScannenScannen voltooidScanfout: %1$dVerwijderen
+ Type:%1$d dag%1$d dagen
diff --git a/pump/common/src/main/res/values-pl-rPL/strings.xml b/pump/common/src/main/res/values-pl-rPL/strings.xml
index 9b088ec1d36..c64b7122b2b 100644
--- a/pump/common/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/common/src/main/res/values-pl-rPL/strings.xml
@@ -10,6 +10,7 @@
ZajętyWstrzymanyWykonywanie polecenia
+
Dawki BazoweUstawienia
@@ -37,6 +38,7 @@
Ostatni miesiącSkanuj
+ StopWybranySkanowanieSkanowanie zakończono
diff --git a/pump/common/src/main/res/values-pt-rBR/strings.xml b/pump/common/src/main/res/values-pt-rBR/strings.xml
index fcd7597c200..f3b5e6f0ced 100644
--- a/pump/common/src/main/res/values-pt-rBR/strings.xml
+++ b/pump/common/src/main/res/values-pt-rBR/strings.xml
@@ -10,6 +10,7 @@
OcupadoSuspensoExecutando Comando
+
BasaisConfigurações
diff --git a/pump/common/src/main/res/values-pt-rPT/strings.xml b/pump/common/src/main/res/values-pt-rPT/strings.xml
index 50b67bb7c6a..0a6375fe318 100644
--- a/pump/common/src/main/res/values-pt-rPT/strings.xml
+++ b/pump/common/src/main/res/values-pt-rPT/strings.xml
@@ -5,6 +5,7 @@
Não inicializadoSuspenso
+
BasaisConfigurações
diff --git a/pump/common/src/main/res/values-ro-rRO/strings.xml b/pump/common/src/main/res/values-ro-rRO/strings.xml
index e3aec3ce420..216a4686c6a 100644
--- a/pump/common/src/main/res/values-ro-rRO/strings.xml
+++ b/pump/common/src/main/res/values-ro-rRO/strings.xml
@@ -10,6 +10,7 @@
OcupatSuspendatExecutare comandă
+
BazaleConfigurații
diff --git a/pump/common/src/main/res/values-ru-rRU/strings.xml b/pump/common/src/main/res/values-ru-rRU/strings.xml
index eef5c3b204f..ca0a4ac36fd 100644
--- a/pump/common/src/main/res/values-ru-rRU/strings.xml
+++ b/pump/common/src/main/res/values-ru-rRU/strings.xml
@@ -10,6 +10,25 @@
ОбработкаПомпа остановленаВыполнение команды
+
+ Получить настройки
+ Получить прошивку помпы
+ Получить базальный профиль
+ Установить базальный профиль
+ Получить временный базал
+ Отменить временный базал
+ Установить временный базал
+ Задать настройки болюса
+ Получить настройки болюса
+ Отменить болюс
+ Получить данные об оставшемся инсулине
+ Получить данные о состояние батареи
+ Получить данные о времени
+ Установить Время
+ Получить статус помпы
+ Получить журнал
+ Получить журнал %s
+ Настраиваемая командаБазалыКонфигурации
@@ -31,6 +50,7 @@
За прошедшие 3 часаЗа прошедшие 6 часовЗа прошедшие 12 часов
+ За прошедшие 24 часовЗа прошедшие 2 дняЗа прошедшие 4 дняЗа прошедшую неделю
diff --git a/pump/common/src/main/res/values-sk-rSK/strings.xml b/pump/common/src/main/res/values-sk-rSK/strings.xml
index b529825ff0c..a058693a6b4 100644
--- a/pump/common/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/common/src/main/res/values-sk-rSK/strings.xml
@@ -10,6 +10,25 @@
ZaneprázdnenýPozastavenéVykonávanie príkazu
+
+ Načítanie nastavení
+ Načítanie firmvéru pumpy
+ Načítanie bazálneho profilu
+ Nastavte bazálny profil
+ Načítanie dočasného bazálu
+ Zrušiť dočasný bazál
+ Nastaviť dočasný bazál
+ Nastaviť bolus
+ Načítať Bolus
+ Zrušiť bolus
+ Načítať zostávajúci inzulín
+ Načítať stav batérie
+ Načítanie času
+ Nastaviť čas
+ Načítavam stav pumpy
+ Načítavam históriu
+ Načítavanie histórie %s
+ Vlastný príkazBazályKonfigurácie
@@ -31,6 +50,7 @@
Posledné 3 hodinyPosledných 6 hodínPosledných 12 hodín
+ Posledných 24 hodínPosledné 2 dniPosledné 4 dniPosledný týždeň
diff --git a/pump/common/src/main/res/values-sr-rCS/strings.xml b/pump/common/src/main/res/values-sr-rCS/strings.xml
index 37e89919d01..b7ae34f1454 100644
--- a/pump/common/src/main/res/values-sr-rCS/strings.xml
+++ b/pump/common/src/main/res/values-sr-rCS/strings.xml
@@ -2,6 +2,7 @@
+
Ostalo
diff --git a/pump/common/src/main/res/values-sv-rSE/strings.xml b/pump/common/src/main/res/values-sv-rSE/strings.xml
index a2814372b65..076054c3752 100644
--- a/pump/common/src/main/res/values-sv-rSE/strings.xml
+++ b/pump/common/src/main/res/values-sv-rSE/strings.xml
@@ -10,6 +10,7 @@
UpptagenPausadKör kommando
+
BasaldoserKonfigurationer
diff --git a/pump/common/src/main/res/values-tr-rTR/strings.xml b/pump/common/src/main/res/values-tr-rTR/strings.xml
index 23b3bcab8e1..6e0d8af9eb0 100644
--- a/pump/common/src/main/res/values-tr-rTR/strings.xml
+++ b/pump/common/src/main/res/values-tr-rTR/strings.xml
@@ -10,6 +10,7 @@
MeşgulAskıya AlındıKomut Çalıştırılıyor
+
BazallarKonfigürasyon
diff --git a/pump/common/src/main/res/values-uk-rUA/strings.xml b/pump/common/src/main/res/values-uk-rUA/strings.xml
index 479fcf9deb2..87ec5770a99 100644
--- a/pump/common/src/main/res/values-uk-rUA/strings.xml
+++ b/pump/common/src/main/res/values-uk-rUA/strings.xml
@@ -2,6 +2,7 @@
+
diff --git a/pump/common/src/main/res/values-vi-rVN/strings.xml b/pump/common/src/main/res/values-vi-rVN/strings.xml
index 10c99cf5bfb..0ba00bdabb8 100644
--- a/pump/common/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/common/src/main/res/values-vi-rVN/strings.xml
@@ -10,8 +10,27 @@
Đang bậnBị tạm dừngĐang thực hiện lệnh
+
+ Lấy cài đặt
+ Lấy firmware của bơm
+ Lấy Hồ sơ liều nền
+ Thiết lập Hồ sơ liều nền
+ Lấy liều nền tạm thời
+ Hủy bỏ liều nền tạm thời
+ Đặt liều nền tạm thời
+ Đặt liều Bolus
+ Đặt liều Bolus
+ Hủy liều bolus
+ Lấy lượng insulin còn lại
+ Lấy trạng thái pin
+ Lấy thời gian
+ Đặt thời gian
+ Lấy trạng thái bơm
+ Lấy lịch sử
+ Lấy lịch sử %s
+ Lệnh tùy chỉnh
- Liều Basal
+ Liều nềnCấu hìnhThông báoThống kê
@@ -31,6 +50,7 @@
3 giờ trước6 giờ trước12 giờ trước
+ 24 giờ trước2 ngày trước4 ngày trướcTuần trước
diff --git a/pump/common/src/main/res/values-zh-rCN/strings.xml b/pump/common/src/main/res/values-zh-rCN/strings.xml
index 0af3bc8428a..cd456203a3c 100644
--- a/pump/common/src/main/res/values-zh-rCN/strings.xml
+++ b/pump/common/src/main/res/values-zh-rCN/strings.xml
@@ -10,6 +10,7 @@
忙碌挂起正在执行指令
+
基础率配置
diff --git a/pump/common/src/main/res/values-zh-rTW/strings.xml b/pump/common/src/main/res/values-zh-rTW/strings.xml
index 71b77b44112..a1414cc33d5 100644
--- a/pump/common/src/main/res/values-zh-rTW/strings.xml
+++ b/pump/common/src/main/res/values-zh-rTW/strings.xml
@@ -10,6 +10,25 @@
忙碌中已暫停執行命令中
+
+ 讀取設定
+ 讀取幫浦韌體
+ 讀取基礎率設定檔
+ 設定基礎率設定檔
+ 讀取臨時基礎率
+ 取消臨時基礎率
+ 設定臨時基礎率
+ 設定注射
+ 讀取注射
+ 取消注射
+ 讀取剩餘胰島素
+ 讀取電池狀態
+ 讀取時間
+ 設定時間
+ 讀取幫浦狀態
+ 讀取歷史紀錄
+ 讀取歷史紀錄 %s
+ 自訂指令基礎率配置
@@ -31,6 +50,7 @@
過去三小時過去六小時過去十二小時
+ 過去 24 小時過去兩天過去四天過去一週
diff --git a/pump/common/src/main/res/values/strings.xml b/pump/common/src/main/res/values/strings.xml
index 2b7c1a79e78..3896308a1d8 100644
--- a/pump/common/src/main/res/values/strings.xml
+++ b/pump/common/src/main/res/values/strings.xml
@@ -13,6 +13,27 @@
SuspendedExecuting Command
+
+ Get Settings
+ Get Pump Firmware
+ Get Basal Profile
+ Set Basal Profile
+ Get Temporary Basal
+ Cancel Temporary Basal
+ Set Temporary Basal
+ Set Bolus
+ Get Bolus
+ Cancel Bolus
+
+ Get Remaining Insulin
+ Get Battery Status
+ Get Time
+ Set Time
+ Get Pump Status
+ Get History
+ Get History %s
+ Custom command
+
BasalsConfigurations
@@ -35,6 +56,7 @@
Last 3 hoursLast 6 hoursLast 12 hours
+ Last 24 hoursLast 2 daysLast 4 daysLast week
diff --git a/pump/dana/src/main/res/values-sk-rSK/strings.xml b/pump/dana/src/main/res/values-sk-rSK/strings.xml
index ed0b8035981..4536a64a267 100644
--- a/pump/dana/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/dana/src/main/res/values-sk-rSK/strings.xml
@@ -12,9 +12,9 @@
Chyba príkazuChyba rýchlostiPrekročený limit inzulínu
- Požadované: %1$.2fJI Podané: %2$.2fJI Chyba: %3$s
+ Požadované: %1$.2fU Podané: %2$.2fU Chyba: %3$sHodnota nenastavená správne
- Nastavte bazálny krok 0.01JI/h
+ Nastavte bazálny krok 0.01U/hReset informácií o párovaní?%1$s\nModel: %2$02X\nProtokol: %3$02X\nKód: %4$02XSpracúvam udalosť
@@ -84,7 +84,7 @@
DANABluetooth adaptér nenájdenýVybrané zariadenie nenájdené
- Zmeniť v pumpe režim z JI/d na JI/h
+ Zmeniť v pumpe režim z U/d na U/hKórejská DanaRDanaROvládač pumpy opravený
diff --git a/pump/dana/src/main/res/values-vi-rVN/strings.xml b/pump/dana/src/main/res/values-vi-rVN/strings.xml
index 95ed8ff1695..4eca98cf45b 100644
--- a/pump/dana/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/dana/src/main/res/values-vi-rVN/strings.xml
@@ -8,17 +8,17 @@
Dana-i/RSDanaTích hợp bơm cho DANA Diabecare RS và Dana-i
- Vi phạm giới hạn bolus tối đa
+ Vượt giới hạn bolus tối đaLỗi lệnhLỗi tốc độVi phạm giới hạn insulinYêu cầu: %1$.2fU Đã tiêm: %2$.2fU Mã lỗi: %3$sGiá trị không được thiết lập đúng
- Đặt bước basal thành 0,01 U/h
+ Đặt bước liều nền thành 0,01 U/hĐặt lại thông tin ghép đôi?%1$s\nMẫu: %2$02X\nGiao thức: %3$02X\nMã: %4$02XĐang xử lý sự kiện
- Bật bolus mở rộng trên bơm
+ Bật bolus kéo dài trên bơmĐã dừngPhần mềm bơm không được hỗ trợLỗi bơm
@@ -29,33 +29,33 @@
Tắc insulinHết insulinKiểm tra trục truyền động
- Basal tối đa
+ Liều nền tối đaTối đa hàng ngàyCảnh báo đo đường huyếtMức insulin còn lạiQuên bolusThông tin ghép cặp không hợp lệ. Yêu cầu ghép đôi mới
- Đang cập nhật trạng thái pump
- Đang cập nhật trạng thái bolus mở rộng
+ Đang cập nhật trạng thái bơm
+ Đang cập nhật trạng thái bolus kéo dàiĐang cập nhật trạng thái tiêm
- Đang cập nhật trạng thái basal tạm thời
- Đang cập nhật cài đặt pump
- Đang cập nhật thời gian pump
+ Đang cập nhật trạng thái liều nền tạm thời
+ Đang cập nhật cài đặt bơm
+ Đang cập nhật thời gian bơmChênh lệch múi giờ lớnChênh lệch thời gian lớn:\nThời gian trên bơm hiện sai lệch hơn 1,5 giờ.\nHãy điều chỉnh thời gian trên bơm thủ công và đảm bảo việc đọc lịch sử bơm không gây lỗi dữ liệu.\nNếu được, hãy xóa lịch sử trên bơm trước khi thay đổi thời gian, hoặc tạm tắt vòng lặp kín trong một DIA sau mục lịch sử sai cuối cùng, nhưng ít nhất là một DIA kể từ bây giờ.
- Hãy kết nối pump với điện thoại của bạn!
+ Hãy kết nối bơm với điện thoại của bạn!Sắp đạt giới hạn insulin hằng ngàyĐang tiêm liều bolusĐang chờ bolus kết thúc. Còn lại %1$d giây.
- Đang dừng liều basal tạm thời
- Đang cập nhật liều bolus mở rộng
- Đang dừng liều bolus mở rộng
+ Đang dừng liều nền tạm thời
+ Thiết lập bolus kéo dài
+ Đang dừng liều bolus kéo dàiĐang cập nhật tốc độ liều nềnĐang cài đặt liều nền tạm thờiĐang chờ đồng bộ thời gian (%1$d giây)
- Sai mật khẩu pump!
+ Sai mật khẩu bơm!Cảnh báo
- Khung giờ basal
+ Khung giờ liều nềnLiều bolusCarbohydratesInsulin hàng ngày
@@ -77,40 +77,40 @@
Đơn vị đường huyếtTắt máy [giờ]Sắp hết Insulin [u]
- Lưu tùy chọn vào pump
- Tích hợp pump insulin DANA Diabecare R
- Tích hợp pump DANA Diabecare R (bản nội địa)
- Tích hợp pump DANA Diabecare R với firmware đã nâng cấp
+ Lưu tùy chọn vào bơm
+ Tích hợp bơm insulin DANA Diabecare R
+ Tích hợp bơm DANA Diabecare R (bản nội địa)
+ Tích hợp bơm DANA Diabecare R với firmware đã nâng cấpDANAKhông phát hiện BluetoothKhông tìm thấy thiết bị đã chọn
- Thay đổi chế độ từ U/d sang U/h trên pump
+ Thay đổi chế độ từ U/d sang U/h trên bơmDanaR KoreanDanaR
- Trình điều khiển pump đã được sửa
+ Trình điều khiển bơm đã được sửaDanaRv2
- Tắt chế độ EasyUI trên pump
- Cài đặt cấu hình basal thất bại
+ Tắt chế độ EasyUI trên bơm
+ Cài đặt Hồ sơ liều nền thất bạiTrạng thái BluetoothPhần mềm
- Cài đặt pump Dana
+ Cài đặt bơm Dana12h24hBậtTắtThiết bị Bluetooth DanaR
- Mật khẩu pump (chỉ v1)
- Mật khẩu pump
- Sử dụng bolus mở rộng khi >200%
+ Mật khẩu bơm (chỉ v1)
+ Mật khẩu bơm
+ Sử dụng bolus kéo dài khi >200%Tốc độ Bolus
- Pump đã chọn
+ Bơm đã chọnGhi lại thay đổi bình chứaThêm sự kiện \"Thay đổi insulin\" vào careportal khi phát hiện trong lịch sửGhi lại thay đổi kim truyềnThêm sự kiện \"Thay đổi kim truyền\" vào careportal khi phát hiện trong lịch sửMã PIN1Mã PIN2
- Nhấn OK trên pump\nvà nhập 2 số hiển thị\nGiữ màn hình bơm luôn BẬT bằng cách nhấn nút trừ cho đến khi bạn nhập xong mã.
+ Nhấn OK trên Bơm\nvà nhập 2 số hiển thị\nGiữ màn hình bơm luôn BẬT bằng cách nhấn nút trừ cho đến khi bạn nhập xong mã.1: (12 chữ số)2: (8 chữ số)Bước điều chỉnh basal/bolus
diff --git a/pump/danar/src/main/res/values-pl-rPL/strings.xml b/pump/danar/src/main/res/values-pl-rPL/strings.xml
index 4924a438709..78ebd3a15c0 100644
--- a/pump/danar/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/danar/src/main/res/values-pl-rPL/strings.xml
@@ -1,4 +1,5 @@
Nieobsługiwana akcja w pompie. Używaj tylko interfejsu AndroidAPS!
+ Czekam %1$d/%2$d sek przed nową próbą połączenia
diff --git a/pump/danar/src/main/res/values-vi-rVN/strings.xml b/pump/danar/src/main/res/values-vi-rVN/strings.xml
index bdc280b0704..6edfc9d2ca1 100644
--- a/pump/danar/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/danar/src/main/res/values-vi-rVN/strings.xml
@@ -1,5 +1,5 @@
- Pump không hỗ trợ thao tác này. Vui lòng chỉ dùng giao diện AndroidAPS!
+ Bơm không hỗ trợ thao tác này. Vui lòng chỉ dùng giao diện AndroidAPS!Đang chờ %1$d/%2$d giây trước khi thử kết nối lại
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/DanaRPluginTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/DanaRPluginTest.kt
similarity index 98%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/DanaRPluginTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/DanaRPluginTest.kt
index 25e20b7ff3b..90d6b37733c 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/DanaRPluginTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/DanaRPluginTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR
+package app.aaps.pump.danar
import app.aaps.core.data.plugin.PluginType
import app.aaps.core.interfaces.constraints.ConstraintsChecker
@@ -9,7 +9,6 @@ import app.aaps.core.objects.constraints.ConstraintObject
import app.aaps.pump.dana.DanaPump
import app.aaps.pump.dana.database.DanaHistoryDatabase
import app.aaps.pump.dana.keys.DanaStringKey
-import app.aaps.pump.danar.DanaRPlugin
import app.aaps.shared.tests.TestBaseWithProfile
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Assertions
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danar/SerialIOThreadTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/SerialIOThreadTest.kt
index 5530bd85f23..ca8a3fa57e7 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danar/SerialIOThreadTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/SerialIOThreadTest.kt
@@ -8,10 +8,8 @@ import app.aaps.shared.tests.TestBase
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
-import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/DanaRTestBase.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/DanaRTestBase.kt
similarity index 97%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/DanaRTestBase.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/DanaRTestBase.kt
index b21b5f90b42..9b2484dacd9 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/DanaRTestBase.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/DanaRTestBase.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.interfaces.configuration.ConfigBuilder
import app.aaps.core.interfaces.constraints.ConstraintsChecker
@@ -9,7 +9,6 @@ import app.aaps.core.interfaces.ui.UiInteraction
import app.aaps.pump.dana.DanaPump
import app.aaps.pump.dana.database.DanaHistoryRecordDao
import app.aaps.pump.danar.DanaRPlugin
-import app.aaps.pump.danar.comm.MessageBase
import app.aaps.pump.danarkorean.DanaRKoreanPlugin
import app.aaps.pump.danarv2.DanaRv2Plugin
import app.aaps.shared.tests.TestBaseWithProfile
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MessageHashTableRTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MessageHashTableRTest.kt
similarity index 87%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MessageHashTableRTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MessageHashTableRTest.kt
index d60c91e5016..d2e76e84263 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MessageHashTableRTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MessageHashTableRTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.objects.constraints.ConstraintObject
-import app.aaps.pump.danar.comm.MessageHashTableR
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MessageOriginalNamesTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MessageOriginalNamesTest.kt
similarity index 76%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MessageOriginalNamesTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MessageOriginalNamesTest.kt
index 03c04813b2a..f131d8e57fd 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MessageOriginalNamesTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MessageOriginalNamesTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MessageOriginalNames
import app.aaps.shared.tests.TestBase
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusProgressTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusProgressTest.kt
similarity index 88%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusProgressTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusProgressTest.kt
index ea7161d7f8d..50036245aac 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusProgressTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusProgressTest.kt
@@ -1,8 +1,7 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.interfaces.pump.BolusProgressData
import app.aaps.core.interfaces.pump.DetailedBolusInfo
-import app.aaps.pump.danar.comm.MsgBolusProgress
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStartTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStartTest.kt
similarity index 90%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStartTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStartTest.kt
index 5cf6b3ae533..43805c75292 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStartTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStartTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.objects.constraints.ConstraintObject
-import app.aaps.pump.danar.comm.MsgBolusStart
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStartWithSpeedTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStartWithSpeedTest.kt
similarity index 89%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStartWithSpeedTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStartWithSpeedTest.kt
index 2067eb3bd33..d1cc9246441 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStartWithSpeedTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStartWithSpeedTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.objects.constraints.ConstraintObject
-import app.aaps.pump.danar.comm.MsgBolusStartWithSpeed
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStopTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStopTest.kt
similarity index 87%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStopTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStopTest.kt
index 050fcd9c87d..b6ae9a638e1 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgBolusStopTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgBolusStopTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.interfaces.pump.DetailedBolusInfo
-import app.aaps.pump.danar.comm.MsgBolusStop
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgCheckValueTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgCheckValueTest.kt
similarity index 85%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgCheckValueTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgCheckValueTest.kt
index db78a5403c6..fd21c572961 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgCheckValueTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgCheckValueTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.comm.MsgCheckValue
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgErrorTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgErrorTest.kt
similarity index 88%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgErrorTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgErrorTest.kt
index b9bf78deaf6..0584f8811e7 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgErrorTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgErrorTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgError
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAlarmTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAlarmTest.kt
similarity index 74%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAlarmTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAlarmTest.kt
index d41202aa096..d8971c3d015 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAlarmTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAlarmTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryAlarm
import org.junit.jupiter.api.Test
class MsgHistoryAlarmTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAllDoneTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAllDoneTest.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAllDoneTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAllDoneTest.kt
index 853a1cfa7ac..ef740cb1ee0 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAllDoneTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAllDoneTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryAllDone
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAllTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAllTest.kt
similarity index 87%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAllTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAllTest.kt
index 0f84d702b5f..453db45e84d 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryAllTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryAllTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryAll
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryBasalHourTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryBasalHourTest.kt
similarity index 73%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryBasalHourTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryBasalHourTest.kt
index 3189802940e..bb58236cdea 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryBasalHourTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryBasalHourTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryBasalHour
import org.junit.jupiter.api.Test
class MsgHistoryBasalHourTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryBolusTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryBolusTest.kt
similarity index 74%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryBolusTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryBolusTest.kt
index 29f77cf83a0..a2c39933678 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryBolusTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryBolusTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryBolus
import org.junit.jupiter.api.Test
class MsgHistoryBolusTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryCarboTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryCarboTest.kt
similarity index 74%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryCarboTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryCarboTest.kt
index fa517d99fef..60efdb544e8 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryCarboTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryCarboTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryCarbo
import org.junit.jupiter.api.Test
class MsgHistoryCarboTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryDailyInsulinTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryDailyInsulinTest.kt
similarity index 73%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryDailyInsulinTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryDailyInsulinTest.kt
index 7718edc2671..1b076df5522 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryDailyInsulinTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryDailyInsulinTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryDailyInsulin
import org.junit.jupiter.api.Test
class MsgHistoryDailyInsulinTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryDoneTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryDoneTest.kt
similarity index 74%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryDoneTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryDoneTest.kt
index 4b5a7a663e4..1f8f1909f12 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryDoneTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryDoneTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryDone
import org.junit.jupiter.api.Test
class MsgHistoryDoneTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryErrorTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryErrorTest.kt
similarity index 74%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryErrorTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryErrorTest.kt
index d14efca1395..9bf0e1857f0 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryErrorTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryErrorTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryError
import org.junit.jupiter.api.Test
class MsgHistoryErrorTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryGlucoseTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryGlucoseTest.kt
similarity index 73%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryGlucoseTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryGlucoseTest.kt
index 46b717e684a..5d2ddeb2afe 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryGlucoseTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryGlucoseTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryGlucose
import org.junit.jupiter.api.Test
class MsgHistoryGlucoseTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryNewDoneTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryNewDoneTest.kt
similarity index 73%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryNewDoneTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryNewDoneTest.kt
index 22021bcf459..47120b81bde 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryNewDoneTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryNewDoneTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryNewDone
import org.junit.jupiter.api.Test
class MsgHistoryNewDoneTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryNewTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryNewTest.kt
similarity index 74%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryNewTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryNewTest.kt
index 967b613b8a5..bdf16fcbe06 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryNewTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryNewTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryNew
import org.junit.jupiter.api.Test
class MsgHistoryNewTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryRefillTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryRefillTest.kt
similarity index 74%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryRefillTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryRefillTest.kt
index 52b42e1c9ce..6c8f79369dd 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistoryRefillTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistoryRefillTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistoryRefill
import org.junit.jupiter.api.Test
class MsgHistoryRefillTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistorySuspendTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistorySuspendTest.kt
similarity index 73%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistorySuspendTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistorySuspendTest.kt
index 7523db3b73e..4fdcc29683d 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgHistorySuspendTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgHistorySuspendTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgHistorySuspend
import org.junit.jupiter.api.Test
class MsgHistorySuspendTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBasicTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBasicTest.kt
similarity index 82%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBasicTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBasicTest.kt
index 87821f6853b..f117a812569 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBasicTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBasicTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgInitConnStatusBasic
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBasicTest.kt.unused b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBasicTest.kt.unused
similarity index 93%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBasicTest.kt.unused
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBasicTest.kt.unused
index 87821f6853b..dd0d7b3ab9d 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBasicTest.kt.unused
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBasicTest.kt.unused
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.danar.comm.MsgInitConnStatusBasic
import org.junit.jupiter.api.Assertions
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBolusTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBolusTest.kt
similarity index 86%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBolusTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBolusTest.kt
index 977d7e87d93..5c5597fed3b 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusBolusTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusBolusTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgInitConnStatusBolus
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusOptionTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusOptionTest.kt
similarity index 85%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusOptionTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusOptionTest.kt
index ae5b32cddb1..fb41e01c275 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusOptionTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusOptionTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgInitConnStatusOption
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusTimeTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusTimeTest.kt
similarity index 85%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusTimeTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusTimeTest.kt
index 307cf4d3797..71aa084fe5f 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgInitConnStatusTimeTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgInitConnStatusTimeTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgInitConnStatusTime
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgPCCommStartTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgPCCommStartTest.kt
similarity index 75%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgPCCommStartTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgPCCommStartTest.kt
index 0210c10332b..23a6a02f217 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgPCCommStartTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgPCCommStartTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgPCCommStart
import org.junit.jupiter.api.Test
class MsgPCCommStartTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgPCCommStopTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgPCCommStopTest.kt
similarity index 76%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgPCCommStopTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgPCCommStopTest.kt
index 4486e621f2d..93dbcd01685 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgPCCommStopTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgPCCommStopTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgPCCommStop
import org.junit.jupiter.api.Test
class MsgPCCommStopTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetActivateBasalProfileTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetActivateBasalProfileTest.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetActivateBasalProfileTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetActivateBasalProfileTest.kt
index d3506fe0445..aa05f378493 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetActivateBasalProfileTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetActivateBasalProfileTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetActivateBasalProfile
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetBasalProfileTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetBasalProfileTest.kt
similarity index 82%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetBasalProfileTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetBasalProfileTest.kt
index 804aa169b18..34ad87aef13 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetBasalProfileTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetBasalProfileTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetBasalProfile
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetCarbsEntryTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetCarbsEntryTest.kt
similarity index 82%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetCarbsEntryTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetCarbsEntryTest.kt
index 828f52c63fb..e84047cee7f 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetCarbsEntryTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetCarbsEntryTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetCarbsEntry
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetExtendedBolusStartTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetExtendedBolusStartTest.kt
similarity index 87%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetExtendedBolusStartTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetExtendedBolusStartTest.kt
index 6561296eeb9..c2cc95c2e68 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetExtendedBolusStartTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetExtendedBolusStartTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.objects.constraints.ConstraintObject
-import app.aaps.pump.danar.comm.MsgSetExtendedBolusStart
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetExtendedBolusStopTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetExtendedBolusStopTest.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetExtendedBolusStopTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetExtendedBolusStopTest.kt
index 5f7ead35a7e..78b208bb24d 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetExtendedBolusStopTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetExtendedBolusStopTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetExtendedBolusStop
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetSingleBasalProfileTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetSingleBasalProfileTest.kt
similarity index 81%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetSingleBasalProfileTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetSingleBasalProfileTest.kt
index 3d75cc10ff8..1fa23b5c15c 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetSingleBasalProfileTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetSingleBasalProfileTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetSingleBasalProfile
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetTempBasalStartTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetTempBasalStartTest.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetTempBasalStartTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetTempBasalStartTest.kt
index d420fce0a97..3b0f1b92c37 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetTempBasalStartTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetTempBasalStartTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetTempBasalStart
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetTimeTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetTimeTest.kt
similarity index 82%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetTimeTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetTimeTest.kt
index 926f0885208..0da635fd6b8 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetTimeTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetTimeTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetTime
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetUserOptionsTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetUserOptionsTest.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetUserOptionsTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetUserOptionsTest.kt
index 6e3295a13f4..3dd2894f861 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSetUserOptionsTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSetUserOptionsTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSetUserOptions
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingActiveProfileTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingActiveProfileTest.kt
similarity index 82%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingActiveProfileTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingActiveProfileTest.kt
index 2542fa97e26..c72cb8841d5 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingActiveProfileTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingActiveProfileTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSettingActiveProfile
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalProfileAllTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalProfileAllTest.kt
similarity index 75%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalProfileAllTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalProfileAllTest.kt
index 445cf53df97..11f24658d30 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalProfileAllTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalProfileAllTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSettingBasalProfileAll
import org.junit.jupiter.api.Test
class MsgSettingBasalProfileAllTest : DanaRTestBase() {
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalProfileAllTest.kt.unused b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalProfileAllTest.kt.unused
similarity index 91%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalProfileAllTest.kt.unused
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalProfileAllTest.kt.unused
index 445cf53df97..797e2f4a23a 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalProfileAllTest.kt.unused
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalProfileAllTest.kt.unused
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.danar.comm.MsgSettingBasalProfileAll
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalTest.kt
similarity index 89%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalTest.kt
index c118ffac309..6ce6d66b9c7 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingBasalTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingBasalTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.data.pump.defs.PumpDescription
-import app.aaps.pump.danar.comm.MsgSettingBasal
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.mockito.kotlin.whenever
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingGlucoseTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingGlucoseTest.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingGlucoseTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingGlucoseTest.kt
index 8b8f6d60100..8127ca7b4c7 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingGlucoseTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingGlucoseTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSettingGlucose
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingMaxValuesTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingMaxValuesTest.kt
similarity index 83%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingMaxValuesTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingMaxValuesTest.kt
index c5f9c935521..4f1d52828bd 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingMaxValuesTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingMaxValuesTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSettingMaxValues
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingMealTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingMealTest.kt
similarity index 84%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingMealTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingMealTest.kt
index b144691acb6..6ed9a82a3f4 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingMealTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingMealTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgSettingMeal
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingProfileRatiosAllTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingProfileRatiosAllTest.kt
similarity index 84%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingProfileRatiosAllTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingProfileRatiosAllTest.kt
index 1c731109df6..71b7dc5ac31 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingProfileRatiosAllTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingProfileRatiosAllTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.comm.MsgSettingProfileRatiosAll
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingProfileRatiosTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingProfileRatiosTest.kt
similarity index 84%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingProfileRatiosTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingProfileRatiosTest.kt
index cf6016e9ed3..5e02c4678b1 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingProfileRatiosTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingProfileRatiosTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.comm.MsgSettingProfileRatios
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingPumpTimeTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingPumpTimeTest.kt
similarity index 90%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingPumpTimeTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingPumpTimeTest.kt
index d6a4cd782f5..4c9de357043 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingPumpTimeTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingPumpTimeTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.comm.MsgSettingPumpTime
import org.joda.time.DateTime
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingShippingInfoTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingShippingInfoTest.kt
similarity index 79%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingShippingInfoTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingShippingInfoTest.kt
index c60cc2f0bee..53843a0014f 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingShippingInfoTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingShippingInfoTest.kt
@@ -1,8 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.comm.MessageBase
-import app.aaps.pump.danar.comm.MsgSettingShippingInfo
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingUserOptionsTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingUserOptionsTest.kt
similarity index 83%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingUserOptionsTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingUserOptionsTest.kt
index 09e595fc0a3..de879702a73 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgSettingUserOptionsTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgSettingUserOptionsTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.comm.MsgSettingUserOptions
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusBasicTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusBasicTest.kt
similarity index 84%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusBasicTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusBasicTest.kt
index a86fac71a1f..73cf41bd7ba 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusBasicTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusBasicTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgStatusBasic
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusBolusExtendedTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusBolusExtendedTest.kt
similarity index 85%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusBolusExtendedTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusBolusExtendedTest.kt
index 7648a001459..e73b5a7e474 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusBolusExtendedTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusBolusExtendedTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.core.data.time.T
-import app.aaps.pump.danar.comm.MsgStatusBolusExtended
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusProfileTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusProfileTest.kt
similarity index 85%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusProfileTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusProfileTest.kt
index b147aa3fd29..abfc547dfbd 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusProfileTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusProfileTest.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.comm.MsgStatusProfile
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusProfileTest.kt.unused b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusProfileTest.kt.unused
similarity index 94%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusProfileTest.kt.unused
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusProfileTest.kt.unused
index b147aa3fd29..0824b031351 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusProfileTest.kt.unused
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusProfileTest.kt.unused
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.DanaPump
import app.aaps.pump.danar.comm.MsgStatusProfile
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusTempBasalTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusTempBasalTest.kt
similarity index 86%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusTempBasalTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusTempBasalTest.kt
index 36dd8152c08..c0761efb367 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusTempBasalTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusTempBasalTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgStatusTempBasal
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusTest.kt
similarity index 84%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusTest.kt
index aa66033c7c2..c735ba246aa 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/MsgStatusTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/MsgStatusTest.kt
@@ -1,6 +1,5 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
-import app.aaps.pump.danar.comm.MsgStatus
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/RecordTypesTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/RecordTypesTest.kt
similarity index 88%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/RecordTypesTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/RecordTypesTest.kt
index bf374b61ac7..78f991b3f53 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/comm/RecordTypesTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/comm/RecordTypesTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR.comm
+package app.aaps.pump.danar.comm
import app.aaps.pump.dana.comm.RecordTypes
import org.junit.jupiter.api.Assertions
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/services/AbstractDanaRExecutionServiceTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/services/AbstractDanaRExecutionServiceTest.kt
similarity index 97%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/services/AbstractDanaRExecutionServiceTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/services/AbstractDanaRExecutionServiceTest.kt
index 3c694c2157f..76fd2dd15f9 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/services/AbstractDanaRExecutionServiceTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/services/AbstractDanaRExecutionServiceTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR.services
+package app.aaps.pump.danar.services
import android.bluetooth.BluetoothManager
import android.content.Context
@@ -13,7 +13,6 @@ import app.aaps.pump.dana.comm.RecordTypes
import app.aaps.pump.dana.keys.DanaStringKey
import app.aaps.pump.danar.comm.MessageHashTableBase
import app.aaps.pump.danar.comm.MsgBolusStop
-import app.aaps.pump.danar.services.AbstractDanaRExecutionService
import app.aaps.shared.tests.TestBaseWithProfile
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.BeforeEach
@@ -48,10 +47,11 @@ class AbstractDanaRExecutionServiceTest : TestBaseWithProfile() {
private lateinit var testService: TestDanaRExecutionService
inner class TestDanaRExecutionService : AbstractDanaRExecutionService() {
+
override fun messageHashTable(): MessageHashTableBase = messageHashTable
override fun updateBasalsInPump(profile: Profile): Boolean = true
override fun getPumpStatus() {}
- override fun loadEvents(): PumpEnactResult? = pumpEnactResult
+ override fun loadEvents(): PumpEnactResult = pumpEnactResult
override fun bolus(detailedBolusInfo: DetailedBolusInfo): Boolean = true
override fun highTempBasal(percent: Int, durationInMinutes: Int): Boolean = false
override fun tempBasalShortDuration(percent: Int, durationInMinutes: Int): Boolean = false
@@ -59,7 +59,7 @@ class AbstractDanaRExecutionServiceTest : TestBaseWithProfile() {
override fun tempBasalStop(): Boolean = true
override fun extendedBolus(insulin: Double, durationInHalfHours: Int): Boolean = true
override fun extendedBolusStop(): Boolean = true
- override fun setUserOptions(): PumpEnactResult? = pumpEnactResult
+ override fun setUserOptions(): PumpEnactResult = pumpEnactResult
}
@BeforeEach
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/services/DanaRExecutionServiceTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danar/services/DanaRExecutionServiceTest.kt
similarity index 97%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaR/services/DanaRExecutionServiceTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danar/services/DanaRExecutionServiceTest.kt
index 27b9c3b99a7..5bf6c59f8c7 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaR/services/DanaRExecutionServiceTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danar/services/DanaRExecutionServiceTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaR.services
+package app.aaps.pump.danar.services
import app.aaps.core.interfaces.profile.Profile
import app.aaps.core.interfaces.pump.DetailedBolusInfo
@@ -8,7 +8,6 @@ import app.aaps.core.interfaces.ui.UiInteraction
import app.aaps.pump.dana.DanaPump
import app.aaps.pump.danar.DanaRPlugin
import app.aaps.pump.danar.comm.MessageHashTableR
-import app.aaps.pump.danar.services.DanaRExecutionService
import app.aaps.pump.danarkorean.DanaRKoreanPlugin
import app.aaps.shared.tests.TestBaseWithProfile
import com.google.common.truth.Truth.assertThat
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRKorean/DanaRKoreanPluginTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarkorean/DanaRKoreanPluginTest.kt
similarity index 97%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRKorean/DanaRKoreanPluginTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarkorean/DanaRKoreanPluginTest.kt
index 47a8b6eb544..8f5473927da 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRKorean/DanaRKoreanPluginTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarkorean/DanaRKoreanPluginTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaRKorean
+package app.aaps.pump.danarkorean
import app.aaps.core.data.plugin.PluginType
import app.aaps.core.interfaces.constraints.ConstraintsChecker
@@ -9,7 +9,6 @@ import app.aaps.core.objects.constraints.ConstraintObject
import app.aaps.pump.dana.DanaPump
import app.aaps.pump.dana.database.DanaHistoryDatabase
import app.aaps.pump.dana.keys.DanaStringKey
-import app.aaps.pump.danarkorean.DanaRKoreanPlugin
import app.aaps.shared.tests.TestBaseWithProfile
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Assertions
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRKorean/comm/MessageHashTableRKoreanTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarkorean/comm/MessageHashTableRKoreanTest.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRKorean/comm/MessageHashTableRKoreanTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarkorean/comm/MessageHashTableRKoreanTest.kt
index f91ef89eda1..0286b03fb2d 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRKorean/comm/MessageHashTableRKoreanTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarkorean/comm/MessageHashTableRKoreanTest.kt
@@ -1,8 +1,7 @@
-package app.aaps.pump.danaRKorean.comm
+package app.aaps.pump.danarkorean.comm
import app.aaps.core.objects.constraints.ConstraintObject
-import app.aaps.pump.danaR.comm.DanaRTestBase
-import app.aaps.pump.danarkorean.comm.MessageHashTableRKorean
+import app.aaps.pump.danar.comm.DanaRTestBase
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/DanaRv2PluginTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/DanaRv2PluginTest.kt
similarity index 98%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/DanaRv2PluginTest.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarv2/DanaRv2PluginTest.kt
index edc61110085..82570aef137 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/DanaRv2PluginTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/DanaRv2PluginTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.danaRv2
+package app.aaps.pump.danarv2
import app.aaps.core.data.plugin.PluginType
import app.aaps.core.interfaces.constraints.ConstraintsChecker
@@ -11,7 +11,6 @@ import app.aaps.core.objects.constraints.ConstraintObject
import app.aaps.pump.dana.DanaPump
import app.aaps.pump.dana.database.DanaHistoryDatabase
import app.aaps.pump.dana.keys.DanaStringKey
-import app.aaps.pump.danarv2.DanaRv2Plugin
import app.aaps.shared.tests.TestBaseWithProfile
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Assertions
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MessageHashTableRv2Test.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MessageHashTableRv2Test.kt
similarity index 84%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MessageHashTableRv2Test.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MessageHashTableRv2Test.kt
index dcbe1d65697..c9f6861d28a 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MessageHashTableRv2Test.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MessageHashTableRv2Test.kt
@@ -1,10 +1,8 @@
-package app.aaps.pump.danaRv2.comm
+package app.aaps.pump.danarv2.comm
import app.aaps.core.objects.constraints.ConstraintObject
-import app.aaps.pump.danaR.comm.DanaRTestBase
+import app.aaps.pump.danar.comm.DanaRTestBase
import app.aaps.pump.danar.comm.MessageBase
-import app.aaps.pump.danarv2.comm.MessageHashTableRv2
-import app.aaps.pump.danarv2.comm.MsgStatusAPSV2
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgCheckValueRv2Test.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgCheckValueRv2Test.kt
similarity index 75%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgCheckValueRv2Test.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgCheckValueRv2Test.kt
index b6d84773a4b..4bc8e60ca1e 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgCheckValueRv2Test.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgCheckValueRv2Test.kt
@@ -1,8 +1,7 @@
-package app.aaps.pump.danaRv2.comm
+package app.aaps.pump.danarv2.comm
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danaR.comm.DanaRTestBase
-import app.aaps.pump.danarv2.comm.MsgCheckValueV2
+import app.aaps.pump.danar.comm.DanaRTestBase
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgHistoryEventsRv2Test.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgHistoryEventsRv2Test.kt
similarity index 81%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgHistoryEventsRv2Test.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgHistoryEventsRv2Test.kt
index dde52b405ee..f22602665a1 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgHistoryEventsRv2Test.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgHistoryEventsRv2Test.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaRv2.comm
+package app.aaps.pump.danarv2.comm
-import app.aaps.pump.danaR.comm.DanaRTestBase
-import app.aaps.pump.danarv2.comm.MsgHistoryEventsV2
+import app.aaps.pump.danar.comm.DanaRTestBase
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgSetAPSTempBasalStartRv2Test.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgSetAPSTempBasalStartRv2Test.kt
similarity index 94%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgSetAPSTempBasalStartRv2Test.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgSetAPSTempBasalStartRv2Test.kt
index 9ebba177ed8..c3adbe60919 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgSetAPSTempBasalStartRv2Test.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgSetAPSTempBasalStartRv2Test.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaRv2.comm
+package app.aaps.pump.danarv2.comm
-import app.aaps.pump.danaR.comm.DanaRTestBase
-import app.aaps.pump.danarv2.comm.MsgSetAPSTempBasalStartV2
+import app.aaps.pump.danar.comm.DanaRTestBase
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgSetHistoryEntryRv2Test.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgSetHistoryEntryRv2Test.kt
similarity index 80%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgSetHistoryEntryRv2Test.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgSetHistoryEntryRv2Test.kt
index 1c1ca5da4fd..a4acfba4636 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgSetHistoryEntryRv2Test.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgSetHistoryEntryRv2Test.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaRv2.comm
+package app.aaps.pump.danarv2.comm
-import app.aaps.pump.danaR.comm.DanaRTestBase
-import app.aaps.pump.danarv2.comm.MsgSetHistoryEntryV2
+import app.aaps.pump.danar.comm.DanaRTestBase
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgStatusAPSRv2Test.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgStatusAPSRv2Test.kt
similarity index 77%
rename from pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgStatusAPSRv2Test.kt
rename to pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgStatusAPSRv2Test.kt
index f68715849aa..4c638200228 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danaRv2/comm/MsgStatusAPSRv2Test.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/comm/MsgStatusAPSRv2Test.kt
@@ -1,7 +1,6 @@
-package app.aaps.pump.danaRv2.comm
+package app.aaps.pump.danarv2.comm
-import app.aaps.pump.danaR.comm.DanaRTestBase
-import app.aaps.pump.danarv2.comm.MsgStatusAPSV2
+import app.aaps.pump.danar.comm.DanaRTestBase
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
diff --git a/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/services/DanaRv2ExecutionServiceTest.kt b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/services/DanaRv2ExecutionServiceTest.kt
index e35f6263a14..7036cd18c27 100644
--- a/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/services/DanaRv2ExecutionServiceTest.kt
+++ b/pump/danar/src/test/kotlin/app/aaps/pump/danarv2/services/DanaRv2ExecutionServiceTest.kt
@@ -1,16 +1,12 @@
package app.aaps.pump.danarv2.services
-import android.bluetooth.BluetoothSocket
import app.aaps.core.interfaces.profile.Profile
-import app.aaps.core.interfaces.profile.ProfileFunction
import app.aaps.core.interfaces.pump.DetailedBolusInfo
import app.aaps.core.interfaces.pump.PumpEnactResult
import app.aaps.core.interfaces.pump.PumpSync
-import app.aaps.core.interfaces.queue.Command
import app.aaps.core.interfaces.queue.CommandQueue
import app.aaps.core.interfaces.ui.UiInteraction
import app.aaps.pump.dana.DanaPump
-import app.aaps.pump.danar.SerialIOThread
import app.aaps.pump.danarkorean.DanaRKoreanPlugin
import app.aaps.pump.danarv2.DanaRv2Plugin
import app.aaps.pump.danarv2.comm.MessageHashTableRv2
@@ -20,10 +16,8 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.`when`
-import javax.inject.Provider
class DanaRv2ExecutionServiceTest : TestBaseWithProfile() {
diff --git a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Plugin.kt b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Plugin.kt
index 9260d6894ef..b64c4363ee7 100644
--- a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Plugin.kt
+++ b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Plugin.kt
@@ -126,8 +126,11 @@ class DiaconnG8Plugin @Inject constructor(
disposable += rxBus
.toObservable(EventDiaconnG8DeviceChange::class.java)
.observeOn(aapsSchedulers.io)
- .subscribe({ changePump() }) { fabricPrivacy.logException(it) }
- changePump() // load device name
+ .subscribe({
+ pumpSync.connectNewPump()
+ changePump()
+ }) { fabricPrivacy.logException(it) }
+ changePump() // load device name on app start
}
override fun onStop() {
@@ -150,10 +153,27 @@ class DiaconnG8Plugin @Inject constructor(
}
fun changePump() {
- mDeviceAddress = preferences.get(DiaconnStringNonKey.Address)
- mDeviceName = preferences.get(DiaconnStringNonKey.Name)
+ val newAddress = preferences.get(DiaconnStringNonKey.Address)
+ val newName = preferences.get(DiaconnStringNonKey.Name)
+
+ // Check if device actually changed by comparing addresses
+ val isDeviceChanged = mDeviceAddress.isNotEmpty() && mDeviceAddress != newAddress
+
+ // Firmware 3.58+: force disconnect since disconnect() is skipped for permanent connection
+ if (isDeviceChanged && diaconnG8Pump.isPumpVersionGe3_58) {
+ diaconnG8Service?.disconnect("Pump changed")
+ }
+
+ mDeviceAddress = newAddress
+ mDeviceName = newName
diaconnG8Pump.reset()
- commandQueue.readStatus(rh.gs(app.aaps.core.ui.R.string.device_changed), null)
+
+ // Use different message for app start vs actual device change
+ val reason = if (isDeviceChanged)
+ rh.gs(app.aaps.core.ui.R.string.device_changed)
+ else
+ rh.gs(R.string.gettingpumpsettings)
+ commandQueue.readStatus(reason, null)
}
override fun connect(reason: String) {
@@ -170,6 +190,11 @@ class DiaconnG8Plugin @Inject constructor(
override fun disconnect(reason: String) {
aapsLogger.debug(LTag.PUMP, "Diaconn G8 disconnect from: $reason")
+ // Firmware 3.58+: permanent BLE connection, skip actual disconnect
+ if (diaconnG8Pump.isPumpVersionGe3_58) {
+ aapsLogger.debug(LTag.PUMP, "Skipping disconnect for firmware 3.58+ (permanent connection)")
+ return
+ }
diaconnG8Service?.disconnect(reason)
}
diff --git a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Pump.kt b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Pump.kt
index 6ee18e4f06e..e1b1d9f3f45 100644
--- a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Pump.kt
+++ b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/DiaconnG8Pump.kt
@@ -31,6 +31,7 @@ class DiaconnG8Pump @Inject constructor(
var pumpIncarnationNum: Int = 65536
var isPumpVersionGe2_63: Boolean = false // is pumpVersion higher then 2.63
var isPumpVersionGe3_53: Boolean = false // is pumpVersion higher then 3.42
+ var isPumpVersionGe3_58: Boolean = false // BLE permanent connection support
var insulinWarningGrade: Int = 0
var insulinWarningProcess: Int = 0
var insulinWarningRemain: Int = 0
@@ -107,6 +108,37 @@ class DiaconnG8Pump @Inject constructor(
}
}
+ /**
+ * Sync TBR state from pump response fields (tbStatus, tbTime, tbInjectRateRatio, tbElapsedTime)
+ * This is more reliable than pumpSync.expectedPumpState() which may have timing issues
+ * Note: tbTime is in 15-minute units (e.g., tbTime=2 means 30 minutes)
+ * tbElapsedTime is in minutes
+ */
+ fun syncTempBasalFromPump() {
+ if (tbStatus == 1) { // TBR is running
+ // Calculate start time from elapsed time (tbElapsedTime is in minutes)
+ tempBasalStart = dateUtil.now() - T.mins(tbElapsedTime.toLong()).msecs()
+ // Duration in milliseconds (tbTime is in 15-minute units)
+ tempBasalDuration = T.mins((tbTime * 15).toLong()).msecs()
+ // Calculate absolute rate from tbInjectRateRatio
+ tempBasalAbsoluteRate = if (tbInjectRateRatio >= 50000) {
+ // Percentage mode: 50000 = 0%, 50100 = 100%, 50250 = 250%
+ val percent = tbInjectRateRatio - 50000
+ baseAmount * percent / 100.0
+ } else {
+ // Absolute mode: 1000 = 0.00 U/h, 1025 = 0.25 U/h, 1600 = 6.00 U/h
+ (tbInjectRateRatio - 1000) / 100.0
+ }
+ aapsLogger.debug(LTag.PUMP, "syncTempBasalFromPump: running, start=$tempBasalStart, duration=${T.msecs(tempBasalDuration).mins()}min (tbTime=$tbTime), rate=$tempBasalAbsoluteRate U/h")
+ } else {
+ // TBR is not running - clear state
+ tempBasalStart = 0
+ tempBasalDuration = 0
+ tempBasalAbsoluteRate = 0.0
+ aapsLogger.debug(LTag.PUMP, "syncTempBasalFromPump: not running (tbStatus=$tbStatus), state cleared")
+ }
+ }
+
/*
* EXTENDED BOLUSES
*/
@@ -158,6 +190,28 @@ class DiaconnG8Pump @Inject constructor(
}
}
+ /**
+ * Sync Extended Bolus state from pump response fields (squareStatus, squareTime, squareInjTime, squareAmount)
+ * This is more reliable than pumpSync.expectedPumpState() which may have timing issues
+ */
+ fun syncExtendedBolusFromPump() {
+ if (squareStatus == 1) { // EB is running
+ // Calculate start time from elapsed time
+ extendedBolusStart = dateUtil.now() - T.mins(squareInjTime.toLong()).msecs()
+ // Duration in milliseconds
+ extendedBolusDuration = T.mins(squareTime.toLong()).msecs()
+ // Amount
+ extendedBolusAmount = squareAmount
+ aapsLogger.debug(LTag.PUMP, "syncExtendedBolusFromPump: running, start=$extendedBolusStart, duration=${T.msecs(extendedBolusDuration).mins()}min, amount=$extendedBolusAmount U")
+ } else {
+ // EB is not running - clear state
+ extendedBolusStart = 0
+ extendedBolusDuration = 0
+ extendedBolusAmount = 0.0
+ aapsLogger.debug(LTag.PUMP, "syncExtendedBolusFromPump: not running, state cleared")
+ }
+ }
+
// Profile
var activeProfile = 0
var pumpProfiles: Array>? = null
diff --git a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/database/DiaconnHistoryRecordDao.kt b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/database/DiaconnHistoryRecordDao.kt
index 74a01f033ae..cd9d593a37a 100644
--- a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/database/DiaconnHistoryRecordDao.kt
+++ b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/database/DiaconnHistoryRecordDao.kt
@@ -15,6 +15,6 @@ abstract class DiaconnHistoryRecordDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract fun createOrUpdate(diaconnHistoryRecord: DiaconnHistoryRecord)
- @Query( "SELECT * from $TABLE_DIACONN_HISTORY WHERE pumpUid = :pumpUid ORDER BY timestamp DESC LIMIT 1" )
+ @Query( "SELECT * from $TABLE_DIACONN_HISTORY WHERE pumpUid = :pumpUid ORDER BY wrappingCount DESC, lognum DESC LIMIT 1" )
abstract fun getLastRecord(pumpUid: String): DiaconnHistoryRecord?
}
diff --git a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigAPSMainInfoInquireResponsePacket.kt b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigAPSMainInfoInquireResponsePacket.kt
index cd630ab0b3b..e8f720a14e5 100644
--- a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigAPSMainInfoInquireResponsePacket.kt
+++ b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigAPSMainInfoInquireResponsePacket.kt
@@ -217,6 +217,7 @@ class BigAPSMainInfoInquireResponsePacket(
//incarnation no 처리
diaconnG8Pump.isPumpVersionGe2_63 = PumpLogUtil.isPumpVersionGe(preferences.get(DiaconnStringNonKey.PumpVersion), 2, 63)
diaconnG8Pump.isPumpVersionGe3_53 = PumpLogUtil.isPumpVersionGe(preferences.get(DiaconnStringNonKey.PumpVersion), 3, 53)
+ diaconnG8Pump.isPumpVersionGe3_58 = PumpLogUtil.isPumpVersionGe(preferences.get(DiaconnStringNonKey.PumpVersion), 3, 58)
aapsLogger.debug(LTag.PUMPCOMM, "result > " + diaconnG8Pump.result)
aapsLogger.debug(LTag.PUMPCOMM, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin)
diff --git a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigMainInfoInquireResponsePacket.kt b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigMainInfoInquireResponsePacket.kt
index ced2d1b2dd4..c015ba59176 100644
--- a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigMainInfoInquireResponsePacket.kt
+++ b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/packet/BigMainInfoInquireResponsePacket.kt
@@ -213,6 +213,7 @@ class BigMainInfoInquireResponsePacket(
//incarnation no 처리
diaconnG8Pump.isPumpVersionGe2_63 = PumpLogUtil.isPumpVersionGe(preferences.get(DiaconnStringNonKey.PumpVersion), 2, 63)
diaconnG8Pump.isPumpVersionGe3_53 = PumpLogUtil.isPumpVersionGe(preferences.get(DiaconnStringNonKey.PumpVersion), 3, 53)
+ diaconnG8Pump.isPumpVersionGe3_58 = PumpLogUtil.isPumpVersionGe(preferences.get(DiaconnStringNonKey.PumpVersion), 3, 58)
aapsLogger.debug(LTag.PUMPCOMM, "result > " + diaconnG8Pump.result)
aapsLogger.debug(LTag.PUMPCOMM, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin)
diff --git a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/service/DiaconnG8Service.kt b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/service/DiaconnG8Service.kt
index 734b1f28115..51598fdd0f6 100644
--- a/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/service/DiaconnG8Service.kt
+++ b/pump/diaconn/src/main/kotlin/app/aaps/pump/diaconn/service/DiaconnG8Service.kt
@@ -7,6 +7,7 @@ import android.os.IBinder
import android.os.SystemClock
import app.aaps.core.data.configuration.Constants
import app.aaps.core.data.pump.defs.PumpType
+import app.aaps.core.data.time.T
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.interfaces.notifications.Notification
@@ -253,10 +254,10 @@ class DiaconnG8Service : DaggerService() {
}
}
loadHistory()
- val eb = pumpSync.expectedPumpState().extendedBolus
- diaconnG8Pump.fromExtendedBolus(eb)
- val tbr = pumpSync.expectedPumpState().temporaryBasal
- diaconnG8Pump.fromTemporaryBasal(tbr)
+ // Sync TBR/EB state directly from pump response fields instead of pumpSync.expectedPumpState()
+ // This prevents timing issues where pumpSync DB may not be updated yet
+ diaconnG8Pump.syncTempBasalFromPump()
+ diaconnG8Pump.syncExtendedBolusFromPump()
rxBus.send(EventDiaconnG8NewStatus())
rxBus.send(EventInitializationChanged())
if (diaconnG8Pump.dailyTotalUnits > diaconnG8Pump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
@@ -342,7 +343,7 @@ class DiaconnG8Service : DaggerService() {
val endLogNo: Int = startLogNo + min(end - startLogNo, pumpLogPageSize)
aapsLogger.debug(LTag.PUMPCOMM, "pumplog request : $startLogNo ~ $endLogNo")
val msg = BigLogInquirePacket(injector, startLogNo, endLogNo, 100)
- sendMessage(msg, 500)
+ sendMessage(msg, 2000)
}
result.success(true)
diaconnG8Pump.lastConnection = System.currentTimeMillis()
@@ -597,10 +598,22 @@ class DiaconnG8Service : DaggerService() {
// pump tempbasal status inquire
}
+ // Set TBR state directly after successful setting (don't rely solely on loadHistory/pumpSync)
+ if (result.success()) {
+ val durationInMinutes = (durationInHours * 60).toLong()
+ diaconnG8Pump.tempBasalStart = dateUtil.now()
+ diaconnG8Pump.tempBasalDuration = T.mins(durationInMinutes).msecs()
+ diaconnG8Pump.tempBasalAbsoluteRate = absoluteRate
+ aapsLogger.debug(LTag.PUMPCOMM, "TBR set directly: start=${diaconnG8Pump.tempBasalStart}, duration=${durationInMinutes}min, rate=${absoluteRate}U/h")
+ }
+
sendMessage(TempBasalInquirePacket(injector))
- loadHistory()
- val tbr = pumpSync.expectedPumpState().temporaryBasal
- diaconnG8Pump.fromTemporaryBasal(tbr)
+ // do not call loadHistory() directly, reconnection may be needed
+ commandQueue.loadEvents(object : Callback() {
+ override fun run() {
+ rxBus.send(EventDiaconnG8NewStatus())
+ }
+ })
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return result.success()
}
@@ -640,10 +653,21 @@ class DiaconnG8Service : DaggerService() {
// otp process
if (!processConfirm(msgTBR.msgType)) return false
}
+ // Set TBR state directly after successful setting (don't rely solely on loadHistory/pumpSync)
+ if (result.success()) {
+ diaconnG8Pump.tempBasalStart = dateUtil.now()
+ diaconnG8Pump.tempBasalDuration = T.mins(durationInMinutes.toLong()).msecs()
+ diaconnG8Pump.tempBasalAbsoluteRate = absoluteRate
+ aapsLogger.debug(LTag.PUMPCOMM, "TBR set directly: start=${diaconnG8Pump.tempBasalStart}, duration=${durationInMinutes}min, rate=${absoluteRate}U/h")
+ }
+
sendMessage(TempBasalInquirePacket(injector))
- loadHistory()
- val tbr = pumpSync.expectedPumpState().temporaryBasal
- diaconnG8Pump.fromTemporaryBasal(tbr)
+ // do not call loadHistory() directly, reconnection may be needed
+ commandQueue.loadEvents(object : Callback() {
+ override fun run() {
+ rxBus.send(EventDiaconnG8NewStatus())
+ }
+ })
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return result.success()
}
@@ -665,11 +689,20 @@ class DiaconnG8Service : DaggerService() {
// otp process
if (!processConfirm(msgPacket.msgType)) return false
SystemClock.sleep(500)
+
+ // Clear TBR state directly after successful stop
+ diaconnG8Pump.tempBasalStart = 0L
+ diaconnG8Pump.tempBasalDuration = 0L
+ diaconnG8Pump.tempBasalAbsoluteRate = 0.0
+ aapsLogger.debug(LTag.PUMPCOMM, "TBR stopped and state cleared directly")
}
- loadHistory()
- val tbr = pumpSync.expectedPumpState().temporaryBasal
- diaconnG8Pump.fromTemporaryBasal(tbr)
+ // do not call loadHistory() directly, reconnection may be needed
+ commandQueue.loadEvents(object : Callback() {
+ override fun run() {
+ rxBus.send(EventDiaconnG8NewStatus())
+ }
+ })
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
@@ -683,10 +716,21 @@ class DiaconnG8Service : DaggerService() {
sendMessage(msgExtended)
// otp process
if (!processConfirm(msgExtended.msgType)) return false
- //diaconnG8Pump.isExtendedInProgress = true
- loadHistory()
- val eb = pumpSync.expectedPumpState().extendedBolus
- diaconnG8Pump.fromExtendedBolus(eb)
+
+ // Set EB state directly after successful setting (don't rely solely on loadHistory/pumpSync)
+ if (msgExtended.success()) {
+ diaconnG8Pump.extendedBolusStart = dateUtil.now()
+ diaconnG8Pump.extendedBolusDuration = T.mins(durationInMinutes.toLong()).msecs()
+ diaconnG8Pump.extendedBolusAmount = insulin
+ aapsLogger.debug(LTag.PUMPCOMM, "EB set directly: start=${diaconnG8Pump.extendedBolusStart}, duration=${durationInMinutes}min, amount=${insulin}U")
+ }
+
+ // do not call loadHistory() directly, reconnection may be needed
+ commandQueue.loadEvents(object : Callback() {
+ override fun run() {
+ rxBus.send(EventDiaconnG8NewStatus())
+ }
+ })
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return msgExtended.success()
}
@@ -699,9 +743,19 @@ class DiaconnG8Service : DaggerService() {
sendMessage(msgStop)
// otp process
if (!processConfirm(msgStop.msgType)) return false
- loadHistory() // pump log sync( db update)
- val eb = pumpSync.expectedPumpState().extendedBolus
- diaconnG8Pump.fromExtendedBolus(eb)
+
+ // Clear EB state directly after successful stop
+ diaconnG8Pump.extendedBolusStart = 0L
+ diaconnG8Pump.extendedBolusDuration = 0L
+ diaconnG8Pump.extendedBolusAmount = 0.0
+ aapsLogger.debug(LTag.PUMPCOMM, "EB stopped and state cleared directly")
+
+ // do not call loadHistory() directly, reconnection may be needed
+ commandQueue.loadEvents(object : Callback() {
+ override fun run() {
+ rxBus.send(EventDiaconnG8NewStatus())
+ }
+ })
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return msgStop.success()
}
@@ -780,19 +834,18 @@ class DiaconnG8Service : DaggerService() {
private fun processConfirm(msgType: Byte): Boolean {
// pump confirm
var loopCnt = 0
- // waiting 2 seconds for otp
- while (loopCnt < 20) {
- if (diaconnG8Pump.otpNumber == 0) {
- SystemClock.sleep(100)
- aapsLogger.error(LTag.PUMPCOMM, "OTP waiting 100ms $loopCnt / 20")
- }
+ // waiting 2 seconds for otp (max 30 loops * 100ms = 2000ms)
+ while (loopCnt < 30 && diaconnG8Pump.otpNumber == 0) {
+ SystemClock.sleep(100)
+ aapsLogger.debug(LTag.PUMPCOMM, "OTP waiting 100ms $loopCnt / 30")
loopCnt++
}
- // after 2 second
+ // check if otp received
if (diaconnG8Pump.otpNumber == 0) {
- aapsLogger.error(LTag.PUMPCOMM, "otp is not received yet")
+ aapsLogger.error(LTag.PUMPCOMM, "otp is not received yet after ${loopCnt * 100}ms")
return false
}
+ aapsLogger.debug(LTag.PUMPCOMM, "OTP received: ${diaconnG8Pump.otpNumber} after ${loopCnt * 100}ms")
diaconnG8Pump.bolusConfirmMessage = msgType
sendMessage(AppConfirmSettingPacket(injector, msgType, diaconnG8Pump.otpNumber), 2000)
diaconnG8Pump.otpNumber = 0
diff --git a/pump/diaconn/src/main/res/values-sk-rSK/strings.xml b/pump/diaconn/src/main/res/values-sk-rSK/strings.xml
index 4901b4962fe..85b4bdf03b8 100644
--- a/pump/diaconn/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/diaconn/src/main/res/values-sk-rSK/strings.xml
@@ -31,7 +31,7 @@
Chyba príkazuChyba rýchlostiPrekročený limit inzulínu
- Požadované: %1$.2fJI Podané: %2$.2fJI Chyba: %3$s
+ Požadované: %1$.2fU Podané: %2$.2fU Chyba: %3$sRýchlosť bolusuVybraná pumpaStav Bluetooth
@@ -73,9 +73,9 @@
Prebieha synchronizácia logovNedostatok inzulínuSlabá batéria
- Plnenie ihly :%1$.2fJI
- Plnenie kanyly:%1$.2fJI
- Plnenie hadičky :%1$.2fJI
+ Plnenie ihly :%1$.2fU
+ Plnenie kanyly:%1$.2fU
+ Plnenie hadičky :%1$.2fUResetovať po obnovení na továrenské nastaveniaResetovať po núdzovom vypnutíResetovať po výmene batérie
diff --git a/pump/diaconn/src/main/res/values-vi-rVN/strings.xml b/pump/diaconn/src/main/res/values-vi-rVN/strings.xml
index 825141f15d8..f5255611a81 100644
--- a/pump/diaconn/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/diaconn/src/main/res/values-vi-rVN/strings.xml
@@ -11,19 +11,19 @@
Nạp lại InsulinTạm dừngThông tin ghép cặp không hợp lệ. Yêu cầu ghép đôi mới
- Đang cập nhật cài đặt pump
- Đang cập nhật thời gian pump
+ Đang cập nhật cài đặt Bơm
+ Đang cập nhật thời gian BơmChênh lệch thời gian lớn:\nThời gian trên bơm lệch hơn 1,5 giờ.\nVui lòng chỉnh thời gian trên bơm thủ công và đảm bảo việc đọc lịch sử từ bơm không gây ra hành vi bất ngờ.\nNếu có thể, hãy xóa lịch sử trên bơm trước khi thay đổi thời gian hoặc tắt chế độ vòng lặp kín trong một khoảng DIA kể từ mục lịch sử sai cuối cùng, nhưng tối thiểu một DIA kể từ bây giờ.Chênh lệch múi giờ lớnSắp đạt giới hạn insulin hằng ngàyĐang tiêm bolusĐang chờ kết thúc liều bolus ước tínhĐang cập nhật trạng thái liều Bolus
- Đang dừng liều basal tạm thời
+ Đang dừng liều nền tạm thờiĐang cài đặt liều nền tạm thời
- Đang cập nhật liều bolus mở rộng
- Đang dừng liều bolus mở rộng
- Đang cập nhật tốc độ liều Basal
+ Đang cập nhật liều bolus kéo dài
+ Đang dừng liều bolus kéo dài
+ Đang cập nhật tốc độ liều nềnTích hợp cho bơm Diaconn G8Diaconn G8Diaconn G8
@@ -33,16 +33,16 @@
Vi phạm giới hạn insulinYêu cầu: %1$.2fU Đã tiêm: %2$.2fU Mã lỗi: %3$sTốc độ liều Bolus
- Pump đã chọn
+ Bơm đã chọnTrạng thái BluetoothBolus StepBasal StepPhần mềmTÙY CHỌN NGƯỜI DÙNG
- Hãy kết nối pump với điện thoại của bạn!
+ Hãy kết nối Bơm với điện thoại của bạn!"Đang xử lý sự kiện "
- Liều basal tạm thời
- Cài đặt pump Diaconn
+ Liều nền tạm thời
+ Cài đặt Bơm DiaconnÂm thanhâm thanhrung
@@ -99,8 +99,8 @@
REPLACE NEEDLEREPLACE SYRINGEKhông thể tiêm (%s)
- giải phóng liều basal (%s)
- tạm dừng liều basal (%s)
+ giải phóng liều nền (%s)
+ tạm dừng liều nền (%s)Dual Nomarl thành côngBắt đầu Dual SquareDual Square thành công
@@ -114,23 +114,23 @@
Không thể đặt thành lỗi kỹ thuật giao thức.Đang ở chế độ bữa ăn, không thể tiêm.Bị hủy bởi máy bơm
- Đang xử lý tác vụ khác, tạm giới hạn cài đặt.
+ Đang thực hiện thao tác khác, các cài đặt ứng dụng bị hạn chế.Đang tiêm bolus khác, không thể tiêm thêm.
- Yêu cầu tiếp tục tiêm liều basal
+ Yêu cầu tiếp tục tiêm liều nềnĐã hủy do bơm không phản hồi.Không thể tiêm do pin yếu.Không thể tiêm do insulin không đủ.Không thể tiêm, vượt quá giới hạn.Không thể tiêm vì đã vượt quá tổng lượng tiêm cho hôm nay.
- Sau khi thiết lập basal hoàn tất, có thể thực hiện tiêm basal.
+ Sau khi thiết lập liều nền hoàn tất, có thể thực hiện tiêm liều nền.Ghi lại thay đổi TubeThêm sự kiện ‘Thay Tube’ vào Ghi chú khi phát hiện trong lịch sử
- Bắt đầu basal tạm thời
+ Bắt đầu liều nền tạm thờiKhi LGS đang chạy, việc tiêm bị hạn chếTrạng thái LGS đang BẬT, lệnh BẬT bị từ chối.Trạng thái LGS đang TẮT, lệnh TẮT bị từ chối.
- Không thể bắt đầu basal tạm thời này khi một basal tạm thời khác đang chạy
- Dừng basal tạm thời bị từ chối khi basal tạm thời không hoạt động
+ Không thể bắt đầu liều nền tạm thời này khi một basal tạm thời khác đang chạy
+ Dừng liều nền tạm thời bị từ chối khi liều nền tạm thời không hoạt độngGửi nhật ký bơm lên Diaconn Cloud.Đông bộ Diaconn Cloud
diff --git a/pump/eopatch/src/main/res/values-es-rES/strings.xml b/pump/eopatch/src/main/res/values-es-rES/strings.xml
index 828d2edda4a..5419003868a 100644
--- a/pump/eopatch/src/main/res/values-es-rES/strings.xml
+++ b/pump/eopatch/src/main/res/values-es-rES/strings.xml
@@ -54,8 +54,8 @@
Prepárate para colocar el parche3/6Retire la cinta adhesiva y luego pulse \'Siguiente\'.
- [Caution1] Si la aguja es visible, pulse \'Descartar\'.
- [Caution2] Si el parche está húmedo, sucio, o su cinta adhesiva está doblada, pulse \'Descartar\'.
+ [Precaución1] Si la aguja es visible, pulse \'Descartar\'.
+ [Precaución2] Si el parche está húmedo, sucio, o su cinta adhesiva está doblada, pulse \'Descartar\'.Coloque el parche en su cuerpo4/6Limpie y seque el sitio de la aplicación, luego de colocar el parche en la piel.
@@ -64,7 +64,7 @@
Comprobaciones de seguridad…5/6Tardará unos 30 segundos
- [Caution] Para un uso seguro, no retire la palanca que ejecuta la aguja hasta que se complete la verificación de seguridad!
+ [Precaución] Para un uso seguro, no retire la palanca de accionamiento de la aguja hasta que haya finalizado la comprobación de seguridadInserción de la aguja6/6Gira la palanca de accionamiento de la aguja más de 100° para insertar la aguja y, a continuación, gírala completamente para extraerla
@@ -104,14 +104,14 @@
CambiandoProcesandoReintentar
- [Caution] No retires el protector de la aguja ni el soporte adhesivo hasta recibir instrucciones adicionales
+ [Precaución] No retires el protector de la aguja ni el soporte adhesivo hasta recibir instrucciones adicionales¿Estás seguro de descartar el parche actual?Error de inserción de la agujaComprueba que la dirección del orificio que queda tras girar la palanca es recta y, a continuación, pulsa en \"Reintentar\".Pulsa \'Descartar\' para desactivar el parcheTiempo de suspensión basalReanudar la administración de insulina
- Fin de la suspensión de insulina.\nPulsa \'Confirmar\' para reanudar la administración de insulina.\n\n[Caution]\nLa administración de insulina no se reanudará hasta que pulses \'Confirmar\'.\nSi no pulsas en \'Confirmar\', podrías desarrollar una hiperglucemia
+ Fin de la suspensión de insulina.\nPulsa \'Confirmar\' para reanudar la administración de insulina.\n\n[Precaución]\nLa administración de insulina no se reanudará hasta que pulses \'Confirmar\'.\nSi no pulsas en \'Confirmar\', podrías desarrollar una hiperglucemiaSe suspende la administración de insulinaSe reanuda la administración de insulinaFinalizar
diff --git a/pump/eopatch/src/main/res/values-sk-rSK/strings.xml b/pump/eopatch/src/main/res/values-sk-rSK/strings.xml
index 8207c6bd41d..f8a14b808e9 100644
--- a/pump/eopatch/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/eopatch/src/main/res/values-sk-rSK/strings.xml
@@ -15,7 +15,7 @@
Základná hodnota bazáluDočasná bazálna dávkaCelkovo podané
- Bazál profilu je menší než 0.05 JI/h. EOPatch má minimálnu dávku 0.05 JI. Prosím skúste to znovu po nastavení v profile na viac ako minimálnu dávku.
+ Bazál profilu je menší než 0.05 U/h. EOPatch má minimálnu dávku 0.05 U. Prosím skúste to znovu po nastavení v profile na viac ako minimálnu dávku.Žiadny vybraný profil. Prosím vyberte si profil a skúste to znovu.deň+
@@ -83,10 +83,10 @@
Pripojené k Patch.Zrušiť párovaniední
- JI
- Po pozastavení, budú práve podávaný bolus & dočasný bazál zrušené. \n\nHodnota: %1$s JI/h\nZostávajúci čas : %2$s\n& Zostávajúci inzulín: %3$.2f JI
- Po pozastavení, bude práve podávaný bolus zrušený. \n\nZostávajúci inzulín: %1$.2f JI
- Po pozastavení, bude práve podávaný dočasný bazál zrušený. \n\nHodnota: %1$s JI/h\nZostávajúci čas : %2$s
+ U
+ Po pozastavení, budú práve podávaný bolus & dočasný bazál zrušené. \n\nHodnota: %1$s U/h\nZostávajúci čas : %2$s\n& Zostávajúci inzulín: %3$.2f U
+ Po pozastavení, bude práve podávaný bolus zrušený. \n\nZostávajúci inzulín: %1$.2f U
+ Po pozastavení, bude práve podávaný dočasný bazál zrušený. \n\nHodnota: %1$s U/h\nZostávajúci čas : %2$sPodávanie inzulínu je pozastavené.Zahodiť/Vymeniť pumpuAktivovať pumpu
diff --git a/pump/eopatch/src/main/res/values-vi-rVN/strings.xml b/pump/eopatch/src/main/res/values-vi-rVN/strings.xml
index 95b4714b06d..c197d1eb408 100644
--- a/pump/eopatch/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/eopatch/src/main/res/values-vi-rVN/strings.xml
@@ -12,11 +12,11 @@
Ngày & giờ đánh thứcThời gian hết hạnTrạng thái
- Tỷ lệ basal cơ bản
- Tỷ lệ Basal tạm thời
+ Tỷ lệ liều nền cơ bản
+ Tỷ lệ liều nền tạm thờiTổng lượng đã tiêm
- Basal trong cấu hình nhỏ hơn 0,05 U/giờ. EOPatch có đơn vị tiêm tối thiểu là 0,05 U. Vui lòng thử lại sau khi đặt cấu hình lớn hơn đơn vị tiêm tối thiểu.
- Chưa chọn cấu hình. Vui lòng chọn cấu hình và thử lại.
+ Liều nền trong Hồ sơ nhỏ hơn 0,05 U/giờ. EOPatch có đơn vị tiêm tối thiểu là 0.05 U. Vui lòng thử lại sau khi đặt cấu hình lớn hơn đơn vị tiêm tối thiểu.
+ Chưa chọn Hồ sơ. Vui lòng chọn Hồ sơ và thử lại.ngày+-
@@ -28,8 +28,8 @@
Đã hoàn tất việc bỏ Patch.Patch đã được hủy kích hoạt.\nHãy bỏ Patch đi.\nTháo Patch ra khỏi cơ thể.Hiện tại đang tiêm bolus. Bạn có thực sự muốn hủy việc tiêm insulin và bỏ Patch không?
- Hiện tại đang tiêm insulin nền tạm thời. Bạn có thực sự muốn hủy việc tiêm insulin và bỏ Patch không?
- Hiện tại đang tiêm bolus và insulin nền tạm thời. Bạn có thực sự muốn hủy việc tiêm insulin và bỏ Patch không?
+ Hiện tại đang tiêm liều nền tạm thời. Bạn có thực sự muốn hủy việc tiêm insulin và bỏ Patch không?
+ Hiện tại đang tiêm liều bolus và liều nền tạm thời. Bạn có thực sự muốn hủy việc tiêm insulin và bỏ Patch không?Bạn có chắc chắn muốn bỏ Patch không?Insulin còn lạiThời gian còn lại
@@ -84,9 +84,9 @@
Hủy ghép nốingày U
- Khi tạm dừng, Bolus và Temp basal đang truyền sẽ bị hủy.\n\nTốc độ: %1$s U/giờ\nThời gian còn lại: %2$s\n&Insulin còn lại: %3$.2f U
+ Khi tạm dừng, liều Bolus và liều nền tạm thời đang truyền sẽ bị hủy.\n\nTốc độ: %1$s U/giờ\nThời gian còn lại: %2$s\n&Insulin còn lại: %3$.2f UKhi tạm dừng, Bolus đang truyền sẽ bị hủy.\n\nInsulin còn lại: %1$.2f U
- Khi tạm dừng, Temp Basal đang truyền sẽ bị hủy.\n\nTốc độ: %1$s U/giờ\nThời gian còn lại: %2$s
+ Khi tạm dừng, liều nền tạm thời đang truyền sẽ bị hủy.\n\nTốc độ: %1$s U/giờ\nThời gian còn lại: %2$sViệc truyền insulin sẽ bị tạm dừng.Hủy bỏ/Thay PatchKích hoạt Patch
@@ -109,7 +109,7 @@
Lỗi khi đưa kim vào.Kiểm tra xem hướng của lỗ sau khi xoay cần thao tác có thẳng không, sau đó nhấn ‘Thử lại’.Nhấn ‘Hủy bỏ’ để hủy kích hoạt Patch.
- Thời gian tạm dừng Basal
+ Thời gian tạm dừng liều nềnPhục hồi liều insulinKết thúc tạm ngừng tiêm insulin.\nNhấn \'Xác nhận\' để tiếp tục tiêm insulin.\n\n[Cảnh báo]\nViệc tiêm insulin sẽ không tiếp tục cho đến khi bạn nhấn \'Xác nhận\'.\nNếu bạn không nhấn \'Xác nhận\', bạn có thể bị tăng đường huyết.Việc tiêm insulin đã bị tạm dừng.
diff --git a/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGet.kt b/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGet.kt
index 9fefab6d786..174c3500b13 100644
--- a/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGet.kt
+++ b/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGet.kt
@@ -174,7 +174,14 @@ class CmdDevicesOldGet(
}
}
- fun isSupport(): Boolean = firmwareVersion >= EquilConst.EQUIL_SUPPORT_LEVEL
+ fun isSupport(serialNumber: String): Boolean {
+ val firstChar = serialNumber.firstOrNull()?.uppercaseChar()
+ val needsVersionCheck = setOf('0', '1', '3', 'A', 'D')
+ return when (firstChar) {
+ in needsVersionCheck -> firmwareVersion >= EquilConst.EQUIL_SUPPORT_LEVEL
+ else -> true
+ }
+ }
override fun getEventType(): EquilHistoryRecord.EventType? = null
}
diff --git a/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdResistanceGet.kt b/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdResistanceGet.kt
index 7ceae8dc33a..e9c5283963c 100644
--- a/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdResistanceGet.kt
+++ b/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdResistanceGet.kt
@@ -1,6 +1,7 @@
package app.aaps.pump.equil.manager.command
import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.keys.interfaces.Preferences
import app.aaps.pump.equil.database.EquilHistoryRecord
import app.aaps.pump.equil.manager.AESUtil
@@ -38,6 +39,10 @@ class CmdResistanceGet(
val value = Utils.bytesToInt(data[7], data[6])
cmdSuccess = true
enacted = value >= 500
+ aapsLogger.debug(
+ LTag.PUMPCOMM,
+ "CmdResistanceGet: resistance=$value, threshold=500, enacted=$enacted (pin ${if (enacted) "REACHED" else "NOT reached"} piston)"
+ )
synchronized(this) {
(this as Object).notify()
}
diff --git a/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdStepSet.kt b/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdStepSet.kt
index 71de63b68e2..1c5bd6be912 100644
--- a/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdStepSet.kt
+++ b/pump/equil/src/main/kotlin/app/aaps/pump/equil/manager/command/CmdStepSet.kt
@@ -1,6 +1,7 @@
package app.aaps.pump.equil.manager.command
import app.aaps.core.interfaces.logging.AAPSLogger
+import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.keys.interfaces.Preferences
import app.aaps.pump.equil.database.EquilHistoryRecord
import app.aaps.pump.equil.manager.AESUtil
@@ -16,6 +17,7 @@ class CmdStepSet(
) : BaseSetting(System.currentTimeMillis(), aapsLogger, preferences, equilManager) {
override fun getFirstData(): ByteArray {
+ aapsLogger.debug(LTag.PUMPCOMM, "CmdStepSet: Sending pin movement command, step=$step, sendConfig=$sendConfig")
val indexByte = Utils.intToBytes(pumpReqIndex)
val data2 = byteArrayOf(0x01, 0x07)
val data3 = Utils.intToBytes(step)
@@ -36,6 +38,7 @@ class CmdStepSet(
override fun decodeConfirmData(data: ByteArray) {
// byte[] byteData = Crc.hexStringToBytes(data);
// int status = byteData[6] & 0xff;
+ aapsLogger.debug(LTag.PUMPCOMM, "CmdStepSet: Pin movement command completed successfully, step=$step")
synchronized(this) {
cmdSuccess = true
(this as Object).notify()
diff --git a/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairFillFragment.kt b/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairFillFragment.kt
index 7246cbc178d..c01e226bbbf 100644
--- a/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairFillFragment.kt
+++ b/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairFillFragment.kt
@@ -52,6 +52,7 @@ class EquilPairFillFragment : EquilPairFragmentBase() {
}
buttonFill?.setOnClickListener {
context?.let {
+ aapsLogger.info(LTag.PUMPCOMM, "EquilFill: User initiated auto-fill, starting pin movement from step=$intStep")
auto = true
showAutoDlg()
setStep()
@@ -109,14 +110,17 @@ class EquilPairFillFragment : EquilPairFragmentBase() {
}
private fun setStep() {
+ aapsLogger.debug(LTag.PUMPCOMM, "EquilFill: setStep() called, currentStep=$intStep, stepIncrement=${EquilConst.EQUIL_STEP_FILL}, maxStep=${EquilConst.EQUIL_STEP_MAX}")
commandQueue.customCommand(CmdStepSet(false, EquilConst.EQUIL_STEP_FILL, aapsLogger, preferences, equilManager), object : Callback() {
override fun run() {
if (activity == null) return
- aapsLogger.debug(LTag.PUMPCOMM, "result====" + result.success)
+ aapsLogger.debug(LTag.PUMPCOMM, "EquilFill: CmdStepSet result.success=${result.success}, intStep=$intStep")
if (result.success) {
intStep += EquilConst.EQUIL_STEP_FILL
+ aapsLogger.debug(LTag.PUMPCOMM, "EquilFill: Pin moved, newTotalStep=$intStep (${intStep / EquilConst.EQUIL_STEP_FILL} iterations)")
readStatus()
} else {
+ aapsLogger.warn(LTag.PUMPCOMM, "EquilFill: CmdStepSet FAILED at step $intStep")
if (auto) dismissAutoDlg()
else dismissLoading()
}
@@ -125,17 +129,20 @@ class EquilPairFillFragment : EquilPairFragmentBase() {
}
private fun readStatus() {
+ aapsLogger.debug(LTag.PUMPCOMM, "EquilFill: readStatus() checking resistance at step $intStep")
commandQueue.customCommand(
CmdResistanceGet(aapsLogger, preferences, equilManager),
object : Callback() {
override fun run() {
if (activity == null) return
- aapsLogger.debug(LTag.PUMPCOMM, "readStatus result====" + result.success + "===" + result.enacted + "====" + auto)
- // result.enacted=true
+ aapsLogger.debug(LTag.PUMPCOMM, "EquilFill: readStatus result.success=${result.success}, result.enacted=${result.enacted}, intStep=$intStep, auto=$auto")
+ // result.enacted=true means pin reached piston (resistance >= 500)
if (result.success) {
if (!result.enacted) {
+ aapsLogger.debug(LTag.PUMPCOMM, "EquilFill: Pin NOT at piston yet, continuing...")
if (auto) {
if (intStep > EquilConst.EQUIL_STEP_MAX) {
+ aapsLogger.error(LTag.PUMPCOMM, "EquilFill: MAXIMUM STEP EXCEEDED! intStep=$intStep > maxStep=${EquilConst.EQUIL_STEP_MAX}")
ToastUtils.infoToast(context, rh.gs(R.string.equil_replace_reservoir))
dismissLoading()
activity?.finish()
@@ -143,9 +150,11 @@ class EquilPairFillFragment : EquilPairFragmentBase() {
}
setStep()
} else {
+ aapsLogger.debug(LTag.PUMPCOMM, "EquilFill: Manual mode, dismissing loading")
dismissLoading()
}
} else {
+ aapsLogger.info(LTag.PUMPCOMM, "EquilFill: Pin REACHED piston at step $intStep (${intStep / EquilConst.EQUIL_STEP_FILL} iterations), stopping fill")
if (auto) {
runOnUiThread {
buttonFill?.visibility = View.GONE
@@ -155,6 +164,7 @@ class EquilPairFillFragment : EquilPairFragmentBase() {
} else dismissLoading()
}
} else {
+ aapsLogger.warn(LTag.PUMPCOMM, "EquilFill: CmdResistanceGet FAILED at step $intStep")
if (auto) dismissAutoDlg()
else dismissLoading()
}
diff --git a/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairSerialNumberFragment.kt b/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairSerialNumberFragment.kt
index 27abafeeea0..2d2760de96b 100644
--- a/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairSerialNumberFragment.kt
+++ b/pump/equil/src/main/kotlin/app/aaps/pump/equil/ui/pair/EquilPairSerialNumberFragment.kt
@@ -275,7 +275,7 @@ class EquilPairSerialNumberFragment : EquilPairFragmentBase() {
if (activity == null) return
aapsLogger.debug(LTag.PUMPCOMM, "result====" + result.success + "===" + result.enacted)
if (result.success) {
- if (cmdDevicesOldGet.isSupport()) {
+ if (cmdDevicesOldGet.isSupport(serialNumber)) {
SystemClock.sleep(EquilConst.EQUIL_BLE_NEXT_CMD)
pair(scanResult)
} else {
diff --git a/pump/equil/src/main/res/values-nl-rNL/strings.xml b/pump/equil/src/main/res/values-nl-rNL/strings.xml
index 5b47083b1e9..93bfe85326f 100644
--- a/pump/equil/src/main/res/values-nl-rNL/strings.xml
+++ b/pump/equil/src/main/res/values-nl-rNL/strings.xml
@@ -9,6 +9,7 @@
Laatste verbindingVervang reservoirDe zuiger automatisch naar de bodem van het reservoir aan het verplaatsen. Deze zal automatisch stoppen in de eindstand. Klik op \'Stop\' om te onderbreken indien nodig.
+ BeëindigenVolgendeDeze operatie zal de toediening van de insuline stopzetten en de zuiger van de pomp terugplaatsen naar de bodem van het reservoir!Geschiedenis
@@ -148,6 +149,7 @@
Instellen koppelwachtwoordNa het installeren van de pomp op het basisplaat, selecteer of de lucht uit de binnenste naald moet worden verwijderd.Apparaat ontkoppelen
+ Apparaat niet gekoppeldMonteer de pomp, het gevulde reservoir en de opgeladen batterijVoer nieuw pomp ID inPrime het reservoir totdat er een druppel insuline aan de punt van de naald zichtbaar is
@@ -159,4 +161,5 @@
Pomp bijgewerktHet reservoir is leeg. Vervang het reservoirMoet 6 tekens bevatten uit ABCDEF0123456789
+ Ontkoppel opdracht is mislukt. Pomp wordt toch verwijderd. Wachtwoord ingesteld tijdens het koppelen wordt niet van de pomp verwijderd.
diff --git a/pump/equil/src/main/res/values-pl-rPL/strings.xml b/pump/equil/src/main/res/values-pl-rPL/strings.xml
index 62379fe1e15..d223b18f7ec 100644
--- a/pump/equil/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/equil/src/main/res/values-pl-rPL/strings.xml
@@ -9,6 +9,7 @@
Ostatnie połączenieZmień zbiornikAutomatycznie przesuwam tłok na dno zbiornika. Zatrzyma się sam po dotarciu na dół. Kliknij \'Zatrzymaj\', aby w razie potrzeby przerwać.
+ ZakończDalejTa operacja zatrzyma podawanie insuliny i spowoduje cofnięcie tłoka pompy do dołu!Historia
@@ -154,6 +155,7 @@
Ustaw hasło parowaniaPo zainstalowaniu pompy na płytce bazowej wybierz, czy usunąć powietrze z igły, która ma być wkłuta.Rozłącz urządzenie
+ Urządzenie odparowaneZmontuj pompę, wypełniony zbiornik i naładowaną baterięWprowadź nowy identyfikator pompyProszę napełnij zbiornik z insuliną aż do pojawienia się kropli insuliny na końcu igły
@@ -165,4 +167,5 @@
Pompa zaktualizowanaZbiornik jest pusty. Proszę wymienić zbiornikMusi składać się z 6 znaków spośród: ABCDEF0123456789
+ Nie udało się odparować. Pompa i tak zostanie usunięta. Hasło ustawione podczas parowania nie jest usuwane z pompy.
diff --git a/pump/equil/src/main/res/values-sk-rSK/strings.xml b/pump/equil/src/main/res/values-sk-rSK/strings.xml
index d275d111da3..68d1ed32096 100644
--- a/pump/equil/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/equil/src/main/res/values-sk-rSK/strings.xml
@@ -29,8 +29,8 @@
Iba vibrovaťIba zvukyVibrácie a zvuky
- %1$s JI
- %1$s JI/h
+ %1$s U
+ %1$s U/hTáto operácia zastaví vydávanie inzulínu, a zasunie piest pumpy do východzej polohy! Taktiež zruší spárovanie!Žiadne zariadenieSpárovať Equil Patch pumpu
@@ -39,9 +39,9 @@
Vyberte pumpu zo základne.Naozaj sa chcete vzdať kontroly nad %1$s?Číslo zariadenia
- Bazálna dávka %1$s JI/h
- Dočasný bazál %1$s JI/h
- Bolus %1$s JI
+ Bazálna dávka %1$s U/h
+ Dočasný bazál %1$s U/h
+ Bolus %1$s UDoba trvania TBR musí byť väčšia ako nula, a musí byť násobkom %1$s minút.Nedostatok inzulínu v zásobníkuSlabá batéria
@@ -58,8 +58,8 @@
Verzia firmvéruEquil bude automaticky vypnutáEquil automatické vypnutie
- Rýchlosť: %1$.2f JI/h, Doba trvania: %2$d minút
- %1$.2f JI
+ Rýchlosť: %1$.2f U/h, Doba trvania: %2$d minút
+ %1$.2f UTyp:Nastaviť bolus
@@ -122,7 +122,7 @@
Zastavené abnormálne podávanie izulínuPozastaviťObnoviť podávanie inzulínu
- %1$.2fJI/h @%2$s (%3$d/%4$d minút)
+ %1$.2f U/h @%2$s (%3$d/%4$d min)Pred chvíľouPred menej ako minútoupred %1$s
diff --git a/pump/equil/src/main/res/values-vi-rVN/strings.xml b/pump/equil/src/main/res/values-vi-rVN/strings.xml
index f165dc22e52..ca958cf1b2d 100644
--- a/pump/equil/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/equil/src/main/res/values-vi-rVN/strings.xml
@@ -1,9 +1,9 @@
Equil 5.3
- Pump Patch Equil 5.3 trở lên
+ Bơm Patch Equil 5.3 trở lên
- Base basal
+ Liều nền cơ bảnHủyCầnBỏ qua
@@ -15,14 +15,14 @@
Thao tác này sẽ dừng việc truyền insulin và khiến piston bơm rút về đáy!Lịch sửBình chứa Insulin
- Chế độ hoạt động
+ Chế độ đang chạyĐang chạyĐã dừngBị tạm dừngSố thiết bịDừng lạiThành công
- Thay insulin
+ Thay bình chứa insulinLịch sử sự kiệnMẹoÂm cảnh báo
@@ -36,24 +36,24 @@
Chưa có thiết bịGhép nối bơm Patch EquilLỗi kết nối
- Thay pump
+ Thay BơmVui lòng tháo bơm ra khỏi đế.Bạn có chắc chắn muốn từ bỏ quyền kiểm soát đối với %1$s không?Số thiết bị
- Tỷ lệ Basal %1$s U/giờ
- Tỷ lệ basal tạm thời %1$s U/giờ
+ Tỷ lệ liều nền %1$s U/giờ
+ Tỷ lệ liều nền tạm thời %1$s U/giờBolus %1$s UThời lượng TBR phải lớn hơn 0 và là bội số của %1$s phút.Insulin trong bình chứa không đủPin yếuInsulin trong bình chứa không đủ
- Pump không chạy
+ Bơm không chạyGhép đôiLỗi ghép đôiThử lạiPrime/FillĐuổi khí
- Liều Basal tạm thời
+ Liều liều nền tạm thờiTổng lượng đã tiêmLiều bolus trướcPhiên bản phần mềm
@@ -65,9 +65,9 @@
Đặt liều BolusHủy liều bolus
- Đặt Basal tạm thời
- Hủy Basal tạm thời
- Đặt lịch trình Basal
+ Đặt liều nền tạm thời
+ Hủy liều nền tạm thời
+ Đặt lịch trình liều nềnĐặt thời gianTạm dừng liều insulinTiếp tục lại việc tiêm insulin
@@ -75,8 +75,8 @@
Gắn CannulaHủy ghép đôi EquilCảnh báo
- Đặt liều Bolus mở rộng
- Hủy liều Bolus mở rộng
+ Đặt liều Bolus kéo dài
+ Hủy liều Bolus kéo dàiRút cần đẩyCấu hình chỉ để phát âm thanh thông báo
@@ -87,8 +87,8 @@
FillCấu hình thủ côngKhông tìm thấy thiết bị
- Lỗi kết nối Pump
- Không có phản hồi từ Pump
+ Lỗi kết nối Bơm
+ Không có phản hồi từ BơmKhông xác định được trạng thái của lệnhGắn bơm vào cơ thểCảnh báo mức pin yếu
@@ -97,7 +97,7 @@
Tất cảGhép đôiLiều bolus
- Liều Basal
+ Liều nềnCấu hìnhLịch sử hoạt độngLịch sử Equil
@@ -113,10 +113,10 @@
Chuẩn bị tự động tắt nguồnTự động tắt!Mồi ống chứa
- Thu hồi pít-tông pump
+ Thu hồi pít-tông BơmBắt đầu Bolus nhanh
- Bắt đầu Basal tạm thời
- Kết thúc Basal tạm thời
+ Bắt đầu liều nền tạm thời
+ Kết thúc liều nền tạm thờiMức pin yếuHết Pin!Đặt lại khi bật nguồn
@@ -142,7 +142,7 @@
%1$d ngàyPhiên bản firmware quá thấp. Không được hỗ trợ
- Vui lòng đặt mật khẩu mới để ghép nối với bơm Equil v5.3. Mật khẩu này cũng sẽ được sử dụng để hủy ghép nối với bơm hiện tại trong tương lai, vì vậy hãy chắc chắn ghi nhớ. Quy tắc mật khẩu: gồm 4 ký tự, chọn từ ABCDEF0123456789.
+ Vui lòng đặt mật khẩu mới để ghép nối với bơm Equil v5.3. Mật khẩu này cũng sẽ được sử dụng để hủy ghép nối với bơm hiện tại trong dự kiến, vì vậy hãy chắc chắn ghi nhớ. Quy tắc mật khẩu: gồm 4 ký tự, chọn từ ABCDEF0123456789.XóaĐặt mật khẩu ghép nốiSau khi lắp bơm vào đế, hãy chọn xem có muốn đuổi khí khỏi kim tiêm lưu hay không.
@@ -156,7 +156,7 @@
Mồi ống dẫn (cannula)Vui lòng tháo bơm ra khỏi đếVô hiệu hóa bơm cũ %1$s?
- Đã đồng bộ thời gian Pump
+ Đã đồng bộ BơmỐng chứa trống. Vui lòng thay ống chứa mớiPhải gồm 6 ký tự, chọn từ ABCDEF0123456789Lệnh hủy ghép nối không thành công. Bơm vẫn sẽ bị xóa. Mật khẩu được đặt trong quá trình ghép nối sẽ không bị xóa khỏi bơm.
diff --git a/pump/equil/src/test/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGetTest.kt b/pump/equil/src/test/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGetTest.kt
index 55d873aaeee..a7ab7ea23ee 100644
--- a/pump/equil/src/test/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGetTest.kt
+++ b/pump/equil/src/test/kotlin/app/aaps/pump/equil/manager/command/CmdDevicesOldGetTest.kt
@@ -97,8 +97,8 @@ class CmdDevicesOldGetTest : TestBaseWithProfile() {
@Test
fun `isSupport should check firmware version`() {
val cmd = CmdDevicesOldGet("00:11:22:33:44:55", aapsLogger, preferences, equilManager)
- // Initially firmware version is 0.0
- assertFalse(cmd.isSupport())
+ // Initially firmware version is 0.0, serial starting with '0' needs version check
+ assertFalse(cmd.isSupport("0ABC12"))
}
@Test
@@ -162,7 +162,7 @@ class CmdDevicesOldGetTest : TestBaseWithProfile() {
thread.join(1000)
assertTrue(cmd.cmdSuccess)
- assertTrue(cmd.isSupport()) // 5.5 should be supported (>= 5.3)
+ assertTrue(cmd.isSupport("0ABC12")) // 5.5 should be supported (>= 5.3)
}
@Test
diff --git a/pump/insight/src/main/res/values-sk-rSK/strings.xml b/pump/insight/src/main/res/values-sk-rSK/strings.xml
index f65100312d7..d7a2dfba951 100644
--- a/pump/insight/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/insight/src/main/res/values-sk-rSK/strings.xml
@@ -18,7 +18,7 @@
CDD bazálov%1$d%% pre %2$d / %3$d minDuálny bolus
- %1$.2f / %2$.2f JI pre %3$d min
+ %1$.2f / %2$.2f U pre %3$d minPosledný bolusVyhľadávam zariadenia...Párovanie dokončené
diff --git a/pump/insight/src/main/res/values-vi-rVN/alert_titles.xml b/pump/insight/src/main/res/values-vi-rVN/alert_titles.xml
index dbb563a6634..2f73804f24d 100644
--- a/pump/insight/src/main/res/values-vi-rVN/alert_titles.xml
+++ b/pump/insight/src/main/res/values-vi-rVN/alert_titles.xml
@@ -16,7 +16,7 @@
Ống insulin đã hếtPin hếtTắt tự động – bơm đã dừng
- Tắc insulin
+ Tắc nghẽnHết thời gian mượn(tạm) – kết thúc hoạt độngThay ống chứa insulin chưa hoàn tấtTải dữ liệu thất bại
diff --git a/pump/insight/src/main/res/values-vi-rVN/exceptions.xml b/pump/insight/src/main/res/values-vi-rVN/exceptions.xml
index 9b16813c463..b58d672eaba 100644
--- a/pump/insight/src/main/res/values-vi-rVN/exceptions.xml
+++ b/pump/insight/src/main/res/values-vi-rVN/exceptions.xml
@@ -9,6 +9,6 @@
Không có TBR đang hoạt động để hủyKhông có TBR đang hoạt động để thay đổiKhông có liều bolus nào để hủy
- Pump đã ở trạng thái này
+ Bơm đã ở trạng thái nàyKhông được phép ở chế độ chạy
diff --git a/pump/insight/src/main/res/values-vi-rVN/strings.xml b/pump/insight/src/main/res/values-vi-rVN/strings.xml
index c1cda37c58a..6c060a1ddcb 100644
--- a/pump/insight/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/insight/src/main/res/values-vi-rVN/strings.xml
@@ -6,16 +6,16 @@
Đang Khôi PhụcTrạng tháiThời gian hồi phục
- Kết nối gần nhất
- Khởi động Pump
- Dừng Pump
+ Đã kết nối lúc
+ Khởi động Bơm
+ Dừng BơmĐã bắt đầuĐã dừng
- Chế độ hoạt động
- Tích hợp Pump cho các Pump Accu-Chek Insight
+ Chế độ vận hành
+ Tích hợp Bơm cho các Bơm Accu-Chek InsightChưa được lắp
- Tổng liều Bolus hàng ngày
- Tổng liều Basal hàng ngày (TDD)
+ Tổng liều Bolus
+ Tổng liều nền%1$d%% trong %2$d / %3$d phútBolus nhiều đợt%1$.2f / %2$.2f U trong %3$d phút
@@ -23,19 +23,19 @@
Đang tìm kiếm thiết bị…Hoàn thành ghép đôiMã hiển thị trên thiết bị này có khớp với mã trên bơm của bạn không?
- Ghép nối Pump Insight
+ Ghép nối Bơm InsightAccu-Chek Insight%1$s: %2$sỐng dẫn insulin đã được thaySightCảnh báo bơm InsightTắt rung khi tiêm bolus thủ công
- Dành cho bolus và bolus mở rộng (chỉ khả dụng với firmware Insight 3.x)
+ Dành cho bolus và bolus kéo dài (chỉ khả dụng với firmware Insight 3.x)Tắt rung khi tiêm bolus tự động
- Dành cho SMB và Basal tạm thời với mô phỏng TBR (chỉ khả dụng với firmware Insight 3.x)
+ Dành cho SMB và liều nền tạm thời với mô phỏng TBR (chỉ khả dụng với firmware Insight 3.x)Hết thời gian chờ trong quá trình trao đổi – đặt lại Bluetooth
- Đã dừng Pump
- Đã khởi động Pump
+ Đã dừng Bơm
+ Đã khởi động BơmPhiên bản phần mềmPhiên bản phần mềm xử lý giao diệnPhiên bản phần mềm bộ xử lý PC
@@ -50,14 +50,14 @@
Ghi lại thay đổi bình chứa insulinGhi lại thay đổi dây truyềnGhi lại thay đổi Pin
- Ghi lại thay đổi chế độ hoạt động
+ Ghi lại thay đổi chế độ vận hànhGhi lại cảnh báoBật mô phỏng TBR
- Sử dụng liều bolus mở rộng thay vì TBR để vượt qua giới hạn 250%
+ Sử dụng liều bolus kéo dài thay vì TBR để vượt qua giới hạn 250%Thời gian trễ ngắt kết nối [giây]Thời gian hồi phục tối đa [giây]Thời gian hồi phục tối thiểu [giây]
- Cảnh báo pump
+ Cảnh báo BơmThông tin ghép nối%1$s (%2$s)
diff --git a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/MedtronicPumpPlugin.kt b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/MedtronicPumpPlugin.kt
index 1cb6a29c260..9e0e2ca9485 100644
--- a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/MedtronicPumpPlugin.kt
+++ b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/MedtronicPumpPlugin.kt
@@ -6,6 +6,7 @@ import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.os.SystemClock
+import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen
@@ -36,6 +37,8 @@ import app.aaps.core.interfaces.rx.events.EventRefreshButtonState
import app.aaps.core.interfaces.rx.events.EventRefreshOverview
import app.aaps.core.interfaces.rx.events.EventSWRLStatus
import app.aaps.core.interfaces.ui.UiInteraction
+import app.aaps.core.interfaces.utils.DateUtil
+import app.aaps.core.interfaces.utils.DecimalFormatter
import app.aaps.core.interfaces.utils.fabric.FabricPrivacy
import app.aaps.core.keys.interfaces.Preferences
import app.aaps.core.utils.DateTimeUtil
@@ -51,6 +54,8 @@ import app.aaps.pump.common.PumpPluginAbstract
import app.aaps.pump.common.data.PumpStatus
import app.aaps.pump.common.defs.PumpDriverState
import app.aaps.pump.common.dialog.RileyLinkBLEConfigActivity
+import app.aaps.pump.common.driver.refresh.PumpDataRefreshAction
+import app.aaps.pump.common.driver.refresh.PumpDataRefreshType
import app.aaps.pump.common.events.EventRileyLinkDeviceStatusChange
import app.aaps.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType
import app.aaps.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency
@@ -83,6 +88,7 @@ import app.aaps.pump.medtronic.defs.BatteryType
import app.aaps.pump.medtronic.defs.MedtronicCommandType
import app.aaps.pump.medtronic.defs.MedtronicCommandType.Companion.getSettings
import app.aaps.pump.medtronic.defs.MedtronicCustomActionType
+import app.aaps.pump.medtronic.defs.MedtronicDeviceType
import app.aaps.pump.medtronic.defs.MedtronicNotificationType
import app.aaps.pump.medtronic.defs.MedtronicStatusRefreshType
import app.aaps.pump.medtronic.defs.MedtronicUIResponseType
@@ -96,6 +102,7 @@ import app.aaps.pump.medtronic.keys.MedtronicStringPreferenceKey
import app.aaps.pump.medtronic.service.RileyLinkMedtronicService
import app.aaps.pump.medtronic.util.MedtronicUtil
import app.aaps.pump.medtronic.util.MedtronicUtil.Companion.isSame
+import app.aaps.pump.medtronic.driver.MedtronicPumpDriverConfiguration
import org.joda.time.LocalDateTime
import java.util.Calendar
import java.util.GregorianCalendar
@@ -127,9 +134,11 @@ class MedtronicPumpPlugin @Inject constructor(
private val rileyLinkServiceData: RileyLinkServiceData,
private val serviceTaskExecutor: ServiceTaskExecutor,
private val uiInteraction: UiInteraction,
+ dateUtil: DateUtil,
aapsSchedulers: AapsSchedulers,
pumpSync: PumpSync,
pumpSyncStorage: PumpSyncStorage,
+ decimalFormatter: DecimalFormatter,
pumpEnactResultProvider: Provider,
private val wakeAndTuneTaskProvider: Provider,
private val resetRileyLinkConfigurationTaskProvider: Provider
@@ -149,23 +158,33 @@ class MedtronicPumpPlugin @Inject constructor(
MedtronicLongNonKey::class.java, MedtronicStringPreferenceKey::class.java
),
PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later
- rh, aapsLogger, preferences, commandQueue, rxBus, context, fabricPrivacy, aapsSchedulers, pumpSync, pumpSyncStorage, pumpEnactResultProvider
+ rh = rh,
+ aapsLogger = aapsLogger,
+ preferences = preferences,
+ commandQueue = commandQueue,
+ rxBus = rxBus,
+ //activePlugin = activePlugin,
+ context = context,
+ fabricPrivacy = fabricPrivacy,
+ dateUtil = dateUtil,
+ aapsSchedulers = aapsSchedulers,
+ pumpSync = pumpSync,
+ pumpSyncStorage = pumpSyncStorage,
+ decimalFormatter = decimalFormatter,
+ //instantiator = instantiator,
+ pumpEnactResultProvider = pumpEnactResultProvider,
+ pumpDriverConfigurationInternal = MedtronicPumpDriverConfiguration()
), Pump, RileyLinkPumpDevice, PumpSyncEntriesCreator {
private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null
- // variables for handling statuses and history
- private var firstRun = true
- private var isRefresh = false
- private val statusRefreshMap: MutableMap = mutableMapOf()
- private var isInitialized = false
+ // variables for handling statuses and history (most moved to PumpAbstract now)
private var lastPumpHistoryEntry: PumpHistoryEntry? = null
private val busyTimestamps: MutableList = ArrayList()
- private var hasTimeDateOrTimeZoneChanged = false
private var isBusy = false
override fun onStart() {
- aapsLogger.debug(LTag.PUMP, deviceID() + " started. (V2.0006)")
+ aapsLogger.debug(LTag.PUMP, deviceID() + " started. (V2.0007)")
serviceConnection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName) {
aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is disconnected")
@@ -199,6 +218,14 @@ class MedtronicPumpPlugin @Inject constructor(
super.onStart()
}
+ override fun updatePreferenceSummary(pref: Preference) {
+ super.updatePreferenceSummary(pref)
+ if (pref.key == RileyLinkStringPreferenceKey.MacAddress.key) {
+ val value = preferences.getIfExists(RileyLinkStringPreferenceKey.MacAddress)
+ pref.summary = value ?: rh.gs(app.aaps.core.ui.R.string.not_set_short)
+ }
+ }
+
override fun initPumpStatusData() {
medtronicPumpStatus.lastConnection = preferences.get(RileyLinkLongKey.LastGoodDeviceCommunicationTime)
medtronicPumpStatus.lastDataTime = medtronicPumpStatus.lastConnection
@@ -234,22 +261,8 @@ class MedtronicPumpPlugin @Inject constructor(
}
override fun onStartScheduledPumpActions() {
-
// check status every minute (if any status needs refresh we send readStatus command)
- Thread {
- do {
- SystemClock.sleep(60000)
- if (this.isInitialized) {
- val statusRefresh = synchronized(statusRefreshMap) { HashMap(statusRefreshMap) }
- if (doWeHaveAnyStatusNeededRefreshing(statusRefresh)) {
- if (!commandQueue.statusInQueue()) {
- commandQueue.readStatus(rh.gs(R.string.scheduled_status_refresh), null)
- }
- }
- clearBusyQueue()
- }
- } while (serviceRunning)
- }.start()
+ startRefreshOfPumpCommands()
}
override val serviceClass: Class<*> = RileyLinkMedtronicService::class.java
@@ -275,7 +288,7 @@ class MedtronicPumpPlugin @Inject constructor(
override fun isInitialized(): Boolean {
if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isInitialized")
- return isServiceSet && isInitialized
+ return isServiceSet && isDriverInitialized
}
override fun setBusy(busy: Boolean) {
@@ -352,9 +365,15 @@ class MedtronicPumpPlugin @Inject constructor(
return rileyLinkMedtronicService?.deviceCommunicationManager?.isDeviceReachable() != true
}
+
private fun refreshAnyStatusThatNeedsToBeRefreshed() {
- val statusRefresh = synchronized(statusRefreshMap) { HashMap(statusRefreshMap) }
- if (!doWeHaveAnyStatusNeededRefreshing(statusRefresh)) {
+ //val statusRefresh = synchronized(statusRefreshMap) { HashMap(statusRefreshMap) }
+
+ val statusRefresh = workWithStatusRefresh(
+ PumpDataRefreshAction.GetData, null,
+ null)
+
+ if (!doWeHaveAnyStatusNeededRefereshing(statusRefresh)) {
return
}
var resetTime = false
@@ -372,31 +391,36 @@ class MedtronicPumpPlugin @Inject constructor(
}
// execute
- val refreshTypesNeededToReschedule: MutableSet = mutableSetOf()
- for ((key, value) in statusRefresh) {
- if (value > 0 && System.currentTimeMillis() > value) {
+ val refreshTypesNeededToReschedule: MutableSet = mutableSetOf()
+ for ((key, value) in statusRefresh!!) {
+ if (value!! > 0 && System.currentTimeMillis() > value) {
@Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA")
when (key) {
- MedtronicStatusRefreshType.PumpHistory -> {
+ PumpDataRefreshType.PumpHistory -> {
readPumpHistory()
}
- MedtronicStatusRefreshType.PumpTime -> {
+ PumpDataRefreshType.PumpTime -> {
checkTimeAndOptionallySetTime()
refreshTypesNeededToReschedule.add(key)
resetTime = true
}
- MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.RemainingInsulin -> {
- rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!)
+ PumpDataRefreshType.BatteryStatus,
+ PumpDataRefreshType.RemainingInsulin -> {
+ rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(
+ getPumpCommandForRefresh(key, medtronicUtil.medtronicPumpModel)!!)
refreshTypesNeededToReschedule.add(key)
resetTime = true
}
- MedtronicStatusRefreshType.Configuration -> {
- rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!)
+ PumpDataRefreshType.Configuration -> {
+ rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(
+ getPumpCommandForRefresh(key, medtronicUtil.medtronicPumpModel)!!)
resetTime = true
}
+
+ else -> { }
}
}
@@ -406,17 +430,10 @@ class MedtronicPumpPlugin @Inject constructor(
}
}
- if (resetTime) medtronicPumpStatus.setLastCommunicationToNow()
+ if (resetTime)
+ medtronicPumpStatus.setLastCommunicationToNow()
}
- private fun doWeHaveAnyStatusNeededRefreshing(statusRefresh: Map): Boolean {
- for ((_, value) in statusRefresh) {
- if (value > 0 && System.currentTimeMillis() > value) {
- return true
- }
- }
- return hasTimeDateOrTimeZoneChanged
- }
private fun setRefreshButtonEnabled(enabled: Boolean) {
rxBus.send(EventRefreshButtonState(enabled))
@@ -454,11 +471,11 @@ class MedtronicPumpPlugin @Inject constructor(
// remaining insulin (>50 = 4h; 50-20 = 1h; 15m)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetRemainingInsulin)
- scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10)
+ scheduleNextRefresh(PumpDataRefreshType.RemainingInsulin, 10)
// remaining power (1h)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetBatteryStatus)
- scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20)
+ scheduleNextRefresh(PumpDataRefreshType.BatteryStatus, 20)
// configuration (once and then if history shows config changes)
rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(getSettings(medtronicUtil.medtronicPumpModel))
@@ -477,7 +494,7 @@ class MedtronicPumpPlugin @Inject constructor(
if (!isRefresh) {
pumpState = PumpDriverState.Initialized
}
- isInitialized = true
+ isDriverInitialized = true
// this.pumpState = PumpDriverState.Initialized;
firstRun = false
return true
@@ -494,7 +511,7 @@ class MedtronicPumpPlugin @Inject constructor(
@Synchronized
override fun isThisProfileSet(profile: Profile): Boolean {
aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitialized=" + medtronicPumpStatus.basalProfileStatus)
- if (!isInitialized) return true
+ if (!isDriverInitialized) return true
if (medtronicPumpStatus.basalProfileStatus === BasalProfileStatus.NotInitialized) {
// this shouldn't happen, but if there was problem we try again
basalProfiles
@@ -523,8 +540,6 @@ class MedtronicPumpPlugin @Inject constructor(
if (!isSame(basalsByHour[hour], basalValueValue)) {
invalid = true
}
- // stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue))
- // stringBuilder.append(" ")
}
aapsLogger.debug(LTag.PUMP, stringBuilder.toString())
if (!invalid) {
@@ -535,12 +550,20 @@ class MedtronicPumpPlugin @Inject constructor(
return !invalid
}
- override val lastDataTime: Long get() = medtronicPumpStatus.lastConnection
- override val lastBolusTime: Long? get() = null
- override val lastBolusAmount: Double? get() = null
- override val baseBasalRate: Double get() = medtronicPumpStatus.basalProfileForHour
- override val reservoirLevel: Double get() = medtronicPumpStatus.reservoirRemainingUnits
- override val batteryLevel: Int? get() = medtronicPumpStatus.batteryRemaining
+ fun lastDataTime(): Long {
+ return if (medtronicPumpStatus.lastConnection > 0) {
+ medtronicPumpStatus.lastConnection
+ } else System.currentTimeMillis()
+ }
+
+ override val baseBasalRate: Double
+ get() = medtronicPumpStatus.basalProfileForHour
+
+ override val reservoirLevel: Double
+ get() = medtronicPumpStatus.reservoirRemainingUnits
+
+ override val batteryLevel: Int?
+ get() = medtronicPumpStatus.batteryRemaining
override fun triggerUIChange() {
rxBus.send(EventMedtronicPumpValuesChanged())
@@ -593,7 +616,7 @@ class MedtronicPumpPlugin @Inject constructor(
} else {
aapsLogger.info(LTag.PUMP, String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is %d s. Do nothing.", timeDiff))
}
- scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0)
+ scheduleNextRefresh(PumpDataRefreshType.PumpTime, 0)
}
@Synchronized
@@ -619,7 +642,7 @@ class MedtronicPumpPlugin @Inject constructor(
}
medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus)
if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) {
- // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled.");
+ aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - Delivery Canceled.");
return setNotReachable(isBolus = true, success = true)
}
@@ -707,7 +730,7 @@ class MedtronicPumpPlugin @Inject constructor(
.comment(R.string.medtronic_pump_status_pump_unreachable)
}
medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus)
- aapsLogger.info(LTag.PUMP, "setTempBasalAbsolute: rate: " + absoluteRate + ", duration=" + durationInMinutes)
+ aapsLogger.info(LTag.PUMP, "setTempBasalAbsolute: rate: ${absoluteRate}, duration= $durationInMinutes")
// read current TBR
val tbrCurrent = readTBR()
@@ -767,7 +790,7 @@ class MedtronicPumpPlugin @Inject constructor(
} else {
medtronicPumpStatus.tempBasalStart = System.currentTimeMillis()
medtronicPumpStatus.tempBasalAmount = absoluteRate
- medtronicPumpStatus.tempBasalLength = durationInMinutes
+ medtronicPumpStatus.tempBasalDuration = durationInMinutes
val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes * 60, tbrType)
@@ -866,12 +889,12 @@ class MedtronicPumpPlugin @Inject constructor(
// if (isLoggingEnabled())
// LOG.error(getLogPrefix() + "readPumpHistory WIP.");
readPumpHistoryLogic()
- scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory)
+ scheduleNextRefresh(PumpDataRefreshType.PumpHistory)
if (medtronicHistoryData.hasRelevantConfigurationChanged()) {
- scheduleNextRefresh(MedtronicStatusRefreshType.Configuration, -1)
+ scheduleNextRefresh(PumpDataRefreshType.Configuration, -1)
}
if (medtronicHistoryData.hasPumpTimeChanged()) {
- scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1)
+ scheduleNextRefresh(PumpDataRefreshType.PumpTime, -1)
}
if (medtronicPumpStatus.basalProfileStatus !== BasalProfileStatus.NotInitialized
&& medtronicHistoryData.hasBasalProfileChanged()
@@ -977,27 +1000,27 @@ class MedtronicPumpPlugin @Inject constructor(
}
}
- private fun scheduleNextRefresh(refreshType: MedtronicStatusRefreshType, additionalTimeInMinutes: Int = 0) {
- when (refreshType) {
- MedtronicStatusRefreshType.RemainingInsulin -> {
- val remaining = medtronicPumpStatus.reservoirRemainingUnits
- val min: Int = if (remaining > 50) 4 * 60 else if (remaining > 20) 60 else 15
- synchronized(statusRefreshMap) { statusRefreshMap[refreshType] = getTimeInFutureFromMinutes(min) }
- }
-
- MedtronicStatusRefreshType.PumpTime, MedtronicStatusRefreshType.Configuration, MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.PumpHistory -> {
- synchronized(statusRefreshMap) { statusRefreshMap[refreshType] = getTimeInFutureFromMinutes(refreshType.refreshTime + additionalTimeInMinutes) }
- }
- }
- }
-
- private fun getTimeInFutureFromMinutes(minutes: Int): Long {
- return System.currentTimeMillis() + getTimeInMs(minutes)
- }
-
- private fun getTimeInMs(minutes: Int): Long {
- return minutes * 60 * 1000L
- }
+ // private fun scheduleNextRefresh(refreshType: MedtronicStatusRefreshType, additionalTimeInMinutes: Int = 0) {
+ // when (refreshType) {
+ // MedtronicStatusRefreshType.RemainingInsulin -> {
+ // val remaining = medtronicPumpStatus.reservoirRemainingUnits
+ // val min: Int = if (remaining > 50) 4 * 60 else if (remaining > 20) 60 else 15
+ // synchronized(statusRefreshMap) { statusRefreshMap[refreshType] = getTimeInFutureFromMinutes(min) }
+ // }
+ //
+ // MedtronicStatusRefreshType.PumpTime, MedtronicStatusRefreshType.Configuration, MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.PumpHistory -> {
+ // synchronized(statusRefreshMap) { statusRefreshMap[refreshType] = getTimeInFutureFromMinutes(refreshType.refreshTime + additionalTimeInMinutes) }
+ // }
+ // }
+ // }
+
+ // private fun getTimeInFutureFromMinutes(minutes: Int): Long {
+ // return System.currentTimeMillis() + getTimeInMs(minutes)
+ // }
+ //
+ // private fun getTimeInMs(minutes: Int): Long {
+ // return minutes * 60 * 1000L
+ // }
private fun readTBR(): TempBasalPair? {
val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.ReadTemporaryBasal)
@@ -1251,7 +1274,7 @@ class MedtronicPumpPlugin @Inject constructor(
if (requiredKey != null) return
val batteryEntries = mutableListOf().also { list -> BatteryType.entries.forEach { list.add(rh.gs(it.friendlyName)) } }.toTypedArray()
- val encodingEntries = arrayOf(rh.gs(RileyLinkEncodingType.FourByteSixByteLocal.friendlyName!!), rh.gs(RileyLinkEncodingType.FourByteSixByteLocal.friendlyName!!))
+ val encodingEntries = arrayOf(rh.gs(RileyLinkEncodingType.FourByteSixByteLocal.friendlyName!!), rh.gs(RileyLinkEncodingType.FourByteSixByteRileyLink.friendlyName!!))
val pumpTypeEntries = arrayOf(
"Other (unsupported)",
@@ -1359,4 +1382,17 @@ class MedtronicPumpPlugin @Inject constructor(
addPreference(AdaptiveSwitchPreference(ctx = context, booleanKey = MedtronicBooleanPreferenceKey.SetNeutralTemp, title = R.string.set_neutral_temps_title, summary = R.string.set_neutral_temps_summary))
}
}
-}
\ No newline at end of file
+
+
+ fun getPumpCommandForRefresh(pumpDataRefreshType: PumpDataRefreshType, medtronicDeviceType: MedtronicDeviceType) : MedtronicCommandType? {
+ return when (pumpDataRefreshType) {
+ PumpDataRefreshType.Configuration -> MedtronicCommandType.getSettings(medtronicDeviceType)
+ PumpDataRefreshType.RemainingInsulin -> MedtronicCommandType.GetRemainingInsulin
+ PumpDataRefreshType.BatteryStatus -> MedtronicCommandType.GetBatteryStatus
+ PumpDataRefreshType.PumpTime -> MedtronicCommandType.GetRealTimeClock
+ else
+ -> null
+ }
+ }
+
+}
diff --git a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt
index 6834e71769b..10cea8bca48 100644
--- a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt
+++ b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt
@@ -83,7 +83,7 @@ class MedtronicUIPostprocessor @Inject constructor(
MedtronicCommandType.CancelTBR -> {
medtronicPumpStatus.tempBasalStart = null
medtronicPumpStatus.tempBasalAmount = null
- medtronicPumpStatus.tempBasalLength = null
+ medtronicPumpStatus.tempBasalDuration = null
}
MedtronicCommandType.GetRealTimeClock -> {
diff --git a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/data/dto/TempBasalPair.kt b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/data/dto/TempBasalPair.kt
index ce96258ec46..0e287c514d4 100644
--- a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/data/dto/TempBasalPair.kt
+++ b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/data/dto/TempBasalPair.kt
@@ -21,12 +21,13 @@ class TempBasalPair : TempBasalPair {
* @param startTimeByte
* @param isPercent
*/
- constructor(rateByte: Byte, startTimeByte: Int, isPercent: Boolean) : super() {
- val rateInt = ByteUtil.asUINT8(rateByte)
- if (isPercent) insulinRate = rateByte.toDouble() else insulinRate = rateInt * 0.025
- durationMinutes = startTimeByte * 30
- this.isPercent = isPercent
- }
+ constructor(rateByte: Byte, startTimeByte: Int, isPercent: Boolean) : super(
+ insulinRate = if (isPercent) ByteUtil.asUINT8(rateByte).toDouble()
+ else ByteUtil.asUINT8(rateByte) * 0.025,
+ isPercent = isPercent,
+ durationMinutes = startTimeByte * 30,
+ null
+ )
/**
* This constructor is for use with PumpHistoryDecoder
@@ -35,17 +36,18 @@ class TempBasalPair : TempBasalPair {
* @param startTimeByte
* @param isPercent
*/
- constructor(rateByte0: Byte, rateByte1: Byte, startTimeByte: Int, isPercent: Boolean) {
- if (isPercent) {
- insulinRate = rateByte0.toDouble()
- } else {
- insulinRate = ByteUtil.toInt(rateByte1.toInt(), rateByte0.toInt()) * 0.025
- }
+ constructor(rateByte0: Byte, rateByte1: Byte, startTimeByte: Int, isPercent: Boolean) : super(
+ insulinRate = if (isPercent) rateByte0.toDouble() else
+ ByteUtil.toInt(rateByte1.toInt(), rateByte0.toInt()) * 0.025 ,
+ isPercent = isPercent,
durationMinutes = startTimeByte * 30
- this.isPercent = isPercent
- }
+ )
- constructor(aapsLogger: AAPSLogger, response: ByteArray) : super() {
+ constructor(aapsLogger: AAPSLogger, response: ByteArray) : super(
+ insulinRate = 0.0,
+ isPercent = response[0] == 1.toByte(),
+ durationMinutes = 0
+ ) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received TempBasal response: " + ByteUtil.getHex(response))
isPercent = response[0] == 1.toByte()
insulinRate = if (isPercent) {
diff --git a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/driver/MedtronicPumpDriverConfiguration.kt b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/driver/MedtronicPumpDriverConfiguration.kt
new file mode 100644
index 00000000000..ac28279d2e0
--- /dev/null
+++ b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/driver/MedtronicPumpDriverConfiguration.kt
@@ -0,0 +1,35 @@
+package app.aaps.pump.medtronic.driver
+
+import app.aaps.core.data.pump.defs.PumpType
+import app.aaps.pump.common.driver.PumpDriverConfiguration
+import app.aaps.pump.common.driver.ble.PumpBLESelector
+import app.aaps.pump.common.driver.db.PumpDriverDatabaseOperation
+import app.aaps.pump.common.driver.history.PumpHistoryDataProvider
+
+// At the moment this class is not used, but since Medtronic is using PumpPluginAbstract, it needs it
+// and changes could be made to use this, which would deduplicate History and BLE Activity screens
+class MedtronicPumpDriverConfiguration: PumpDriverConfiguration {
+
+ override fun getPumpBLESelector(): PumpBLESelector? {
+ //TODO("Not yet implemented")
+ return null
+ }
+
+ override fun getPumpHistoryDataProvider(): PumpHistoryDataProvider? {
+ //TODO("Not yet implemented")
+ return null
+ }
+
+ override fun getPumpDriverDatabaseOperation(): PumpDriverDatabaseOperation {
+ TODO("Not yet implemented")
+ }
+
+ override fun getPumpType(): PumpType {
+ return PumpType.MEDTRONIC_523_723_REVEL
+ }
+
+ override var logPrefix: String = "MedtronicPumpPlugin::"
+ override var canHandleDST: Boolean = false
+ override var hasService: Boolean = true
+
+}
\ No newline at end of file
diff --git a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/driver/MedtronicPumpStatus.kt b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/driver/MedtronicPumpStatus.kt
index e5e15f9762f..378f1b634e9 100644
--- a/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/driver/MedtronicPumpStatus.kt
+++ b/pump/medtronic/src/main/kotlin/app/aaps/pump/medtronic/driver/MedtronicPumpStatus.kt
@@ -25,13 +25,14 @@ import javax.inject.Singleton
*/
@Singleton
class MedtronicPumpStatus @Inject constructor(
- preferences: Preferences,
+ private val preferences: Preferences,
private val rxBus: RxBus,
private val rileyLinkUtil: RileyLinkUtil
) : PumpStatus(PumpType.MEDTRONIC_522_722) {
var errorDescription: String? = null
- var serialNumber: String = preferences.get(MedtronicStringPreferenceKey.Serial)
+ var serialNumber: String = preferences.getIfExists(MedtronicStringPreferenceKey.Serial) ?: ""
+ var pumpFrequency: String? = null
var maxBolus: Double? = null
var maxBasal: Double? = null
var runningTBR: PumpDbEntryTBR? = null
@@ -51,7 +52,7 @@ class MedtronicPumpStatus @Inject constructor(
var basalProfileStatus = BasalProfileStatus.NotInitialized
var batteryType = BatteryType.None
- init {
+ fun initSettings() {
activeProfileName = "STD"
reservoirRemainingUnits = 75.0
batteryRemaining = 75
@@ -59,6 +60,7 @@ class MedtronicPumpStatus @Inject constructor(
if (medtronicDeviceTypeMap.isEmpty()) createMedtronicDeviceTypeMap()
lastConnection = preferences.get(MedtronicLongNonKey.LastGoodPumpCommunicationTime)
lastDataTime = lastConnection
+ this.tempBasalLegacyMode = true
}
private fun createMedtronicDeviceTypeMap() {
@@ -98,6 +100,18 @@ class MedtronicPumpStatus @Inject constructor(
return 0.0
}
+ // Battery type
+ //private var batteryTypeByDescMap: MutableMap = HashMap()
+
+ // fun getBatteryTypeByDescription(batteryTypeStr: String?): BatteryType {
+ // if (batteryTypeByDescMap.isEmpty()) {
+ // for (value in BatteryType.entries) {
+ // batteryTypeByDescMap[rh.gs(value.description)] = value
+ // }
+ // }
+ // return batteryTypeByDescMap[batteryTypeStr] ?: BatteryType.None
+ // }
+
override val errorInfo: String get() = errorDescription ?: "-"
val tbrRemainingTime: Int?
@@ -105,16 +119,20 @@ class MedtronicPumpStatus @Inject constructor(
if (tempBasalStart == null) return null
if (tempBasalEnd == null) {
val startTime = tempBasalStart!!
- tempBasalEnd = startTime + tempBasalLength!! * 60 * 1000
+ tempBasalEnd = startTime + tempBasalDuration!! * 60 * 1000
}
if (System.currentTimeMillis() > tempBasalEnd!!) {
tempBasalStart = null
tempBasalEnd = null
- tempBasalLength = null
+ tempBasalDuration = null
tempBasalAmount = null
return null
}
val timeMinutes = (tempBasalEnd!! - System.currentTimeMillis()) / (1000 * 60)
return timeMinutes.toInt()
}
-}
\ No newline at end of file
+
+ init {
+ initSettings()
+ }
+}
diff --git a/pump/medtronic/src/main/res/values-sk-rSK/strings.xml b/pump/medtronic/src/main/res/values-sk-rSK/strings.xml
index f5310d4662a..4e752f256a6 100644
--- a/pump/medtronic/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/medtronic/src/main/res/values-sk-rSK/strings.xml
@@ -82,7 +82,7 @@
Čas v pumpe bol aktualizovanýNastaviť neutrálny dočasný bazálAk je povolená táto možnosť, zastaví sa dočasný bazál pred koncom každej hodiny. To môže u niektorých púmp pomôcť zastaviť pípanie/vibrácie na celú hodinu.
- %1$.1f JI/h (%2$d min zostáva)
+ %1$.1f U/h (%2$d min zostáva)Zistené chybné dáta v histórii pumpy. Otvor nový incident a poskytni logy.Štatistiky RLTyp:
diff --git a/pump/medtronic/src/main/res/values-vi-rVN/strings.xml b/pump/medtronic/src/main/res/values-vi-rVN/strings.xml
index ad16af43ce0..8d5d2f5545b 100644
--- a/pump/medtronic/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/medtronic/src/main/res/values-vi-rVN/strings.xml
@@ -3,14 +3,14 @@
Tích hợp bơm Medtronic, cần có thiết bị RileyLink và đúng mẫu bơm hỗ trợ
- Số serial Pump
- Loại Pump
- Tần số Pump
+ Số serial Bơm
+ Loại Bơm
+ Tần số BơmThời gian trễ trước khi bắt đầu tiêm bolus (giây)Bolus tối đa trên bơm (U)
- Basal tối đa trên bơm (U)
+ Liều nền tối đa trên bơm (U)Mã hóa Medtronic
- Đánh thức và hiệu chỉnh
+ Đánh thức và tinh chỉnhXóa chặn bolusĐặt lại cấu hình RileyLinkLoại pin (xem nguồn)
@@ -25,17 +25,17 @@
LỗiSerial # chưa thiết lập.Serial # chưa hợp lệ.
- Chưa chọn loại pump.
- Loại pump này không được hỗ trợ.
- Tần số pump chưa được thiết lập.
+ Chưa chọn loại Bơm.
+ Loại Bơm này không được hỗ trợ.
+ Tần số Bơm chưa được thiết lập.Tần số bơm không được hỗ trợ.Địa chỉ RileyLink không hợp lệ.
- Loại pump phát hiện không khớp với loại đã cấu hình.
+ Loại Bơm phát hiện không khớp với loại đã cấu hình.Cài đặt các profiles/patterns chưa được bật trên bơm. Hãy bật nó trên bơm.
- Cấu hình Basal trên bơm không chính xác (phải là Standard).
- Loại TBR trên pump không đúng (phải là Absolute).
- Giá trị Max Bolus trên pump không đúng (phải là %1$.2f).
- Giá trị Max Basal trên pump không đúng (phải là %1$.2f).
+ Hồ sơ liều nền trên bơm không chính xác (phải là Standard).
+ Loại TBR trên Bơm không đúng (phải là Absolute).
+ Giá trị Max Bolus trên Bơm không đúng (phải là %1$.2f).
+ Giá trị liều nền tối đa trên bơm không đúng (phải là %1$.2f).Thao tác không thể thực hiện được.\n\nBạn cần cấu hình bơm Medtronic trước khi có thể sử dụng thao tác này.Yêu cầu thay đổi thời gian trên 24 giờ đã được gửi.
@@ -45,43 +45,43 @@
- Lịch sử Pump Medtronic
+ Lịch sử bơm Medtronic
- Bạn đã hủy Bolus sau khi nó đã được thiết lập trên pump. Vì pump Medtronic không hỗ trợ hủy trực tiếp, bạn sẽ cần hủy thủ công. Đặt pump vào chế độ Suspend rồi thực hiện Resume (nếu bạn vẫn muốn hủy). Ứng dụng sẽ nhận các thay đổi này trong lần cập nhật tiếp theo (dưới 5 phút).
+ Bạn đã hủy liều Bolus sau khi nó đã được thiết lập trên bơm. Vì bơm Medtronic không hỗ trợ hủy trực tiếp, bạn sẽ cần hủy thủ công. Đặt bơm vào chế độ Suspend rồi thực hiện Resume (nếu bạn vẫn muốn hủy). Ứng dụng sẽ nhận các thay đổi này trong lần cập nhật tiếp theo (dưới 5 phút).Không thể đọc TBR hiện tại.Không thể hủy TBR hiện tại. Dừng thao tác.
- Thiết lập cấu hình thất bại, vì các mẫu sau có tỷ lệ Basal quá cao: %1$s
+ Thiết lập Hồ sơ thất bại, vì các mẫu sau có tỷ lệ liều nền quá cao: %1$sKhông thể tiêm Bolus.Không thể tiêm Bolus, vì lượng insulin hiện có (%1$.2f) ít hơn lượng Bolus yêu cầu (%2$.2f).Không thể thiết lập TBR.Không thể hủy TBR hiện tại.
- Không thể thiết lập Cấu hình Basal.
- Cấu hình Basal không thay đổi, nên sẽ không được thiết lập lại.
+ Không thể thiết lập Hồ sơ liều nền.
+ Hồ sơ liều nền không thay đổi, nên sẽ không được thiết lập lại.Lấy lịch sử - Trang %1$d (%2$d/16)Lấy lịch sử - Trang %1$d
- Lấy thời gian Pump
- Thiết lập thời gian Pump
+ Lấy thời gian Bơm
+ Thiết lập thời gian BơmLấy trạng thái pinLấy cài đặt
- Lấy mẫu Pump
- Lấy Cấu hình Basal
- Thiết lập Cấu hình Basal
- Lấy Temporary Basal
+ Lấy mẫu Bơm
+ Lấy Hồ sơ liều nền
+ Thiết lập Hồ sơ liều nền
+ Lấy liều nền tạm thờiThiết lập liều nền tạm thờiHủy liều nền tạm thờiThiết lập liều BolusLấy lượng insulin còn lại
- Không thể kết nối với Pump
+ Không thể kết nối với BơmCảnh báoBây giờcách đây
- Cần cập nhật đồng hồ Pump
+ Cần cập nhật đồng hồ Bơm
- Đã đồng bộ thời gian Pump
- Thiết lập basal tạm thời trung tính
- Nếu được bật, tính năng này sẽ hủy liều nền tạm thời trước khi kết thúc mỗi giờ. Phương pháp này có thể giúp ngăn một số pump phát tiếng bíp hoặc rung vào đầu giờ.
+ Đã cập nhật thời gian bơm
+ Thiết lập liều nền tạm thời trung tính
+ Nếu được bật, tính năng này sẽ hủy liều nền tạm thời trước khi kết thúc mỗi giờ. Phương pháp này có thể giúp ngăn một số bơm phát tiếng bíp hoặc rung vào đầu giờ.%1$.1f U/giờ (%2$d phút còn lại)Phát hiện dữ liệu lịch sử bơm không hợp lệ. Hãy tạo báo cáo mới và cung cấp nhật ký.Thống kê RL
diff --git a/pump/medtrum/src/main/res/values-nl-rNL/strings.xml b/pump/medtrum/src/main/res/values-nl-rNL/strings.xml
index 692388ad26c..bf276fb8fe1 100644
--- a/pump/medtrum/src/main/res/values-nl-rNL/strings.xml
+++ b/pump/medtrum/src/main/res/values-nl-rNL/strings.xml
@@ -28,6 +28,7 @@
FW versiePatch nrPatch verloopt
+ ActivatieVernieuwenReset alarmenPatch verwisselen
diff --git a/pump/medtrum/src/main/res/values-pl-rPL/strings.xml b/pump/medtrum/src/main/res/values-pl-rPL/strings.xml
index c76ac62c01f..53c96a96fc1 100644
--- a/pump/medtrum/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/medtrum/src/main/res/values-pl-rPL/strings.xml
@@ -28,6 +28,7 @@
Wersja FWNr PatchaPatch wygasa
+ AktywacjaOdświeżZresetuj alarmyZmień Patch
diff --git a/pump/medtrum/src/main/res/values-sk-rSK/strings.xml b/pump/medtrum/src/main/res/values-sk-rSK/strings.xml
index 165f604afa4..5b7a3f5f7f1 100644
--- a/pump/medtrum/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/medtrum/src/main/res/values-sk-rSK/strings.xml
@@ -19,11 +19,11 @@
Aktívny bolusStav pumpyAktívne alarmy
- %.2f JI
+ %.2f U %.2f VTyp bazáluBazálna dávka
- %.2f JI/h
+ %.2f U/hTyp pumpyVerzia FWČ. Patch
@@ -79,7 +79,7 @@
Základňa by nemala byť pripojená ku kanyle až do dalšieho kroku!Pripojte základňu k novej kanyle, odstráňte zostávajúci vzduch a doplňte inzulínom, potom stlačte tlačítko Ďalšia.Poznámka: Pre aktiváciu je potrebných najmenej 70 jednotiek inzulínu.
- Zásobník: %.2fJI
+ Zásobník: %.2f UZatiaľ nepripájajte Patch k telu.Stlačte tlačítko ihly do polovice. Potom stlačte tlačítko Ďalšia pre spustenie plnenia.Počkajte prosím na dokončenie plnenia.
diff --git a/pump/medtrum/src/main/res/values-vi-rVN/strings.xml b/pump/medtrum/src/main/res/values-vi-rVN/strings.xml
index 34b86cc5ab4..689530f9a1b 100644
--- a/pump/medtrum/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/medtrum/src/main/res/values-vi-rVN/strings.xml
@@ -3,28 +3,28 @@
MedtrumMT
- Tích hợp Pump cho Medtrum Nano và Medtrum 300U
- Cài đặt Pump Medtrum
- Lỗi Pump: %1$s !!
- Cảnh báo Pump: %1$s
- Pump đã tạm dừng
- Pump bị tạm dừng do vượt quá giới hạn insulin tối đa theo giờ
- Pump bị tạm dừng do vượt quá giới hạn insulin tối đa trong ngày
+ Tích hợp Bơm Medtrum Nano và Medtrum 300U
+ Cài đặt Bơm Medtrum
+ Lỗi Bơm: %1$s !!
+ Cảnh báo Bơm: %1$s
+ Bơm đã tạm dừng
+ Bơm bị tạm dừng do vượt quá giới hạn insulin tối đa theo giờ
+ Bơm bị tạm dừng do vượt quá giới hạn insulin tối đa trong ngàyPatch chưa được kích hoạt
- Thiết lập cài đặt người dùng cho Pump thất bại!
- Lỗi khi đồng bộ lịch sử từ Pump, một bản ghi đã bị bỏ qua. Kiểm tra tab Treatment để xem bolus đã được đồng bộ chính xác chưa. Tạm bỏ qua, và nếu lỗi tiếp tục xuất hiện, hãy thay Patch hoặc PumpBase.
+ Thiết lập cài đặt người dùng cho Bơm thất bại!
+ Lỗi khi đồng bộ lịch sử từ Bơm, một bản ghi đã bị bỏ qua. Kiểm tra tab Điều trị để xem bolus đã được đồng bộ chính xác chưa. Tạm bỏ qua, và nếu lỗi tiếp tục xuất hiện, hãy thay Patch hoặc PumpBase.Trạng thái BLEKết nối trướcĐang tiêm Bolus
- Trạng thái Pump
+ Trạng thái BơmBật cảnh báo %.2f U %.2f V
- Kiểu basal
- Tỷ lệ liều Basal
+ Kiểu liều nền
+ Tỷ lệ liều nền %.2f U/h
- Loại Pump
+ Loại BơmPhiên bản FWPatch noPatch hết hạn
@@ -36,9 +36,9 @@
Không kích hoạtKhông
- Pin Pump yếu
- Pump sắp hết insulin
- Pump sắp hết hạn
+ Pin Bơm yếu
+ Bơm sắp hết insulin
+ Bơm sắp hết hạnTạm dừng do đường huyết thấpTạm ngừng do đường huyết thấp (2)Đã tự động tạm dừng
@@ -46,7 +46,7 @@
tạm dừng tối đa theo ngàyBị tạm dừngĐã tạm dừng
- Tắc insulin
+ Tắc nghẽnĐã hết hạnHết insulinLỗi Patch
@@ -61,9 +61,9 @@
Bỏ quaKích hoạt PatchKết nối và nạp insulin
- Mồi pump
+ Mồi BơmĐang mồi
- Hoàn thành mồi pump
+ Hoàn thành mồi BơmGắn PatchĐang kích hoạt...Kích hoạt hoàn tất
@@ -72,22 +72,22 @@
Đã hủy kích hoạt PatchĐang kích hoạtTrạng thái không mong đợi: %1$s
- Chưa chọn cấu hình. Vui lòng chọn cấu hình và thử lại.
+ Chưa chọn Hồ sơ. Vui lòng chọn Hồ sơ và thử lại.Chưa biết số serial. Vui lòng nhập số serial của pumpbase trong cài đặt và thử lại.Số serial Pump Base: %1$XChưa có patch đang hoạt động. Nhấn Tiếp theo để bắt đầu quá trình kích hoạt.Không được kết nối Pump Base với patch cho đến bước tiếp theo!Kết nối pump base với Patch mới, loại bỏ bọt khí và nạp insulin, rồi nhấn Tiếp theo.Lưu ý: Cần ít nhất 70 đơn vị insulin để kích hoạt.
- Insulin còn: %.2f U
+ Bình chứa: %.2f UChưa gắn Patch lên cơ thể lúc này.
- Nhấn nhẹ nút kim (nửa chừng). Sau đó bấm Tiếp theo để bắt đầu mồi insulin.
+ Nhấn nửa nút kim, rồi chạm Tiếp tục để bắt đầu mồi insulin.Vui lòng chờ cho quá trình xả mồi insulin hoàn tất.Mồi insulin thất bại, nhấn Thử lại để thử lại.Nhấn Tiếp theo để tiếp tục.Nhấn Tiếp theo để bắt đầu kích hoạt.Tháo khóa an toàn. Gắn pump lên cơ thể. Nhấn nút kim.
- Đang kích hoạt pump và cài đặt tốc độ insulin nền ban đầu. Vui lòng chờ.
+ Đang kích hoạt Bơm và cài đặt liều nền. Vui lòng chờ.Kích hoạt thất bại, nhấn Thử lại để thử lại.Patch mới đã được kích hoạt. Còn lại %.2f đơn vị.Bạn có thể xuất cài đặt để khôi phục lại phiên Patch này sau.
@@ -103,39 +103,39 @@
Nhấn ĐỒNG Ý để quay về màn hình chính. Nhấn Tiếp theo để bắt đầu kích hoạt Patch mới.Rất tiếc! Đã xảy ra lỗi, có vẻ như một quá trình kích hoạt khác đang diễn ra.Nhấn Tiếp theo để tiếp tục kích hoạt hoặc Bỏ qua để đặt lại trạng thái kích hoạt.
- Vui lòng chờ, đang đọc trạng thái kích hoạt từ pump.
+ Vui lòng chờ, đang đọc trạng thái kích hoạt từ Bơm.Cảnh báo không thể kết nối đã được buộc bật, vì Patch Medtrum có thể gặp lỗi và trở nên không thể kết nối.Khuyến nghị đặt là 30 phút, vì Patch Medtrum có thể gặp lỗi và trở nên không thể kết nối.Số sê-riNhập số sê-ri của pump base của bạn.Số sê-ri không hợp lệ!
- Pump chưa được kiểm thử: %1$s! Vui lòng liên hệ với chúng tôi trên Discord hoặc GitHub để được hỗ trợ
+ Bơm chưa được kiểm thử: %1$s! Vui lòng liên hệ với chúng tôi trên Discord hoặc GitHub để được hỗ trợCài đặt cảnh báo
- Chọn cài đặt báo động pump mà bạn muốn.
- Thông báo khi có cảnh báo từ pump
- Hiển thị thông báo cho các cảnh báo không nghiêm trọng từ pump: pin yếu, lượng insulin còn ít (20 đơn vị) và sắp hết hạn. Khuyến nghị nên để bật khi báo động của pump được đặt ở chế độ im lặng.
- Cảnh báo pump hết hạn [giờ]
+ Chọn cài đặt báo động Bơm mà bạn muốn.
+ Thông báo khi có cảnh báo từ Bơm
+ Hiển thị thông báo cho các cảnh báo không nghiêm trọng từ Bơm: pin yếu, lượng insulin còn ít (20 đơn vị) và sắp hết hạn. Khuyến nghị nên để bật khi báo động của Bơm được đặt ở chế độ im lặng.
+ Cảnh báo Bơm hết hạn [giờ]Hiển thị thông báo vào giờ được chỉ định sau khi kích hoạt.Patch hết hạnKhi bật, Patch sẽ hết hạn sau 3 ngày, với thời gian gia hạn thêm 8 giờ sau đó.Lượng insulin tối đa theo giờ [đơn vị]
- Chỉ định lượng insulin tối đa được phép trong mỗi giờ. Nếu vượt quá, pump sẽ tạm ngừng.
+ Chỉ định lượng insulin tối đa được phép trong mỗi giờ. Nếu vượt quá, Bơm sẽ tạm ngừng.Lượng insulin tối đa theo ngày [đơn vị]Chỉ định lượng insulin tối đa được phép trong mỗi ngày. Nếu vượt quá, pump sẽ tạm ngừng.Quét khi lỗi kết nốiCảnh báo: Chỉ nên bật nếu gặp lỗi kết nối. Khi bật, hệ thống sẽ quét lại bơm trước khi thử kết nối lại. Đảm bảo rằng quyền Vị trí được đặt thành \"Luôn cho phép\"
- Đang cập nhật trạng thái pump
+ Đang cập nhật trạng thái BơmĐang đồng bộ dữ liệu, còn lại %1$d mụcĐang cập nhật trạng thái liều bolusĐang cập nhật trạng thái liều basal tạm thờiCài đặt các tùy chọn cá nhânLiều Bolus bị hủy bởi người dùng
- Pump đã ngắt kết nối
+ Bơm đã ngắt kết nốiĐang thực hiện liều BolusKhông thể gửi lệnh bolusHết thời gian chờ khi lấy trạng thái bolus
- Pump lỗi
+ Bơm lỗi
diff --git a/pump/omnipod/common/build.gradle.kts b/pump/omnipod/common/build.gradle.kts
index 09e64b242a9..fecf9491f70 100644
--- a/pump/omnipod/common/build.gradle.kts
+++ b/pump/omnipod/common/build.gradle.kts
@@ -12,6 +12,7 @@ android {
}
dependencies {
+ implementation(project(":core:data"))
implementation(project(":core:interfaces"))
implementation(project(":core:keys"))
implementation(project(":core:libraries"))
@@ -25,4 +26,4 @@ dependencies {
ksp(libs.com.google.dagger.compiler)
ksp(libs.com.google.dagger.android.processor)
-}
\ No newline at end of file
+}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/EventOmnipodDashPumpValuesChanged.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/EventOmnipodDashPumpValuesChanged.kt
similarity index 72%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/EventOmnipodDashPumpValuesChanged.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/EventOmnipodDashPumpValuesChanged.kt
index 8b0bcaf3152..99c80f839e4 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/EventOmnipodDashPumpValuesChanged.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/EventOmnipodDashPumpValuesChanged.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash
+package app.aaps.pump.omnipod.common
import app.aaps.core.interfaces.rx.events.Event
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/Id.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/Id.kt
similarity index 96%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/Id.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/Id.kt
index d5ba0b0360c..66f9ddad94f 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/Id.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/Id.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm
+package app.aaps.pump.omnipod.common.bledriver.comm
import app.aaps.core.utils.toHex
import java.nio.ByteBuffer
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/Ids.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/Ids.kt
similarity index 59%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/Ids.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/Ids.kt
index 9ee07123380..f60b26ba43c 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/Ids.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/Ids.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm
+package app.aaps.pump.omnipod.common.bledriver.comm
-import app.aaps.pump.omnipod.dash.driver.comm.scan.PodScanner
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.comm.scan.PodScanner
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
class Ids(podState: OmnipodDashPodStateManager) {
@@ -14,8 +14,7 @@ class Ids(podState: OmnipodDashPodStateManager) {
fun notActivated(): Id {
return Id.fromLong(
- PodScanner
- .POD_ID_NOT_ACTIVATED
+ PodScanner.POD_ID_NOT_ACTIVATED
)
}
}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/OmnipodDashBleManager.kt
similarity index 61%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/OmnipodDashBleManager.kt
index 26eb4962a31..1cc91c24688 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/OmnipodDashBleManager.kt
@@ -1,10 +1,10 @@
-package app.aaps.pump.omnipod.dash.driver.comm
+package app.aaps.pump.omnipod.common.bledriver.comm
-import app.aaps.pump.omnipod.dash.driver.comm.session.Connection
-import app.aaps.pump.omnipod.dash.driver.comm.session.ConnectionState
-import app.aaps.pump.omnipod.dash.driver.event.PodEvent
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.Command
-import app.aaps.pump.omnipod.dash.driver.pod.response.Response
+import app.aaps.pump.omnipod.common.bledriver.comm.session.Connection
+import app.aaps.pump.omnipod.common.bledriver.comm.session.ConnectionState
+import app.aaps.pump.omnipod.common.bledriver.event.PodEvent
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.Command
+import app.aaps.pump.omnipod.common.bledriver.pod.response.Response
import io.reactivex.rxjava3.core.Observable
import java.util.concurrent.CountDownLatch
import kotlin.reflect.KClass
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/OmnipodDashBleManagerImpl.kt
similarity index 84%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/OmnipodDashBleManagerImpl.kt
index 6c25569deb8..6e477f8fb0f 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/OmnipodDashBleManagerImpl.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm
+package app.aaps.pump.omnipod.common.bledriver.comm
import android.Manifest
import android.bluetooth.BluetoothAdapter
@@ -13,32 +13,32 @@ import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.keys.interfaces.Preferences
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.BusyException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ConnectException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendCommandException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.NotConnectedException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.SessionEstablishmentException
-import app.aaps.pump.omnipod.dash.driver.comm.pair.LTKExchanger
-import app.aaps.pump.omnipod.dash.driver.comm.scan.PodScanner
-import app.aaps.pump.omnipod.dash.driver.comm.session.CommandAckError
-import app.aaps.pump.omnipod.dash.driver.comm.session.CommandReceiveError
-import app.aaps.pump.omnipod.dash.driver.comm.session.CommandReceiveSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.session.CommandSendErrorConfirming
-import app.aaps.pump.omnipod.dash.driver.comm.session.CommandSendErrorSending
-import app.aaps.pump.omnipod.dash.driver.comm.session.CommandSendSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.session.Connected
-import app.aaps.pump.omnipod.dash.driver.comm.session.Connection
-import app.aaps.pump.omnipod.dash.driver.comm.session.ConnectionState
-import app.aaps.pump.omnipod.dash.driver.comm.session.ConnectionWaitCondition
-import app.aaps.pump.omnipod.dash.driver.comm.session.NotConnected
-import app.aaps.pump.omnipod.dash.driver.comm.session.Session
-import app.aaps.pump.omnipod.dash.driver.event.PodEvent
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.Command
-import app.aaps.pump.omnipod.dash.driver.pod.response.Response
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
-import app.aaps.pump.omnipod.dash.keys.DashBooleanPreferenceKey
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.BusyException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ConnectException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.CouldNotSendCommandException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.FailedToConnectException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.MessageIOException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.NotConnectedException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.SessionEstablishmentException
+import app.aaps.pump.omnipod.common.bledriver.comm.pair.LTKExchanger
+import app.aaps.pump.omnipod.common.bledriver.comm.scan.PodScanner
+import app.aaps.pump.omnipod.common.bledriver.comm.session.CommandAckError
+import app.aaps.pump.omnipod.common.bledriver.comm.session.CommandReceiveError
+import app.aaps.pump.omnipod.common.bledriver.comm.session.CommandReceiveSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.session.CommandSendErrorConfirming
+import app.aaps.pump.omnipod.common.bledriver.comm.session.CommandSendErrorSending
+import app.aaps.pump.omnipod.common.bledriver.comm.session.CommandSendSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.session.Connected
+import app.aaps.pump.omnipod.common.bledriver.comm.session.Connection
+import app.aaps.pump.omnipod.common.bledriver.comm.session.ConnectionState
+import app.aaps.pump.omnipod.common.bledriver.comm.session.ConnectionWaitCondition
+import app.aaps.pump.omnipod.common.bledriver.comm.session.NotConnected
+import app.aaps.pump.omnipod.common.bledriver.comm.session.Session
+import app.aaps.pump.omnipod.common.bledriver.event.PodEvent
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.Command
+import app.aaps.pump.omnipod.common.bledriver.pod.response.Response
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.keys.DashBooleanPreferenceKey
import io.reactivex.rxjava3.core.Observable
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicBoolean
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/ServiceDiscoverer.kt
similarity index 81%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/ServiceDiscoverer.kt
index c704d23c1f1..991c637ff89 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/ServiceDiscoverer.kt
@@ -1,16 +1,16 @@
-package app.aaps.pump.omnipod.dash.driver.comm
+package app.aaps.pump.omnipod.common.bledriver.comm
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
-import app.aaps.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ConnectException
-import app.aaps.pump.omnipod.dash.driver.comm.io.CharacteristicType
-import app.aaps.pump.omnipod.dash.driver.comm.session.Connected
-import app.aaps.pump.omnipod.dash.driver.comm.session.Connection
-import app.aaps.pump.omnipod.dash.driver.comm.session.Connection.Companion.STOP_CONNECTING_CHECK_INTERVAL_MS
-import app.aaps.pump.omnipod.dash.driver.comm.session.ConnectionWaitCondition
+import app.aaps.pump.omnipod.common.bledriver.comm.callbacks.BleCommCallbacks
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ConnectException
+import app.aaps.pump.omnipod.common.bledriver.comm.io.CharacteristicType
+import app.aaps.pump.omnipod.common.bledriver.comm.session.Connected
+import app.aaps.pump.omnipod.common.bledriver.comm.session.Connection
+import app.aaps.pump.omnipod.common.bledriver.comm.session.Connection.Companion.STOP_CONNECTING_CHECK_INTERVAL_MS
+import app.aaps.pump.omnipod.common.bledriver.comm.session.ConnectionWaitCondition
import java.math.BigInteger
import java.util.UUID
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/callbacks/BleCommCallbacks.kt
similarity index 96%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/callbacks/BleCommCallbacks.kt
index 67fa0f0c2cc..9c70a04873d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/callbacks/BleCommCallbacks.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.callbacks
+package app.aaps.pump.omnipod.common.bledriver.comm.callbacks
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
@@ -8,9 +8,9 @@ import android.bluetooth.BluetoothProfile
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.io.CharacteristicType.Companion.byValue
-import app.aaps.pump.omnipod.dash.driver.comm.io.IncomingPackets
-import app.aaps.pump.omnipod.dash.driver.comm.session.DisconnectHandler
+import app.aaps.pump.omnipod.common.bledriver.comm.io.CharacteristicType.Companion.byValue
+import app.aaps.pump.omnipod.common.bledriver.comm.io.IncomingPackets
+import app.aaps.pump.omnipod.common.bledriver.comm.session.DisconnectHandler
import java.util.UUID
import java.util.concurrent.BlockingQueue
import java.util.concurrent.CountDownLatch
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/callbacks/WriteConfirmation.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/callbacks/WriteConfirmation.kt
similarity index 79%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/callbacks/WriteConfirmation.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/callbacks/WriteConfirmation.kt
index 890d8538dd9..ef906bdeea4 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/callbacks/WriteConfirmation.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/callbacks/WriteConfirmation.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.callbacks
+package app.aaps.pump.omnipod.common.bledriver.comm.callbacks
sealed class WriteConfirmation
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/command/BleCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/command/BleCommand.kt
similarity index 98%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/command/BleCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/command/BleCommand.kt
index f17fff2fe38..cd9c654a890 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/command/BleCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/command/BleCommand.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.command
+package app.aaps.pump.omnipod.common.bledriver.comm.command
import app.aaps.core.utils.toHex
import java.nio.ByteBuffer
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/command/BleCommandType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/command/BleCommandType.kt
similarity index 89%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/command/BleCommandType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/command/BleCommandType.kt
index 1124f7ded09..76e137311b1 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/command/BleCommandType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/command/BleCommandType.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.command
+package app.aaps.pump.omnipod.common.bledriver.comm.command
enum class BleCommandType(val value: Byte) {
RTS(0x00.toByte()),
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/endecrypt/EnDecrypt.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/EnDecrypt.kt
similarity index 94%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/endecrypt/EnDecrypt.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/EnDecrypt.kt
index 4fcdfd9465c..9f495b5a7e8 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/endecrypt/EnDecrypt.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/EnDecrypt.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.comm.endecrypt
+package app.aaps.pump.omnipod.common.bledriver.comm.endecrypt
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessagePacket
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessagePacket
import org.spongycastle.crypto.engines.AESEngine
import org.spongycastle.crypto.modes.CCMBlockCipher
import org.spongycastle.crypto.params.AEADParameters
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/endecrypt/Nonce.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/Nonce.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/endecrypt/Nonce.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/Nonce.kt
index 7a15b348934..29f3283c1c4 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/endecrypt/Nonce.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/Nonce.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.endecrypt
+package app.aaps.pump.omnipod.common.bledriver.comm.endecrypt
import java.nio.ByteBuffer
diff --git a/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/BusyException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/BusyException.kt
new file mode 100644
index 00000000000..e9f1e6a6d07
--- /dev/null
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/BusyException.kt
@@ -0,0 +1,3 @@
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
+
+class BusyException : Exception("Bluetooth busy")
diff --git a/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ConnectException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ConnectException.kt
new file mode 100644
index 00000000000..d023da96bfc
--- /dev/null
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ConnectException.kt
@@ -0,0 +1,3 @@
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
+
+class ConnectException(val msg: String) : Exception(msg)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotParseMessageException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotParseMessageException.kt
similarity index 72%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotParseMessageException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotParseMessageException.kt
index f1e01dfe93c..4e27f5bdefb 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotParseMessageException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotParseMessageException.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
import app.aaps.core.utils.toHex
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotParseResponseException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotParseResponseException.kt
similarity index 55%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotParseResponseException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotParseResponseException.kt
index 70e4cace49a..b694426e16e 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotParseResponseException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotParseResponseException.kt
@@ -1,3 +1,3 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
class CouldNotParseResponseException(message: String?) : Exception(message)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendCommandException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotSendCommandException.kt
similarity index 60%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendCommandException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotSendCommandException.kt
index b062ea7201a..2ce639a62fc 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendCommandException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/CouldNotSendCommandException.kt
@@ -1,3 +1,3 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
class CouldNotSendCommandException(val msg: String = "Could not send command") : Exception(msg)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/FailedToConnectException.kt
similarity index 64%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/FailedToConnectException.kt
index 895f638ace4..119a70b4eee 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/FailedToConnectException.kt
@@ -1,3 +1,3 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
open class FailedToConnectException(message: String? = null) : Exception("Failed to connect: ${message ?: ""}")
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/MessageIOException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/MessageIOException.kt
similarity index 57%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/MessageIOException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/MessageIOException.kt
index d2df62c289f..7a451d81c4a 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/MessageIOException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/MessageIOException.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
class MessageIOException : Exception {
constructor(msg: String) : super(msg)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/NotConnectedException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/NotConnectedException.kt
similarity index 50%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/NotConnectedException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/NotConnectedException.kt
index 96b294c2ddd..29e90b28202 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/NotConnectedException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/NotConnectedException.kt
@@ -1,3 +1,3 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
class NotConnectedException(val msg: String) : Exception(msg)
diff --git a/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/PairingException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/PairingException.kt
new file mode 100644
index 00000000000..51b6f200413
--- /dev/null
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/PairingException.kt
@@ -0,0 +1,3 @@
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
+
+class PairingException(val msg: String) : Exception(msg)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ScanException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ScanException.kt
similarity index 71%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ScanException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ScanException.kt
index ef77a34dbf1..8880f8fd004 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ScanException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ScanException.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
open class ScanException : Exception {
constructor(message: String) : super(message)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ScanFailFoundTooManyException.kt
similarity index 69%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ScanFailFoundTooManyException.kt
index 27ba104a050..0d17b7d7b5a 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/ScanFailFoundTooManyException.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
-import app.aaps.pump.omnipod.dash.driver.comm.scan.BleDiscoveredDevice
+import app.aaps.pump.omnipod.common.bledriver.comm.scan.BleDiscoveredDevice
import java.util.*
class ScanFailFoundTooManyException(devices: List) : ScanException("Found more than one Pod") {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/SessionEstablishmentException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/SessionEstablishmentException.kt
similarity index 52%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/SessionEstablishmentException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/SessionEstablishmentException.kt
index bb13f6dc276..2a33681b0c6 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/SessionEstablishmentException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/exceptions/SessionEstablishmentException.kt
@@ -1,3 +1,3 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
+package app.aaps.pump.omnipod.common.bledriver.comm.exceptions
class SessionEstablishmentException(val msg: String) : Exception(msg)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/BleIO.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/BleIO.kt
similarity index 91%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/BleIO.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/BleIO.kt
index 9287979fde3..a93f9c52f17 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/BleIO.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/BleIO.kt
@@ -1,6 +1,6 @@
@file:Suppress("WildcardImport")
-package app.aaps.pump.omnipod.dash.driver.comm.io
+package app.aaps.pump.omnipod.common.bledriver.comm.io
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
@@ -8,11 +8,11 @@ import android.bluetooth.BluetoothGattDescriptor
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks
-import app.aaps.pump.omnipod.dash.driver.comm.callbacks.WriteConfirmationError
-import app.aaps.pump.omnipod.dash.driver.comm.callbacks.WriteConfirmationSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandRTS
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ConnectException
+import app.aaps.pump.omnipod.common.bledriver.comm.callbacks.BleCommCallbacks
+import app.aaps.pump.omnipod.common.bledriver.comm.callbacks.WriteConfirmationError
+import app.aaps.pump.omnipod.common.bledriver.comm.callbacks.WriteConfirmationSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandRTS
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ConnectException
import java.util.concurrent.BlockingQueue
import java.util.concurrent.TimeUnit
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/CharacteristicType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/CharacteristicType.kt
similarity index 92%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/CharacteristicType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/CharacteristicType.kt
index 5c5f6fb749e..5533d28d960 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/CharacteristicType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/CharacteristicType.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.io
+package app.aaps.pump.omnipod.common.bledriver.comm.io
import java.math.BigInteger
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/CmdBleIO.kt
similarity index 78%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/CmdBleIO.kt
index 498c1d6507e..ee8f8332a71 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/CmdBleIO.kt
@@ -1,12 +1,12 @@
-package app.aaps.pump.omnipod.dash.driver.comm.io
+package app.aaps.pump.omnipod.common.bledriver.comm.io
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import app.aaps.core.interfaces.logging.AAPSLogger
-import app.aaps.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl
-import app.aaps.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommand
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandHello
+import app.aaps.pump.omnipod.common.bledriver.comm.OmnipodDashBleManagerImpl
+import app.aaps.pump.omnipod.common.bledriver.comm.callbacks.BleCommCallbacks
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommand
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandHello
import java.util.concurrent.BlockingQueue
sealed class BleConfirmResult
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/DataBleIO.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/DataBleIO.kt
similarity index 79%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/DataBleIO.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/DataBleIO.kt
index a125ed2dd62..7db49d0a29d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/DataBleIO.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/DataBleIO.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.comm.io
+package app.aaps.pump.omnipod.common.bledriver.comm.io
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import app.aaps.core.interfaces.logging.AAPSLogger
-import app.aaps.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks
+import app.aaps.pump.omnipod.common.bledriver.comm.callbacks.BleCommCallbacks
import java.util.concurrent.BlockingQueue
class DataBleIO(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/IncomingPackets.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/IncomingPackets.kt
similarity index 89%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/IncomingPackets.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/IncomingPackets.kt
index 726b0efc9ec..494f56cd0a6 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/io/IncomingPackets.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/io/IncomingPackets.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.io
+package app.aaps.pump.omnipod.common.bledriver.comm.io
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingDeque
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/CrcMismatchException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/CrcMismatchException.kt
similarity index 78%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/CrcMismatchException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/CrcMismatchException.kt
index 97f65079278..fbec16dddab 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/CrcMismatchException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/CrcMismatchException.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/IncorrectPacketException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/IncorrectPacketException.kt
similarity index 77%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/IncorrectPacketException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/IncorrectPacketException.kt
index 5cf53803e7a..a1e9ea24db4 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/IncorrectPacketException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/IncorrectPacketException.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessageIO.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessageIO.kt
similarity index 86%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessageIO.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessageIO.kt
index 54e356435e3..c45b7dd790f 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessageIO.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessageIO.kt
@@ -1,27 +1,27 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommand
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandAbort
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandCTS
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandFail
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandNack
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandRTS
-import app.aaps.pump.omnipod.dash.driver.comm.command.BleCommandSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.io.BleConfirmError
-import app.aaps.pump.omnipod.dash.driver.comm.io.BleConfirmIncorrectData
-import app.aaps.pump.omnipod.dash.driver.comm.io.BleConfirmSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.io.BleSendErrorConfirming
-import app.aaps.pump.omnipod.dash.driver.comm.io.BleSendErrorSending
-import app.aaps.pump.omnipod.dash.driver.comm.io.BleSendResult
-import app.aaps.pump.omnipod.dash.driver.comm.io.BleSendSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.io.CmdBleIO
-import app.aaps.pump.omnipod.dash.driver.comm.io.DataBleIO
-import app.aaps.pump.omnipod.dash.driver.comm.packet.BlePacket
-import app.aaps.pump.omnipod.dash.driver.comm.packet.PayloadJoiner
-import app.aaps.pump.omnipod.dash.driver.comm.packet.PayloadSplitter
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommand
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandAbort
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandCTS
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandFail
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandNack
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandRTS
+import app.aaps.pump.omnipod.common.bledriver.comm.command.BleCommandSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.io.BleConfirmError
+import app.aaps.pump.omnipod.common.bledriver.comm.io.BleConfirmIncorrectData
+import app.aaps.pump.omnipod.common.bledriver.comm.io.BleConfirmSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.io.BleSendErrorConfirming
+import app.aaps.pump.omnipod.common.bledriver.comm.io.BleSendErrorSending
+import app.aaps.pump.omnipod.common.bledriver.comm.io.BleSendResult
+import app.aaps.pump.omnipod.common.bledriver.comm.io.BleSendSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.io.CmdBleIO
+import app.aaps.pump.omnipod.common.bledriver.comm.io.DataBleIO
+import app.aaps.pump.omnipod.common.bledriver.comm.packet.BlePacket
+import app.aaps.pump.omnipod.common.bledriver.comm.packet.PayloadJoiner
+import app.aaps.pump.omnipod.common.bledriver.comm.packet.PayloadSplitter
sealed class MessageSendResult
object MessageSendSuccess : MessageSendResult()
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessagePacket.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessagePacket.kt
similarity index 94%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessagePacket.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessagePacket.kt
index 0ceeb6a21d3..4540e3370ed 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessagePacket.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessagePacket.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
-import app.aaps.pump.omnipod.dash.driver.comm.Id
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.CouldNotParseMessageException
-import app.aaps.pump.omnipod.dash.util.Flag
+import app.aaps.pump.omnipod.common.bledriver.comm.Id
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.CouldNotParseMessageException
+import app.aaps.pump.omnipod.common.bledriver.util.Flag
import java.nio.ByteBuffer
/***
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessageType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessageType.kt
similarity index 85%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessageType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessageType.kt
index 15c2069820b..1674f9682eb 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/MessageType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessageType.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
enum class MessageType(val value: Byte) {
CLEAR(0),
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncoding.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/StringLengthPrefixEncoding.kt
similarity index 94%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncoding.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/StringLengthPrefixEncoding.kt
index 1344f8d6e71..3e74287a2a5 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncoding.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/StringLengthPrefixEncoding.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.MessageIOException
import java.nio.ByteBuffer
/***
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/BlePacket.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/BlePacket.kt
similarity index 97%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/BlePacket.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/BlePacket.kt
index 4657b6ca09d..8c26214d4b8 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/BlePacket.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/BlePacket.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.comm.packet
+package app.aaps.pump.omnipod.common.bledriver.comm.packet
-import app.aaps.pump.omnipod.dash.driver.comm.message.IncorrectPacketException
+import app.aaps.pump.omnipod.common.bledriver.comm.message.IncorrectPacketException
import java.nio.ByteBuffer
sealed class BlePacket {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/PayloadJoiner.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/PayloadJoiner.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/PayloadJoiner.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/PayloadJoiner.kt
index 2b99eac44af..eb527ff5648 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/PayloadJoiner.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/PayloadJoiner.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm.packet
+package app.aaps.pump.omnipod.common.bledriver.comm.packet
-import app.aaps.pump.omnipod.dash.driver.comm.message.CrcMismatchException
-import app.aaps.pump.omnipod.dash.driver.comm.message.IncorrectPacketException
+import app.aaps.pump.omnipod.common.bledriver.comm.message.CrcMismatchException
+import app.aaps.pump.omnipod.common.bledriver.comm.message.IncorrectPacketException
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/PayloadSplitter.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/PayloadSplitter.kt
similarity index 96%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/PayloadSplitter.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/PayloadSplitter.kt
index d24dfc8075b..01f5382fad6 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/packet/PayloadSplitter.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/packet/PayloadSplitter.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.comm.packet
+package app.aaps.pump.omnipod.common.bledriver.comm.packet
import java.lang.Integer.min
import java.util.zip.CRC32
-internal class PayloadSplitter(private val payload: ByteArray) {
+class PayloadSplitter(private val payload: ByteArray) {
fun splitInPackets(): List {
if (payload.size <= FirstBlePacket.CAPACITY_WITH_THE_OPTIONAL_PLUS_ONE_PACKET) {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/KeyExchange.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/KeyExchange.kt
similarity index 94%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/KeyExchange.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/KeyExchange.kt
index 3a6371cdbb3..23614252fce 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/KeyExchange.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/KeyExchange.kt
@@ -1,12 +1,12 @@
-package app.aaps.pump.omnipod.dash.driver.comm.pair
+package app.aaps.pump.omnipod.common.bledriver.comm.pair
import app.aaps.core.interfaces.configuration.Config
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
-import app.aaps.pump.omnipod.dash.driver.pod.util.RandomByteGenerator
-import app.aaps.pump.omnipod.dash.driver.pod.util.X25519KeyGenerator
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.MessageIOException
+import app.aaps.pump.omnipod.common.bledriver.pod.util.RandomByteGenerator
+import app.aaps.pump.omnipod.common.bledriver.pod.util.X25519KeyGenerator
import org.spongycastle.crypto.engines.AESEngine
import org.spongycastle.crypto.macs.CMac
import org.spongycastle.crypto.params.KeyParameter
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/LTKExchanger.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/LTKExchanger.kt
similarity index 86%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/LTKExchanger.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/LTKExchanger.kt
index cbf63905ab7..be0207a7ce7 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/LTKExchanger.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/LTKExchanger.kt
@@ -1,19 +1,19 @@
-package app.aaps.pump.omnipod.dash.driver.comm.pair
+package app.aaps.pump.omnipod.common.bledriver.comm.pair
import app.aaps.core.interfaces.configuration.Config
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.hexStringToByteArray
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.Ids
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.PairingException
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageIO
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessagePacket
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageSendSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys
-import app.aaps.pump.omnipod.dash.driver.pod.util.RandomByteGenerator
-import app.aaps.pump.omnipod.dash.driver.pod.util.X25519KeyGenerator
+import app.aaps.pump.omnipod.common.bledriver.comm.Ids
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.MessageIOException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.PairingException
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageIO
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessagePacket
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageSendSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys
+import app.aaps.pump.omnipod.common.bledriver.pod.util.RandomByteGenerator
+import app.aaps.pump.omnipod.common.bledriver.pod.util.X25519KeyGenerator
internal class LTKExchanger(
private val aapsLogger: AAPSLogger,
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/PairMessage.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/PairMessage.kt
similarity index 62%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/PairMessage.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/PairMessage.kt
index 9a1920d580f..3ee7984ad03 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/PairMessage.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/PairMessage.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.comm.pair
+package app.aaps.pump.omnipod.common.bledriver.comm.pair
-import app.aaps.pump.omnipod.dash.driver.comm.Id
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessagePacket
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageType
-import app.aaps.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding
+import app.aaps.pump.omnipod.common.bledriver.comm.Id
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessagePacket
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageType
+import app.aaps.pump.omnipod.common.bledriver.comm.message.StringLengthPrefixEncoding
class PairMessage(
val sequenceNumber: Byte,
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/PairResult.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/PairResult.kt
similarity index 78%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/PairResult.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/PairResult.kt
index 7f088bd11fb..cc5ce41c10c 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/PairResult.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/PairResult.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.pair
+package app.aaps.pump.omnipod.common.bledriver.comm.pair
import app.aaps.core.utils.toHex
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/BleDiscoveredDevice.kt
similarity index 98%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/BleDiscoveredDevice.kt
index cbb84079d2f..79119c0599a 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/BleDiscoveredDevice.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.scan
+package app.aaps.pump.omnipod.common.bledriver.comm.scan
import android.bluetooth.le.ScanRecord
import android.bluetooth.le.ScanResult
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/DiscoveredInvalidPodException.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/DiscoveredInvalidPodException.kt
similarity index 75%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/DiscoveredInvalidPodException.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/DiscoveredInvalidPodException.kt
index d1189b808b4..f9e1fbe04ef 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/DiscoveredInvalidPodException.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/DiscoveredInvalidPodException.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.scan
+package app.aaps.pump.omnipod.common.bledriver.comm.scan
import android.os.ParcelUuid
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/PodScanner.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/PodScanner.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/PodScanner.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/PodScanner.kt
index c1c48f51f24..ad19dad14c6 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/PodScanner.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/PodScanner.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.scan
+package app.aaps.pump.omnipod.common.bledriver.comm.scan
import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.ScanFilter
@@ -6,8 +6,8 @@ import android.bluetooth.le.ScanSettings
import android.os.ParcelUuid
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ScanException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ScanFailFoundTooManyException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ScanException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ScanFailFoundTooManyException
import java.util.Arrays
class PodScanner(private val logger: AAPSLogger, private val bluetoothAdapter: BluetoothAdapter) {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/ScanCollector.kt
similarity index 93%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/ScanCollector.kt
index 022f282556c..4f6bee2a471 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/scan/ScanCollector.kt
@@ -1,10 +1,10 @@
-package app.aaps.pump.omnipod.dash.driver.comm.scan
+package app.aaps.pump.omnipod.common.bledriver.comm.scan
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanResult
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ScanException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ScanException
import java.util.Collections
import java.util.concurrent.ConcurrentHashMap
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Connection.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Connection.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Connection.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Connection.kt
index f75017fc8a4..7173a02bccd 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Connection.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Connection.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
@@ -11,18 +11,18 @@ import app.aaps.core.interfaces.configuration.Config
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.Ids
-import app.aaps.pump.omnipod.dash.driver.comm.ServiceDiscoverer
-import app.aaps.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks
-import app.aaps.pump.omnipod.dash.driver.comm.endecrypt.EnDecrypt
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ConnectException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException
-import app.aaps.pump.omnipod.dash.driver.comm.io.CharacteristicType
-import app.aaps.pump.omnipod.dash.driver.comm.io.CmdBleIO
-import app.aaps.pump.omnipod.dash.driver.comm.io.DataBleIO
-import app.aaps.pump.omnipod.dash.driver.comm.io.IncomingPackets
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageIO
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.comm.Ids
+import app.aaps.pump.omnipod.common.bledriver.comm.ServiceDiscoverer
+import app.aaps.pump.omnipod.common.bledriver.comm.callbacks.BleCommCallbacks
+import app.aaps.pump.omnipod.common.bledriver.comm.endecrypt.EnDecrypt
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ConnectException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.FailedToConnectException
+import app.aaps.pump.omnipod.common.bledriver.comm.io.CharacteristicType
+import app.aaps.pump.omnipod.common.bledriver.comm.io.CmdBleIO
+import app.aaps.pump.omnipod.common.bledriver.comm.io.DataBleIO
+import app.aaps.pump.omnipod.common.bledriver.comm.io.IncomingPackets
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageIO
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import java.util.concurrent.CountDownLatch
sealed class ConnectionState
@@ -132,6 +132,8 @@ class Connection(
if (!closeGatt && gattConnection != null) {
// Disconnect first, then close gatt
gattConnection?.disconnect()
+ // Set connection state to DISCONNECTED immediately to prevent reconnection attempts
+ podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED
} else {
// Call with closeGatt=true only when ble is already disconnected or there is no connection
gattConnection?.close()
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/ConnectionStateChangeHandler.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/ConnectionStateChangeHandler.kt
similarity index 63%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/ConnectionStateChangeHandler.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/ConnectionStateChangeHandler.kt
index 67123b685e8..02bb76095f7 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/ConnectionStateChangeHandler.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/ConnectionStateChangeHandler.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
interface ConnectionStateChangeHandler {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/DisconnectHandler.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/DisconnectHandler.kt
similarity index 54%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/DisconnectHandler.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/DisconnectHandler.kt
index 7a6e67966b4..05df7be905d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/DisconnectHandler.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/DisconnectHandler.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
interface DisconnectHandler {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapAkaAttribute.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapAkaAttribute.kt
similarity index 98%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapAkaAttribute.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapAkaAttribute.kt
index b5906eaebeb..c8c3c11f8bd 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapAkaAttribute.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapAkaAttribute.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.MessageIOException
import java.util.LinkedList
enum class EapAkaAttributeType(val type: Byte) {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapMessage.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapMessage.kt
similarity index 95%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapMessage.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapMessage.kt
index 821e649e17f..c0feb0bda31 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapMessage.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapMessage.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.MessageIOException
import java.nio.ByteBuffer
@Suppress("unused")
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapSqn.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapSqn.kt
similarity index 92%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapSqn.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapSqn.kt
index 7b1ded5dd16..860ce390ff2 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/EapSqn.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapSqn.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import java.nio.ByteBuffer
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Milenage.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Milenage.kt
similarity index 98%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Milenage.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Milenage.kt
index 9815bfb617a..18666cc7f30 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Milenage.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Milenage.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import android.annotation.SuppressLint
import app.aaps.core.interfaces.configuration.Config
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/ResponseUtil.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/ResponseUtil.kt
similarity index 91%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/ResponseUtil.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/ResponseUtil.kt
index 1491b038baa..8c9ac6e3a4f 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/ResponseUtil.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/ResponseUtil.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.CouldNotParseResponseException
-import app.aaps.pump.omnipod.dash.driver.pod.response.*
-import app.aaps.pump.omnipod.dash.driver.pod.util.byValue
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.CouldNotParseResponseException
+import app.aaps.pump.omnipod.common.bledriver.pod.response.*
+import app.aaps.pump.omnipod.common.bledriver.pod.util.byValue
object ResponseUtil {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Session.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Session.kt
similarity index 83%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Session.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Session.kt
index bb98b76fe93..54035701a1e 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/Session.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/Session.kt
@@ -1,21 +1,21 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.Ids
-import app.aaps.pump.omnipod.dash.driver.comm.endecrypt.EnDecrypt
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.CouldNotParseResponseException
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageIO
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessagePacket
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageSendErrorConfirming
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageSendErrorSending
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageSendSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageType
-import app.aaps.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding
-import app.aaps.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.Command
-import app.aaps.pump.omnipod.dash.driver.pod.response.Response
+import app.aaps.pump.omnipod.common.bledriver.comm.Ids
+import app.aaps.pump.omnipod.common.bledriver.comm.endecrypt.EnDecrypt
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.CouldNotParseResponseException
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageIO
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessagePacket
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageSendErrorConfirming
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageSendErrorSending
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageSendSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageType
+import app.aaps.pump.omnipod.common.bledriver.comm.message.StringLengthPrefixEncoding
+import app.aaps.pump.omnipod.common.bledriver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.Command
+import app.aaps.pump.omnipod.common.bledriver.pod.response.Response
sealed class CommandSendResult
object CommandSendSuccess : CommandSendResult()
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/SessionEstablisher.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/SessionEstablisher.kt
similarity index 92%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/SessionEstablisher.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/SessionEstablisher.kt
index 4ffd04b8f84..47d0da2d4b3 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/SessionEstablisher.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/SessionEstablisher.kt
@@ -1,16 +1,16 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import app.aaps.core.interfaces.configuration.Config
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.Ids
-import app.aaps.pump.omnipod.dash.driver.comm.endecrypt.Nonce
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.SessionEstablishmentException
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageIO
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessagePacket
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageSendSuccess
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessageType
+import app.aaps.pump.omnipod.common.bledriver.comm.Ids
+import app.aaps.pump.omnipod.common.bledriver.comm.endecrypt.Nonce
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.SessionEstablishmentException
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageIO
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessagePacket
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageSendSuccess
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessageType
import java.security.SecureRandom
class SessionEstablisher(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/SessionKeys.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/SessionKeys.kt
similarity index 76%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/SessionKeys.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/SessionKeys.kt
index 12dafee152a..ba46be6c65e 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/session/SessionKeys.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/SessionKeys.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
-import app.aaps.pump.omnipod.dash.driver.comm.endecrypt.Nonce
+import app.aaps.pump.omnipod.common.bledriver.comm.endecrypt.Nonce
sealed class SessionNegotiationResponse
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/event/PodEvent.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/event/PodEvent.kt
similarity index 87%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/event/PodEvent.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/event/PodEvent.kt
index a203bf46d46..e460105adfc 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/event/PodEvent.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/event/PodEvent.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.event
+package app.aaps.pump.omnipod.common.bledriver.event
-import app.aaps.pump.omnipod.dash.driver.comm.Id
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.Command
-import app.aaps.pump.omnipod.dash.driver.pod.response.Response
+import app.aaps.pump.omnipod.common.bledriver.comm.Id
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.Command
+import app.aaps.pump.omnipod.common.bledriver.pod.response.Response
sealed class PodEvent {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/DeactivateCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/DeactivateCommand.kt
similarity index 81%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/DeactivateCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/DeactivateCommand.kt
index cbfcd707651..d799abf71e8 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/DeactivateCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/DeactivateCommand.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.NonceEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
import java.nio.ByteBuffer
class DeactivateCommand private constructor(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/GetStatusCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetStatusCommand.kt
similarity index 78%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/GetStatusCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetStatusCommand.kt
index dc201abe1e3..7dabd5fac03 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/GetStatusCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetStatusCommand.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.HeaderEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.HeaderEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.HeaderEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType
import java.nio.ByteBuffer
class GetStatusCommand private constructor(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/GetVersionCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetVersionCommand.kt
similarity index 80%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/GetVersionCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetVersionCommand.kt
index a63c1b1e004..298c7f21056 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/GetVersionCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetVersionCommand.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.HeaderEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.HeaderEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.HeaderEnabledCommandBuilder
import java.nio.ByteBuffer
class GetVersionCommand private constructor(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramAlertsCommand.kt
similarity index 87%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramAlertsCommand.kt
index 87bdcdd6d87..4a35f3d771f 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramAlertsCommand.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.NonceEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertConfiguration
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBasalCommand.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBasalCommand.kt
index 5b9132baed4..54f95d68b30 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBasalCommand.kt
@@ -1,13 +1,13 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.BasalInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.util.ProgramBasalUtil
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.util.ProgramTempBasalUtil.mapTenthPulsesPerSlotToLongInsulinProgramElements
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.HeaderEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.BasalInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.util.ProgramBasalUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.util.ProgramTempBasalUtil.mapTenthPulsesPerSlotToLongInsulinProgramElements
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBeepsCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBeepsCommand.kt
similarity index 85%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBeepsCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBeepsCommand.kt
index 37b2d16c1fd..cca55f32328 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBeepsCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBeepsCommand.kt
@@ -1,10 +1,10 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.HeaderEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.HeaderEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.HeaderEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
import java.nio.ByteBuffer
class ProgramBeepsCommand private constructor(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBolusCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBolusCommand.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBolusCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBolusCommand.kt
index c330c467b56..0446fa6b6a2 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramBolusCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBolusCommand.kt
@@ -1,11 +1,11 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.BolusShortInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
-import app.aaps.pump.omnipod.dash.driver.pod.util.MessageUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.HeaderEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.BolusShortInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.util.MessageUtil
import java.nio.ByteBuffer
// NOT SUPPORTED: extended bolus
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramInsulinCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramInsulinCommand.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramInsulinCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramInsulinCommand.kt
index d629102ce9c..be1035eb391 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramInsulinCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramInsulinCommand.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.ShortInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.NonceEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.ShortInsulinProgramElement
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramTempBasalCommand.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramTempBasalCommand.kt
index a4491bc0eea..bf36e893966 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramTempBasalCommand.kt
@@ -1,12 +1,12 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.BasalInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.util.ProgramBasalUtil
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.util.ProgramTempBasalUtil
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.HeaderEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.BasalInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.util.ProgramBasalUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.util.ProgramTempBasalUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SetUniqueIdCommand.kt
similarity index 91%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SetUniqueIdCommand.kt
index cb25e1ce416..3fcbb611e7b 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SetUniqueIdCommand.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.HeaderEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.HeaderEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.HeaderEnabledCommandBuilder
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SilenceAlertsCommand.kt
similarity index 80%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SilenceAlertsCommand.kt
index 65e5a584a46..cc6e82beb06 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SilenceAlertsCommand.kt
@@ -1,10 +1,10 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.util.AlertUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.NonceEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.util.AlertUtil
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/StopDeliveryCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/StopDeliveryCommand.kt
similarity index 86%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/StopDeliveryCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/StopDeliveryCommand.kt
index 59fce35c3c5..5dbc684b09b 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/StopDeliveryCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/StopDeliveryCommand.kt
@@ -1,10 +1,10 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.Encodable
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.NonceEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.Encodable
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SuspendDeliveryCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SuspendDeliveryCommand.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SuspendDeliveryCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SuspendDeliveryCommand.kt
index decded8848c..88f4a2b068b 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/SuspendDeliveryCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SuspendDeliveryCommand.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.CommandType
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
-import app.aaps.pump.omnipod.dash.driver.pod.definition.*
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.CommandType
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.NonceEnabledCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder.NonceEnabledCommandBuilder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.*
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/Command.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/Command.kt
similarity index 51%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/Command.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/Command.kt
index b05f68d03f1..558d34160b9 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/Command.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/Command.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.base
+package app.aaps.pump.omnipod.common.bledriver.pod.command.base
-import app.aaps.pump.omnipod.dash.driver.pod.definition.Encodable
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.Encodable
import java.io.Serializable
interface Command : Encodable, Serializable {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/CommandType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/CommandType.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/CommandType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/CommandType.kt
index 80e8004aac5..18af5688e8a 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/CommandType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/CommandType.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.base
+package app.aaps.pump.omnipod.common.bledriver.pod.command.base
enum class CommandType(val value: Byte) {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/HeaderEnabledCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/HeaderEnabledCommand.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/HeaderEnabledCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/HeaderEnabledCommand.kt
index cfd73003dd4..a3c7d4b5b81 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/HeaderEnabledCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/HeaderEnabledCommand.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.base
+package app.aaps.pump.omnipod.common.bledriver.pod.command.base
-import app.aaps.pump.omnipod.dash.driver.pod.util.MessageUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.util.MessageUtil
import java.nio.ByteBuffer
abstract class HeaderEnabledCommand protected constructor(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/NonceEnabledCommand.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/NonceEnabledCommand.kt
similarity index 81%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/NonceEnabledCommand.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/NonceEnabledCommand.kt
index c27b99ae763..fa48114665d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/NonceEnabledCommand.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/NonceEnabledCommand.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.base
+package app.aaps.pump.omnipod.common.bledriver.pod.command.base
abstract class NonceEnabledCommand protected constructor(
commandType: CommandType,
diff --git a/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/CommandBuilder.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/CommandBuilder.kt
new file mode 100644
index 00000000000..fe906551122
--- /dev/null
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/CommandBuilder.kt
@@ -0,0 +1,8 @@
+package app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder
+
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.Command
+
+interface CommandBuilder {
+
+ fun build(): R
+}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/HeaderEnabledCommandBuilder.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/HeaderEnabledCommandBuilder.kt
similarity index 86%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/HeaderEnabledCommandBuilder.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/HeaderEnabledCommandBuilder.kt
index f7bfd2d6eeb..d47182b9809 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/HeaderEnabledCommandBuilder.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/HeaderEnabledCommandBuilder.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.base.builder
+package app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.Command
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.Command
@Suppress("UNCHECKED_CAST")
abstract class HeaderEnabledCommandBuilder, R : Command> : CommandBuilder {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/NonceEnabledCommandBuilder.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/NonceEnabledCommandBuilder.kt
similarity index 74%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/NonceEnabledCommandBuilder.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/NonceEnabledCommandBuilder.kt
index 354850d01db..c199a4a22ed 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/NonceEnabledCommandBuilder.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/base/builder/NonceEnabledCommandBuilder.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.base.builder
+package app.aaps.pump.omnipod.common.bledriver.pod.command.base.builder
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.Command
+import app.aaps.pump.omnipod.common.bledriver.pod.command.base.Command
@Suppress("UNCHECKED_CAST")
abstract class NonceEnabledCommandBuilder, R : Command> : HeaderEnabledCommandBuilder() {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BasalInsulinProgramElement.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BasalInsulinProgramElement.kt
similarity index 83%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BasalInsulinProgramElement.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BasalInsulinProgramElement.kt
index 11765616225..405bd52049f 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BasalInsulinProgramElement.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BasalInsulinProgramElement.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.util.ProgramBasalUtil
-import app.aaps.pump.omnipod.dash.driver.pod.definition.Encodable
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.util.ProgramBasalUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.Encodable
import java.io.Serializable
import java.nio.ByteBuffer
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BasalShortInsulinProgramElement.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BasalShortInsulinProgramElement.kt
similarity index 93%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BasalShortInsulinProgramElement.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BasalShortInsulinProgramElement.kt
index 5b9222a1634..67cba9491eb 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BasalShortInsulinProgramElement.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BasalShortInsulinProgramElement.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program
import java.nio.ByteBuffer
import kotlin.experimental.and
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BolusShortInsulinProgramElement.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BolusShortInsulinProgramElement.kt
similarity index 76%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BolusShortInsulinProgramElement.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BolusShortInsulinProgramElement.kt
index 8c9f9501f2d..264fa60ec3b 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/BolusShortInsulinProgramElement.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/BolusShortInsulinProgramElement.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program
import java.nio.ByteBuffer
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentBasalInsulinProgramElement.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/CurrentBasalInsulinProgramElement.kt
similarity index 85%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentBasalInsulinProgramElement.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/CurrentBasalInsulinProgramElement.kt
index aec9f11bd10..ac07583a2ac 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentBasalInsulinProgramElement.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/CurrentBasalInsulinProgramElement.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program
import java.io.Serializable
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentSlot.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/CurrentSlot.kt
similarity index 83%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentSlot.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/CurrentSlot.kt
index 8f4dfde3e37..735faba969d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentSlot.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/CurrentSlot.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program
import java.io.Serializable
diff --git a/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/ShortInsulinProgramElement.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/ShortInsulinProgramElement.kt
new file mode 100644
index 00000000000..326e6bf7f96
--- /dev/null
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/ShortInsulinProgramElement.kt
@@ -0,0 +1,6 @@
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program
+
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.Encodable
+import java.io.Serializable
+
+interface ShortInsulinProgramElement : Encodable, Serializable
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/TempBasalInsulinProgramElement.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/TempBasalInsulinProgramElement.kt
similarity index 91%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/TempBasalInsulinProgramElement.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/TempBasalInsulinProgramElement.kt
index bd7b9f560f3..b1ea197124f 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/TempBasalInsulinProgramElement.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/TempBasalInsulinProgramElement.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program
import java.nio.ByteBuffer
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/util/ProgramBasalUtil.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/util/ProgramBasalUtil.kt
similarity index 94%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/util/ProgramBasalUtil.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/util/ProgramBasalUtil.kt
index f2af1ecefff..2e6af90f5ab 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/util/ProgramBasalUtil.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/util/ProgramBasalUtil.kt
@@ -1,12 +1,12 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.util
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.util
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.BasalInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.BasalShortInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.CurrentBasalInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.CurrentSlot
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.ShortInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
-import app.aaps.pump.omnipod.dash.driver.pod.util.MessageUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.BasalInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.BasalShortInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.CurrentBasalInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.CurrentSlot
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.ShortInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.util.MessageUtil
import java.nio.ByteBuffer
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/util/ProgramTempBasalUtil.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/util/ProgramTempBasalUtil.kt
similarity index 86%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/util/ProgramTempBasalUtil.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/util/ProgramTempBasalUtil.kt
index 8c3eb410138..e1eee3a6ea1 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/util/ProgramTempBasalUtil.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/insulin/program/util/ProgramTempBasalUtil.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.util
+package app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.util
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.BasalInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.ShortInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program.TempBasalInsulinProgramElement
-import app.aaps.pump.omnipod.dash.driver.pod.util.MessageUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.BasalInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.ShortInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.command.insulin.program.TempBasalInsulinProgramElement
+import app.aaps.pump.omnipod.common.bledriver.pod.util.MessageUtil
import java.nio.ByteBuffer
import kotlin.math.roundToInt
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/ActivationProgress.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/ActivationProgress.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/ActivationProgress.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/ActivationProgress.kt
index d1a805bcc81..93b43ee81a0 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/ActivationProgress.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/ActivationProgress.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
enum class ActivationProgress {
NOT_STARTED,
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlarmType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlarmType.kt
similarity index 98%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlarmType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlarmType.kt
index 74ef76e38da..65014eaf136 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlarmType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlarmType.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
-import app.aaps.pump.omnipod.dash.driver.pod.util.HasValue
+import app.aaps.pump.omnipod.common.bledriver.pod.util.HasValue
enum class AlarmType(override val value: Byte) : HasValue {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertConfiguration.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertConfiguration.kt
similarity index 96%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertConfiguration.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertConfiguration.kt
index a40bcbdea5c..c3029e9eb2e 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertConfiguration.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertConfiguration.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
import java.nio.ByteBuffer
import kotlin.experimental.or
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertTrigger.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertTrigger.kt
similarity index 74%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertTrigger.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertTrigger.kt
index 13c3ae644eb..d9147f08125 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertTrigger.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertTrigger.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
sealed class AlertTrigger {
class TimerTrigger(val offsetInMinutes: Short) : AlertTrigger()
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertType.kt
similarity index 80%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertType.kt
index b7a5edfa7a7..1e3701fd3ce 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/AlertType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/AlertType.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
-import app.aaps.pump.omnipod.dash.driver.pod.util.HasValue
+import app.aaps.pump.omnipod.common.bledriver.pod.util.HasValue
enum class AlertType(val index: Byte) : HasValue {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BasalProgram.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BasalProgram.kt
similarity index 97%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BasalProgram.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BasalProgram.kt
index 8e7ffac8848..cfaef788fd7 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BasalProgram.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BasalProgram.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
import java.util.*
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BeepRepetitionType.kt
similarity index 87%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BeepRepetitionType.kt
index 05badb56b40..74b7c1177e8 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BeepRepetitionType.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
// FIXME names
enum class BeepRepetitionType(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BeepType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BeepType.kt
similarity index 84%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BeepType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BeepType.kt
index be5928afc35..e1f4b96a246 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/BeepType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/BeepType.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
enum class BeepType(val value: Byte) {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/DeliveryStatus.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/DeliveryStatus.kt
similarity index 86%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/DeliveryStatus.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/DeliveryStatus.kt
index 158d248a15f..0ead4f01d56 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/DeliveryStatus.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/DeliveryStatus.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
-import app.aaps.pump.omnipod.dash.driver.pod.util.HasValue
+import app.aaps.pump.omnipod.common.bledriver.pod.util.HasValue
enum class DeliveryStatus(override val value: Byte) : HasValue {
diff --git a/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/Encodable.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/Encodable.kt
new file mode 100644
index 00000000000..c60f88b8c06
--- /dev/null
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/Encodable.kt
@@ -0,0 +1,6 @@
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
+
+interface Encodable {
+
+ val encoded: ByteArray
+}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/NakErrorType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/NakErrorType.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/NakErrorType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/NakErrorType.kt
index 703d76fc099..b3649d9b2b3 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/NakErrorType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/NakErrorType.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
-import app.aaps.pump.omnipod.dash.driver.pod.util.HasValue
+import app.aaps.pump.omnipod.common.bledriver.pod.util.HasValue
enum class NakErrorType(override val value: Byte) : HasValue {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/PodConstants.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/PodConstants.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/PodConstants.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/PodConstants.kt
index 91ee77e2ddf..64a94d9252d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/PodConstants.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/PodConstants.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
import java.time.Duration
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/PodStatus.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/PodStatus.kt
similarity index 85%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/PodStatus.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/PodStatus.kt
index f91beb7821a..6acb26892b0 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/PodStatus.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/PodStatus.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
-import app.aaps.pump.omnipod.dash.driver.pod.util.HasValue
+import app.aaps.pump.omnipod.common.bledriver.pod.util.HasValue
enum class PodStatus(override val value: Byte) : HasValue {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/ProgramReminder.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/ProgramReminder.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/ProgramReminder.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/ProgramReminder.kt
index 5b33b7204ef..8f8dcc11564 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/ProgramReminder.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/ProgramReminder.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
import java.io.Serializable
import kotlin.experimental.and
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/SoftwareVersion.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/SoftwareVersion.kt
similarity index 80%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/SoftwareVersion.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/SoftwareVersion.kt
index 7f5fec47b50..fc4a5a6bdc6 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/SoftwareVersion.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/definition/SoftwareVersion.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
+package app.aaps.pump.omnipod.common.bledriver.pod.definition
import java.io.Serializable
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ActivationResponseBase.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ActivationResponseBase.kt
similarity index 53%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ActivationResponseBase.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ActivationResponseBase.kt
index 20a0f391a81..fc06ee43d3e 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ActivationResponseBase.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ActivationResponseBase.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType.ActivationResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType.ActivationResponseType
abstract class ActivationResponseBase(
val activationResponseType: ActivationResponseType,
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/AdditionalStatusResponseBase.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AdditionalStatusResponseBase.kt
similarity index 57%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/AdditionalStatusResponseBase.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AdditionalStatusResponseBase.kt
index e6c010c2fd8..b608ef3b2c5 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/AdditionalStatusResponseBase.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AdditionalStatusResponseBase.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType.StatusResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType.StatusResponseType
open class AdditionalStatusResponseBase internal constructor(
val statusResponseType: StatusResponseType,
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/AlarmStatusResponse.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AlarmStatusResponse.kt
similarity index 87%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/AlarmStatusResponse.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AlarmStatusResponse.kt
index ebdcfaa99f4..393448335e8 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/AlarmStatusResponse.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AlarmStatusResponse.kt
@@ -1,12 +1,12 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlarmType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType.StatusResponseType
-import app.aaps.pump.omnipod.dash.driver.pod.util.AlertUtil
-import app.aaps.pump.omnipod.dash.driver.pod.util.byValue
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlarmType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.DeliveryStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType.StatusResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.util.AlertUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.util.byValue
import java.nio.ByteBuffer
import java.util.*
import kotlin.experimental.and
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/DefaultStatusResponse.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/DefaultStatusResponse.kt
similarity index 82%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/DefaultStatusResponse.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/DefaultStatusResponse.kt
index 9ee4bc30cfd..16bb9a583ba 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/DefaultStatusResponse.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/DefaultStatusResponse.kt
@@ -1,10 +1,10 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.util.AlertUtil
-import app.aaps.pump.omnipod.dash.driver.pod.util.byValue
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.DeliveryStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.util.AlertUtil
+import app.aaps.pump.omnipod.common.bledriver.pod.util.byValue
import java.nio.ByteBuffer
import java.util.*
import kotlin.experimental.and
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/NakResponse.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/NakResponse.kt
similarity index 80%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/NakResponse.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/NakResponse.kt
index c377464152e..bd7d0f530ff 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/NakResponse.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/NakResponse.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlarmType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.NakErrorType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.util.byValue
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlarmType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.NakErrorType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.util.byValue
class NakResponse(
encoded: ByteArray
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/Response.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/Response.kt
similarity index 68%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/Response.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/Response.kt
index ee3bba334d5..540c2829db4 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/Response.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/Response.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
import java.io.Serializable
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ResponseBase.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ResponseBase.kt
similarity index 75%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ResponseBase.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ResponseBase.kt
index 4c8697de5e6..e754d4cd01e 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ResponseBase.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ResponseBase.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
abstract class ResponseBase(
override val responseType: ResponseType,
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ResponseType.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ResponseType.kt
similarity index 88%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ResponseType.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ResponseType.kt
index d0568684500..180b8037ffe 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/ResponseType.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/ResponseType.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.util.HasValue
+import app.aaps.pump.omnipod.common.bledriver.pod.util.HasValue
enum class ResponseType(override val value: Byte) : HasValue {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/SetUniqueIdResponse.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/SetUniqueIdResponse.kt
similarity index 92%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/SetUniqueIdResponse.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/SetUniqueIdResponse.kt
index 81ec52c7133..0ed2c98ad6e 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/SetUniqueIdResponse.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/SetUniqueIdResponse.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType.ActivationResponseType
-import app.aaps.pump.omnipod.dash.driver.pod.util.byValue
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType.ActivationResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.util.byValue
import java.nio.ByteBuffer
class SetUniqueIdResponse(
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/VersionResponse.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/VersionResponse.kt
similarity index 90%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/VersionResponse.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/VersionResponse.kt
index 806ed668a26..cb71f1fe3a4 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/response/VersionResponse.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/VersionResponse.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType.ActivationResponseType
-import app.aaps.pump.omnipod.dash.driver.pod.util.byValue
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType.ActivationResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.util.byValue
import java.nio.ByteBuffer
import kotlin.experimental.and
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/CommandConfirmed.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/CommandConfirmed.kt
similarity index 65%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/CommandConfirmed.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/CommandConfirmed.kt
index 4badb0732b5..8d7b7767761 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/CommandConfirmed.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/CommandConfirmed.kt
@@ -1,3 +1,3 @@
-package app.aaps.pump.omnipod.dash.driver.pod.state
+package app.aaps.pump.omnipod.common.bledriver.pod.state
data class CommandConfirmed(val command: OmnipodDashPodStateManager.ActiveCommand, val success: Boolean)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/OmnipodDashPodStateManager.kt
similarity index 85%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/OmnipodDashPodStateManager.kt
index ecb281a62dd..615447a1310 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/OmnipodDashPodStateManager.kt
@@ -1,19 +1,19 @@
-package app.aaps.pump.omnipod.dash.driver.pod.state
+package app.aaps.pump.omnipod.common.bledriver.pod.state
import app.aaps.core.data.model.BS
-import app.aaps.pump.omnipod.dash.driver.comm.Id
-import app.aaps.pump.omnipod.dash.driver.comm.pair.PairResult
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ActivationProgress
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlarmType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
-import app.aaps.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.SoftwareVersion
-import app.aaps.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.VersionResponse
+import app.aaps.pump.omnipod.common.bledriver.comm.Id
+import app.aaps.pump.omnipod.common.bledriver.comm.pair.PairResult
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ActivationProgress
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlarmType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.DeliveryStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.SoftwareVersion
+import app.aaps.pump.omnipod.common.bledriver.pod.response.AlarmStatusResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.DefaultStatusResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.SetUniqueIdResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.VersionResponse
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Single
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/OmnipodDashPodStateManagerImpl.kt
similarity index 95%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/OmnipodDashPodStateManagerImpl.kt
index 4db52248a44..fb62bc9046c 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/state/OmnipodDashPodStateManagerImpl.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.state
+package app.aaps.pump.omnipod.common.bledriver.pod.state
import android.os.SystemClock
import app.aaps.core.data.model.BS
@@ -7,23 +7,23 @@ import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.interfaces.rx.bus.RxBus
import app.aaps.core.interfaces.utils.Round
import app.aaps.core.keys.interfaces.Preferences
-import app.aaps.pump.omnipod.dash.EventOmnipodDashPumpValuesChanged
-import app.aaps.pump.omnipod.dash.driver.comm.Id
-import app.aaps.pump.omnipod.dash.driver.comm.pair.PairResult
-import app.aaps.pump.omnipod.dash.driver.comm.session.EapSqn
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ActivationProgress
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlarmType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
-import app.aaps.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.SoftwareVersion
-import app.aaps.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.VersionResponse
-import app.aaps.pump.omnipod.dash.keys.DashStringNonPreferenceKey
+import app.aaps.pump.omnipod.common.EventOmnipodDashPumpValuesChanged
+import app.aaps.pump.omnipod.common.bledriver.comm.Id
+import app.aaps.pump.omnipod.common.bledriver.comm.pair.PairResult
+import app.aaps.pump.omnipod.common.bledriver.comm.session.EapSqn
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ActivationProgress
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlarmType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.DeliveryStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.SoftwareVersion
+import app.aaps.pump.omnipod.common.bledriver.pod.response.AlarmStatusResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.DefaultStatusResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.SetUniqueIdResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.VersionResponse
+import app.aaps.pump.omnipod.common.keys.DashStringNonPreferenceKey
import com.google.gson.Gson
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Maybe
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/AlertUtil.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/AlertUtil.kt
similarity index 84%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/AlertUtil.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/AlertUtil.kt
index b49519f6aca..0c553824074 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/AlertUtil.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/AlertUtil.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.util
+package app.aaps.pump.omnipod.common.bledriver.pod.util
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
import java.util.*
object AlertUtil {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/HasValue.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/HasValue.kt
similarity index 79%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/HasValue.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/HasValue.kt
index 7cd1f6215ed..4b12b6fa89d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/HasValue.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/HasValue.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.util
+package app.aaps.pump.omnipod.common.bledriver.pod.util
interface HasValue {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/MessageUtil.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/MessageUtil.kt
similarity index 98%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/MessageUtil.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/MessageUtil.kt
index 1c17d5fc806..dc174b1a62c 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/MessageUtil.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/MessageUtil.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.util
+package app.aaps.pump.omnipod.common.bledriver.pod.util
import kotlin.experimental.and
import kotlin.experimental.xor
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/RandomByteGenerator.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/RandomByteGenerator.kt
similarity index 78%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/RandomByteGenerator.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/RandomByteGenerator.kt
index ee56e87c50f..3eb1393f2bb 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/RandomByteGenerator.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/RandomByteGenerator.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.util
+package app.aaps.pump.omnipod.common.bledriver.pod.util
import java.security.SecureRandom
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/X25519KeyGenerator.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/X25519KeyGenerator.kt
similarity index 87%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/X25519KeyGenerator.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/X25519KeyGenerator.kt
index 6a5ff662d59..27069bdb78d 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/util/X25519KeyGenerator.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/util/X25519KeyGenerator.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.util
+package app.aaps.pump.omnipod.common.bledriver.pod.util
import com.google.crypto.tink.subtle.X25519
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/Flag.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/util/Flag.kt
similarity index 79%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/Flag.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/util/Flag.kt
index b0da1bb514e..bb6cd507137 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/Flag.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/bledriver/util/Flag.kt
@@ -1,11 +1,10 @@
-package app.aaps.pump.omnipod.dash.util
+package app.aaps.pump.omnipod.common.bledriver.util
class Flag(var value: Int = 0) {
fun set(idx: Byte, set: Boolean) {
val mask = 1 shl (7 - idx)
- if (!set)
- return
+ if (!set) return
value = value or mask
}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/keys/DashBooleanPreferenceKey.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/keys/DashBooleanPreferenceKey.kt
similarity index 95%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/keys/DashBooleanPreferenceKey.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/keys/DashBooleanPreferenceKey.kt
index 5b829e4a1e8..0994ecfcb49 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/keys/DashBooleanPreferenceKey.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/keys/DashBooleanPreferenceKey.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.keys
+package app.aaps.pump.omnipod.common.keys
import app.aaps.core.keys.interfaces.BooleanPreferenceKey
@@ -19,4 +19,4 @@ enum class DashBooleanPreferenceKey(
SoundDeliverySuspendedNotification("AAPS.Omnipod.notification_delivery_suspended_sound_enabled", true),
UseBonding("AAPS.Omnipod.Dash.use_bonding", false),
-}
\ No newline at end of file
+}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/keys/DashStringNonPreferenceKey.kt b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/keys/DashStringNonPreferenceKey.kt
similarity index 86%
rename from pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/keys/DashStringNonPreferenceKey.kt
rename to pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/keys/DashStringNonPreferenceKey.kt
index 150ed1f1509..840b1fa834c 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/keys/DashStringNonPreferenceKey.kt
+++ b/pump/omnipod/common/src/main/kotlin/app/aaps/pump/omnipod/common/keys/DashStringNonPreferenceKey.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.keys
+package app.aaps.pump.omnipod.common.keys
import app.aaps.core.keys.interfaces.StringNonPreferenceKey
@@ -9,4 +9,4 @@ enum class DashStringNonPreferenceKey(
) : StringNonPreferenceKey {
PodState("AAPS.OmnipodDash.pod_state", ""),
-}
\ No newline at end of file
+}
diff --git a/pump/omnipod/common/src/main/res/values-nl-rNL/strings.xml b/pump/omnipod/common/src/main/res/values-nl-rNL/strings.xml
index c0cf70721f6..41d24111b7b 100644
--- a/pump/omnipod/common/src/main/res/values-nl-rNL/strings.xml
+++ b/pump/omnipod/common/src/main/res/values-nl-rNL/strings.xml
@@ -1,6 +1,7 @@
+ Pod ManagementActiesHulpmiddelenActiveer Pod
@@ -44,6 +45,7 @@
Toediening hervattenPod BeheerAlarmen Stil
+ Pod StatusTotaal toegediend%1$.2f EUniek ID
@@ -54,6 +56,7 @@
Laatste bolusTijdelijke basaalstandBasis basaalstand
+ ReservoirActieve pod alarmenFirmware versieTijd op Pod
@@ -113,7 +116,9 @@
Bevestigings pieptonenNotificatiesGeluid voor onzekere TBR notificaties ingeschakeld
+ Geluid voor onzekere SMB notificaties ingeschakeldGeluid voor onzekere bolus notificaties ingeschakeld
+ Gebruik BT device binding op Android 15Geen actieve PodSetup wordt uitgevoerd (in afwachting van Pod activering)
@@ -159,6 +164,7 @@
JaNee
+ OKAfbrekenWaarschuwingUITSCHAKELEN SUSPEND ALARM
diff --git a/pump/omnipod/common/src/main/res/values-pl-rPL/strings.xml b/pump/omnipod/common/src/main/res/values-pl-rPL/strings.xml
index 0d26f2ebd9d..627f45667e2 100644
--- a/pump/omnipod/common/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/omnipod/common/src/main/res/values-pl-rPL/strings.xml
@@ -47,6 +47,7 @@
Wycisz alarmyStatus PodaŁącznie dostarczono
+ %1$.2f UUnikalny IDNumer LOTNumer sekwencji
@@ -115,7 +116,9 @@
Dźwięki potwierdzeniaPowiadomieniaDźwięk dla powiadomień o niepewnych TBR włączony
+ Dźwięk dla niepewnych powiadomień SMB włączonyDźwięk dla powiadomień o niepewnych bolusach włączony
+ Powiąż urządzenie BT na Androidzie 15Brak akt. PodaKonfiguracja w toku (oczekiwanie na aktywację Poda)
@@ -161,6 +164,7 @@
TakNie
+ OKAnulujOstrzeżenieWYŁĄCZ OSTRZEŻENIA O ZAWIESZENIU
diff --git a/pump/omnipod/common/src/main/res/values-sk-rSK/strings.xml b/pump/omnipod/common/src/main/res/values-sk-rSK/strings.xml
index 2dd83b9b4d1..31a6df8000f 100644
--- a/pump/omnipod/common/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/omnipod/common/src/main/res/values-sk-rSK/strings.xml
@@ -47,7 +47,7 @@
Stíšiť alarmyStav PoduCelkovo podané
- %1$.2f JI
+ %1$.2f UJedinečné IDČíslo šaržePoradové číslo
@@ -60,9 +60,9 @@
Výstrahy aktívneho PoduVerzia firmvéruČas na Pode
- %1$.2fJI/h @%2$s (%3$d/%4$d minút)
- Zostáva %1$.2f JI
- Zostáva viac ako 50 JI
+ %1$.2fU/h @%2$s (%3$d/%4$d minut)
+ Zostáva %1$.2f U
+ Zostáva viac ako 50 UChybyneznáme
diff --git a/pump/omnipod/common/src/main/res/values-vi-rVN/strings.xml b/pump/omnipod/common/src/main/res/values-vi-rVN/strings.xml
index 984c1b45f26..14f46472e99 100644
--- a/pump/omnipod/common/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/omnipod/common/src/main/res/values-vi-rVN/strings.xml
@@ -2,7 +2,7 @@
Quản lý Pod
- Actions
+ Các thao tácCông cụKích hoạt PodHủy kích hoạt Pod
@@ -13,10 +13,10 @@
Lịch sử PodKhông có Pod hoạt động
- Cài đặt cấu hình basal không thành công.
+ Cài đặt cấu hình Hồ sơ không thành công.Bolus không thành công.
- Thiết lập cấu hình Basal thất bại: nhận được cấu hình trống. Hãy đảm bảo rằng bạn đã kích hoạt Cấu hình Basal của mình.
- Không có cấu hình Basal nào đang hoạt động. Hãy đảm bảo bạn đã kích hoạt cấu hình Basal của mình.
+ Thiết lập Hồ sơ liều nền thất bại: nhận được Hồ sơ trống. Hãy đảm bảo rằng bạn đã kích hoạt Hồ sơ liều nền của mình.
+ Không có Hồ sơ liều nền nào đang hoạt động. Hãy đảm bảo bạn đã kích hoạt Hồ sơ liều nền của mình.Lệnh tùy chỉnh không được hỗ trợ: %1$sKhông thể cập nhật trạng tháiKhông thể cập nhật trạng thái khi khởi động
@@ -49,14 +49,14 @@
Tổng lượng đã tiêm%1$.2f UMã số duy nhất
- LOT Number
+ Số LôSố thứ tựPod hết hạnKết nối lần cuốiLiều bolus mới nhất
- Tỷ lệ Basal tạm thời
- Tỷ lệ basal cơ bản
- Ngăn chứa
+ Tỷ lệ liều nền tạm thời
+ Tỷ lệ liều nền cơ bản
+ Bình chứaCảnh báo Pod đang bậtPhiên bản phần mềmThời gian trên Pod
@@ -78,12 +78,12 @@
Làm đầy PodKhởi tạo PodGắn Pod
- Chuẩn bị vị trí gắn. Tháo nắp kim và lớp keo bảo vệ của Pod, sau đó gắn Pod vào vị trí tiêm.\n\nNếu kim truyền (cannula) bị lòi ra, vui lòng nhấn Hủy và Loại bỏ Pod của bạn.\n\nNhấn Tiếp theo để đưa kim truyền vào và bắt đầu truyền basal.
+ Chuẩn bị vị trí gắn. Tháo nắp kim và lớp keo bảo vệ của Pod, sau đó gắn Pod vào vị trí tiêm.\n\nNếu kim truyền (cannula) bị lòi ra, vui lòng nhấn Hủy và Loại bỏ Pod của bạn.\n\nNhấn Tiếp theo để đưa kim truyền vào và bắt đầu truyền liều nền.Khi bạn nhấn OK, kim truyền sẽ được đưa vào. Hãy đảm bảo rằng bạn đã gắn Pod vào vị trí gắn.Gắn kim truyền
- Đang thiết lập lịch basal ban đầu và đưa kim truyền vào.\n\nKhi kim truyền đã được đưa vào thành công, bạn có thể nhấn Tiếp theo.
+ Đang thiết lập lịch liều nền ban đầu và đưa kim truyền vào.\n\nKhi kim truyền đã được đưa vào thành công, bạn có thể nhấn Tiếp theo.Đã kích hoạt Pod
- Pod mới đã được kích hoạt.\n\nLịch basal của bạn đã được lập trình và kim truyền đã được đưa vào.\n\nVui lòng kiểm tra xem kim truyền đã được đưa vào đúng chưa và thay Pod nếu bạn cho rằng chưa đúng.
+ Pod mới đã được kích hoạt.\n\nLịch liều nền của bạn đã được lập trình và kim truyền đã được đưa vào.\n\nVui lòng kiểm tra xem kim truyền đã được đưa vào đúng chưa và thay Pod nếu bạn cho rằng chưa đúng.Hủy kích hoạt PodNhấn Tiếp theo để hủy kích hoạt Pod.\n\nLưu ý: Thao tác này sẽ tạm dừng toàn bộ việc truyền insulin và hủy kích hoạt Pod.
@@ -97,7 +97,7 @@
Xóa PodĐã bật tiếng bíp Bolus
- Đã bật tiếng bíp Basal
+ Âm báo liều nền được bậtĐã bật tiếng bíp SMBĐã bật tiếng bíp TBRHiển thị nút Tạm dừng truyền insulin trong thẻ Omnipod
@@ -134,10 +134,10 @@
Xóa PodThiết lập liều BolusHủy liều bolus
- Đặt Basal tạm thời
- Hủy Basal tạm thời (do hệ thống điều khiển)
- Hủy bỏ Basal tạm thời
- Đặt lịch trình Basal
+ Đặt liều nền tạm thời
+ Hủy liều nền tạm thời (do hệ thống điều khiển)
+ Hủy bỏ liều nền tạm thời
+ Đặt lịch trình liều nềnNhận trạng thái PodNhận thông tin PodĐặt giờ
@@ -149,9 +149,9 @@
Khởi tạo PodGắn kim truyềnĐọc nhật ký Pulse
- Thiết lập basal tạm thời giả vì Pod đang bị tạm dừng
- Hủy basal tạm thời giả đã được tạo khi Pod bị tạm dừng
- Chia basal tạm thời do không chắc chắn về việc hủy thành công
+ Thiết lập liều nền tạm thời giả vì Pod đang bị tạm dừng
+ Hủy liều nền tạm thời giả đã được tạo khi Pod bị tạm dừng
+ Chia liều nền tạm thời do không chắc chắn về việc hủy thành côngKiểm tra tiếng BeepNhắc hoàn tất ghép nối
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/OmnipodDashPumpPlugin.kt
index 0aa93b79d9f..72075123a5b 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/OmnipodDashPumpPlugin.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/OmnipodDashPumpPlugin.kt
@@ -54,27 +54,27 @@ import app.aaps.pump.omnipod.common.queue.command.CommandPlayTestBeep
import app.aaps.pump.omnipod.common.queue.command.CommandResumeDelivery
import app.aaps.pump.omnipod.common.queue.command.CommandSilenceAlerts
import app.aaps.pump.omnipod.common.queue.command.CommandUpdateAlertConfiguration
-import app.aaps.pump.omnipod.dash.driver.OmnipodDashManager
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ActivationProgress
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertTrigger
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepRepetitionType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_IMMINENT_ALERT_HOURS_REMAINING
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType
-import app.aaps.pump.omnipod.dash.driver.pod.state.CommandConfirmed
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.OmnipodDashManager
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ActivationProgress
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertConfiguration
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertTrigger
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepRepetitionType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.DeliveryStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants.Companion.POD_EXPIRATION_IMMINENT_ALERT_HOURS_REMAINING
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.state.CommandConfirmed
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import app.aaps.pump.omnipod.dash.history.DashHistory
import app.aaps.pump.omnipod.dash.history.data.BasalValuesRecord
import app.aaps.pump.omnipod.dash.history.data.BolusRecord
import app.aaps.pump.omnipod.dash.history.data.BolusType
import app.aaps.pump.omnipod.dash.history.data.TempBasalRecord
import app.aaps.pump.omnipod.dash.history.database.DashHistoryDatabase
-import app.aaps.pump.omnipod.dash.keys.DashBooleanPreferenceKey
-import app.aaps.pump.omnipod.dash.keys.DashStringNonPreferenceKey
+import app.aaps.pump.omnipod.common.keys.DashBooleanPreferenceKey
+import app.aaps.pump.omnipod.common.keys.DashStringNonPreferenceKey
import app.aaps.pump.omnipod.dash.ui.OmnipodDashOverviewFragment
import app.aaps.pump.omnipod.dash.util.Constants
import app.aaps.pump.omnipod.dash.util.mapProfileToBasalProgram
@@ -700,10 +700,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
continue
}
val percent = (waited.toFloat() / estimatedDeliveryTimeSeconds) * 100
- updateBolusProgressDialog(
- rh.gs(app.aaps.core.interfaces.R.string.bolus_delivering, Round.roundTo(percent * requestedBolusAmount / 100, PodConstants.POD_PULSE_BOLUS_UNITS)),
- percent.toInt()
- )
+ rxBus.send(EventOverviewBolusProgress(rh, percent = percent.toInt()))
}
(1..BOLUS_RETRIES).forEach { tryNumber ->
@@ -731,10 +728,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
// delivery not complete yet
val remainingUnits = podStateManager.lastBolus!!.bolusUnitsRemaining
val percent = ((requestedBolusAmount - remainingUnits) / requestedBolusAmount) * 100
- updateBolusProgressDialog(
- rh.gs(app.aaps.core.interfaces.R.string.bolus_delivering, Round.roundTo(requestedBolusAmount - remainingUnits, PodConstants.POD_PULSE_BOLUS_UNITS)),
- percent.toInt()
- )
+ rxBus.send(EventOverviewBolusProgress(rh, percent = percent.toInt()))
val sleepSeconds = if (bolusCanceled)
BOLUS_RETRY_INTERVAL_MS
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/di/OmnipodDashModule.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/di/OmnipodDashModule.kt
index aa3d61c7c2c..b28322d9634 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/di/OmnipodDashModule.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/di/OmnipodDashModule.kt
@@ -2,12 +2,12 @@ package app.aaps.pump.omnipod.dash.di
import app.aaps.pump.omnipod.common.di.ActivityScope
import app.aaps.pump.omnipod.common.di.OmnipodWizardModule
-import app.aaps.pump.omnipod.dash.driver.OmnipodDashManager
-import app.aaps.pump.omnipod.dash.driver.OmnipodDashManagerImpl
-import app.aaps.pump.omnipod.dash.driver.comm.OmnipodDashBleManager
-import app.aaps.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManagerImpl
+import app.aaps.pump.omnipod.common.bledriver.OmnipodDashManager
+import app.aaps.pump.omnipod.common.bledriver.OmnipodDashManagerImpl
+import app.aaps.pump.omnipod.common.bledriver.comm.OmnipodDashBleManager
+import app.aaps.pump.omnipod.common.bledriver.comm.OmnipodDashBleManagerImpl
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManagerImpl
import app.aaps.pump.omnipod.dash.ui.DashPodHistoryActivity
import app.aaps.pump.omnipod.dash.ui.DashPodManagementActivity
import app.aaps.pump.omnipod.dash.ui.OmnipodDashOverviewFragment
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManager.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManager.kt
index 510ab3849b6..4bc2a8386ef 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManager.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManager.kt
@@ -1,12 +1,12 @@
-package app.aaps.pump.omnipod.dash.driver
-
-import app.aaps.pump.omnipod.dash.driver.event.PodEvent
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertTrigger
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType
+package app.aaps.pump.omnipod.common.bledriver
+
+import app.aaps.pump.omnipod.common.bledriver.event.PodEvent
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertConfiguration
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertTrigger
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType
import io.reactivex.rxjava3.core.Observable
import java.util.*
import java.util.concurrent.CountDownLatch
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt
index 54c6027933c..3477d67b070 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt
@@ -1,45 +1,45 @@
-package app.aaps.pump.omnipod.dash.driver
+package app.aaps.pump.omnipod.common.bledriver
import android.os.SystemClock
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.logging.LTag
import app.aaps.core.interfaces.rx.AapsSchedulers
import app.aaps.core.interfaces.utils.Round
-import app.aaps.pump.omnipod.dash.driver.comm.OmnipodDashBleManager
-import app.aaps.pump.omnipod.dash.driver.event.PodEvent
-import app.aaps.pump.omnipod.dash.driver.pod.command.DeactivateCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.GetStatusCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.GetVersionCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.GetVersionCommand.Companion.DEFAULT_UNIQUE_ID
-import app.aaps.pump.omnipod.dash.driver.pod.command.ProgramAlertsCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.ProgramBasalCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.ProgramBeepsCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.ProgramBolusCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.ProgramTempBasalCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.SetUniqueIdCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.SilenceAlertsCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.StopDeliveryCommand
-import app.aaps.pump.omnipod.dash.driver.pod.command.SuspendDeliveryCommand
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ActivationProgress
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertTrigger
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepRepetitionType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.MAX_POD_LIFETIME
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_ALERT_HOURS_REMAINING_DEFAULT
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_IMMINENT_ALERT_HOURS_REMAINING
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_PULSE_BOLUS_UNITS
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
-import app.aaps.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.Response
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType
-import app.aaps.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
-import app.aaps.pump.omnipod.dash.driver.pod.response.VersionResponse
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.comm.OmnipodDashBleManager
+import app.aaps.pump.omnipod.common.bledriver.event.PodEvent
+import app.aaps.pump.omnipod.common.bledriver.pod.command.DeactivateCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.GetStatusCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.GetVersionCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.GetVersionCommand.Companion.DEFAULT_UNIQUE_ID
+import app.aaps.pump.omnipod.common.bledriver.pod.command.ProgramAlertsCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.ProgramBasalCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.ProgramBeepsCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.ProgramBolusCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.ProgramTempBasalCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.SetUniqueIdCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.SilenceAlertsCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.StopDeliveryCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.command.SuspendDeliveryCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ActivationProgress
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertConfiguration
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertTrigger
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepRepetitionType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants.Companion.MAX_POD_LIFETIME
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants.Companion.POD_EXPIRATION_ALERT_HOURS_REMAINING_DEFAULT
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants.Companion.POD_EXPIRATION_IMMINENT_ALERT_HOURS_REMAINING
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants.Companion.POD_PULSE_BOLUS_UNITS
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.response.AlarmStatusResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.DefaultStatusResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.Response
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.response.SetUniqueIdResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.response.VersionResponse
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.functions.Action
import io.reactivex.rxjava3.functions.Consumer
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/BusyException.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/BusyException.kt
deleted file mode 100644
index af2d66ad24a..00000000000
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/BusyException.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
-
-class BusyException : Exception("Bluetooth busy")
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ConnectException.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ConnectException.kt
deleted file mode 100644
index 7563f6802ac..00000000000
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/ConnectException.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
-
-class ConnectException(val msg: String) : Exception(msg)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/PairingException.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/PairingException.kt
deleted file mode 100644
index debf56a4008..00000000000
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/comm/exceptions/PairingException.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package app.aaps.pump.omnipod.dash.driver.comm.exceptions
-
-class PairingException(val msg: String) : Exception(msg)
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/CommandBuilder.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/CommandBuilder.kt
deleted file mode 100644
index 7abc917943e..00000000000
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/base/builder/CommandBuilder.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.base.builder
-
-import app.aaps.pump.omnipod.dash.driver.pod.command.base.Command
-
-interface CommandBuilder {
-
- fun build(): R
-}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/ShortInsulinProgramElement.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/ShortInsulinProgramElement.kt
deleted file mode 100644
index 97f60a3780e..00000000000
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/command/insulin/program/ShortInsulinProgramElement.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command.insulin.program
-
-import app.aaps.pump.omnipod.dash.driver.pod.definition.Encodable
-import java.io.Serializable
-
-interface ShortInsulinProgramElement : Encodable, Serializable
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/Encodable.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/Encodable.kt
deleted file mode 100644
index 7fba7de6bc0..00000000000
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/driver/pod/definition/Encodable.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package app.aaps.pump.omnipod.dash.driver.pod.definition
-
-interface Encodable {
-
- val encoded: ByteArray
-}
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/history/DashHistory.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/history/DashHistory.kt
index 970ae2f7644..1dcef9d3705 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/history/DashHistory.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/history/DashHistory.kt
@@ -5,13 +5,13 @@ import app.aaps.core.interfaces.logging.LTag
import app.aaps.pump.omnipod.common.definition.OmnipodCommandType
import app.aaps.pump.omnipod.common.definition.OmnipodCommandType.SET_BOLUS
import app.aaps.pump.omnipod.common.definition.OmnipodCommandType.SET_TEMPORARY_BASAL
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_PULSE_BOLUS_UNITS
-import app.aaps.pump.omnipod.dash.driver.pod.state.CommandConfirmationDenied
-import app.aaps.pump.omnipod.dash.driver.pod.state.CommandConfirmationSuccess
-import app.aaps.pump.omnipod.dash.driver.pod.state.CommandSendingFailure
-import app.aaps.pump.omnipod.dash.driver.pod.state.CommandSendingNotConfirmed
-import app.aaps.pump.omnipod.dash.driver.pod.state.NoActiveCommand
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants.Companion.POD_PULSE_BOLUS_UNITS
+import app.aaps.pump.omnipod.common.bledriver.pod.state.CommandConfirmationDenied
+import app.aaps.pump.omnipod.common.bledriver.pod.state.CommandConfirmationSuccess
+import app.aaps.pump.omnipod.common.bledriver.pod.state.CommandSendingFailure
+import app.aaps.pump.omnipod.common.bledriver.pod.state.CommandSendingNotConfirmed
+import app.aaps.pump.omnipod.common.bledriver.pod.state.NoActiveCommand
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import app.aaps.pump.omnipod.dash.history.data.BasalValuesRecord
import app.aaps.pump.omnipod.dash.history.data.BolusRecord
import app.aaps.pump.omnipod.dash.history.data.HistoryRecord
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/DashPodManagementActivity.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/DashPodManagementActivity.kt
index 4ebe8930395..565d4a37588 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/DashPodManagementActivity.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/DashPodManagementActivity.kt
@@ -3,6 +3,7 @@ package app.aaps.pump.omnipod.dash.ui
import android.content.Context
import android.content.Intent
import android.os.Bundle
+import app.aaps.core.interfaces.profile.ProfileFunction
import app.aaps.core.interfaces.queue.Callback
import app.aaps.core.interfaces.queue.CommandQueue
import app.aaps.core.interfaces.resources.ResourceHelper
@@ -17,10 +18,11 @@ import app.aaps.core.ui.extensions.toVisibility
import app.aaps.pump.omnipod.common.queue.command.CommandPlayTestBeep
import app.aaps.pump.omnipod.common.ui.wizard.activation.PodActivationWizardActivity
import app.aaps.pump.omnipod.dash.databinding.OmnipodDashPodManagementBinding
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ActivationProgress
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ActivationProgress
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import app.aaps.pump.omnipod.dash.ui.wizard.activation.DashPodActivationWizardActivity
import app.aaps.pump.omnipod.dash.ui.wizard.deactivation.DashPodDeactivationWizardActivity
+import app.aaps.pump.omnipod.dash.util.mapProfileToBasalProgram
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
@@ -32,6 +34,7 @@ class DashPodManagementActivity : TranslatedDaggerAppCompatActivity() {
@Inject lateinit var context: Context
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var podStateManager: OmnipodDashPodStateManager
+ @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var uiInteraction: UiInteraction
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var rxBus: RxBus
@@ -51,6 +54,27 @@ class DashPodManagementActivity : TranslatedDaggerAppCompatActivity() {
supportActionBar?.setDisplayShowHomeEnabled(true)
binding.buttonActivatePod.setOnClickListener {
+ val profile = profileFunction.getProfile()
+ if (profile == null) {
+ OKDialog.show(
+ this,
+ rh.gs(app.aaps.pump.omnipod.common.R.string.omnipod_common_warning),
+ rh.gs(app.aaps.pump.omnipod.common.R.string.omnipod_common_error_failed_to_set_profile_empty_profile)
+ )
+ return@setOnClickListener
+ }
+
+ try {
+ mapProfileToBasalProgram(profile)
+ } catch (e: IllegalArgumentException) {
+ OKDialog.show(
+ this,
+ rh.gs(app.aaps.pump.omnipod.common.R.string.omnipod_common_warning),
+ e.message ?: rh.gs(app.aaps.pump.omnipod.common.R.string.omnipod_common_error_set_basal_failed)
+ )
+ return@setOnClickListener
+ }
+
val type: PodActivationWizardActivity.Type =
if (podStateManager.activationProgress.isAtLeast(ActivationProgress.PRIME_COMPLETED)) {
PodActivationWizardActivity.Type.SHORT
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt
index d90498d2ba6..66bd9ea3790 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt
@@ -35,15 +35,15 @@ import app.aaps.pump.omnipod.common.queue.command.CommandHandleTimeChange
import app.aaps.pump.omnipod.common.queue.command.CommandResumeDelivery
import app.aaps.pump.omnipod.common.queue.command.CommandSilenceAlerts
import app.aaps.pump.omnipod.common.queue.command.CommandSuspendDelivery
-import app.aaps.pump.omnipod.dash.EventOmnipodDashPumpValuesChanged
+import app.aaps.pump.omnipod.common.EventOmnipodDashPumpValuesChanged
import app.aaps.pump.omnipod.dash.OmnipodDashPumpPlugin
import app.aaps.pump.omnipod.dash.R
import app.aaps.pump.omnipod.dash.databinding.OmnipodDashOverviewBinding
import app.aaps.pump.omnipod.dash.databinding.OmnipodDashOverviewBluetoothStatusBinding
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ActivationProgress
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodConstants
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ActivationProgress
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodConstants
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import dagger.android.support.DaggerFragment
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt
index dd1be218958..7ea81854593 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt
@@ -12,9 +12,9 @@ import app.aaps.pump.omnipod.common.keys.OmnipodBooleanPreferenceKey
import app.aaps.pump.omnipod.common.keys.OmnipodIntPreferenceKey
import app.aaps.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel
import app.aaps.pump.omnipod.dash.R
-import app.aaps.pump.omnipod.dash.driver.OmnipodDashManager
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertTrigger
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.OmnipodDashManager
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertTrigger
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import app.aaps.pump.omnipod.dash.history.DashHistory
import app.aaps.pump.omnipod.dash.history.data.InitialResult
import app.aaps.pump.omnipod.dash.history.data.ResolvedResult
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt
index d70a560dc50..f3c224a2231 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt
@@ -19,8 +19,8 @@ import app.aaps.pump.omnipod.common.definition.OmnipodCommandType
import app.aaps.pump.omnipod.common.keys.OmnipodBooleanPreferenceKey
import app.aaps.pump.omnipod.common.keys.OmnipodIntPreferenceKey
import app.aaps.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel
-import app.aaps.pump.omnipod.dash.driver.OmnipodDashManager
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.OmnipodDashManager
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import app.aaps.pump.omnipod.dash.history.DashHistory
import app.aaps.pump.omnipod.dash.history.data.BasalValuesRecord
import app.aaps.pump.omnipod.dash.history.data.InitialResult
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/deactivation/viewmodel/action/DashDeactivatePodViewModel.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/deactivation/viewmodel/action/DashDeactivatePodViewModel.kt
index ee13931efa3..b9600589479 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/deactivation/viewmodel/action/DashDeactivatePodViewModel.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/ui/wizard/deactivation/viewmodel/action/DashDeactivatePodViewModel.kt
@@ -12,7 +12,7 @@ import app.aaps.core.interfaces.rx.events.EventDismissNotification
import app.aaps.pump.omnipod.common.R
import app.aaps.pump.omnipod.common.queue.command.CommandDeactivatePod
import app.aaps.pump.omnipod.common.ui.wizard.deactivation.viewmodel.action.DeactivatePodViewModel
-import app.aaps.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
+import app.aaps.pump.omnipod.common.bledriver.pod.state.OmnipodDashPodStateManager
import io.reactivex.rxjava3.core.Single
import javax.inject.Inject
import javax.inject.Provider
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/Functions.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/Functions.kt
index 3cff877cb4a..04f6d9d2f33 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/Functions.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/Functions.kt
@@ -3,7 +3,7 @@ package app.aaps.pump.omnipod.dash.util
import app.aaps.core.data.pump.defs.PumpType
import app.aaps.core.interfaces.profile.Profile
import app.aaps.core.interfaces.pump.defs.determineCorrectBasalSize
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
import kotlin.math.roundToInt
fun mapProfileToBasalProgram(profile: Profile): BasalProgram {
diff --git a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/I8n.kt b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/I8n.kt
index a832e508961..8b25876fbdd 100644
--- a/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/I8n.kt
+++ b/pump/omnipod/dash/src/main/kotlin/app/aaps/pump/omnipod/dash/util/I8n.kt
@@ -2,10 +2,10 @@ package app.aaps.pump.omnipod.dash.util
import app.aaps.core.interfaces.resources.ResourceHelper
import app.aaps.pump.omnipod.dash.R
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.NotConnectedException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ScanException
-import app.aaps.pump.omnipod.dash.driver.comm.exceptions.ScanFailFoundTooManyException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.FailedToConnectException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.NotConnectedException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ScanException
+import app.aaps.pump.omnipod.common.bledriver.comm.exceptions.ScanFailFoundTooManyException
class I8n {
companion object {
diff --git a/pump/omnipod/dash/src/main/res/values-nl-rNL/strings.xml b/pump/omnipod/dash/src/main/res/values-nl-rNL/strings.xml
index cbd78e4303b..96d1569408d 100644
--- a/pump/omnipod/dash/src/main/res/values-nl-rNL/strings.xml
+++ b/pump/omnipod/dash/src/main/res/values-nl-rNL/strings.xml
@@ -8,9 +8,11 @@
HoeveelheidBronDatum
+ Type:Bluetooth statusBluetooth adres
+ Firmware %1$s / Bluetooth %2$sVerbindingskwaliteitLeveringsstatus
diff --git a/pump/omnipod/dash/src/main/res/values-pl-rPL/strings.xml b/pump/omnipod/dash/src/main/res/values-pl-rPL/strings.xml
index 5378727278c..1a8e7392cff 100644
--- a/pump/omnipod/dash/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/omnipod/dash/src/main/res/values-pl-rPL/strings.xml
@@ -12,6 +12,7 @@
Status BluetoothAdres Bluetooth
+ Firmware %1$s / Bluetooth %2$sJakość połączeniaStatus podania
@@ -28,6 +29,7 @@
Polecenie nie odebrane przez podaNieznany stan polecenia%1$.2f U/h, %2$d minut
+ %1$.2f UPodawanie insuliny zawieszoneRazem dostarczono: %1$.2f UUtracono połączenie z Podem
diff --git a/pump/omnipod/dash/src/main/res/values-sk-rSK/strings.xml b/pump/omnipod/dash/src/main/res/values-sk-rSK/strings.xml
index 380e7e1a611..f95cb6c8cf7 100644
--- a/pump/omnipod/dash/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/omnipod/dash/src/main/res/values-sk-rSK/strings.xml
@@ -28,10 +28,10 @@
Príkaz nebol odoslanýPríkaz nebol prijatý PodomNeznámy stav príkazu
- %1$.2f JI/h, %2$d minút
- %1$.2f JI
+ %1$.2f U/h, %2$d minut
+ %1$.2f UPodávanie inzulínu je pozastavené
- Celkovo podané: %1$.2f JI
+ Celkovo podané: %1$.2f UStratilo sa spojenie s PodomUž sa podáva iný bolusNedostatok inzulínu v zásobníku
diff --git a/pump/omnipod/dash/src/main/res/values-vi-rVN/strings.xml b/pump/omnipod/dash/src/main/res/values-vi-rVN/strings.xml
index 0972d79a0da..fd4b1304566 100644
--- a/pump/omnipod/dash/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/omnipod/dash/src/main/res/values-vi-rVN/strings.xml
@@ -39,17 +39,17 @@ Hãy chắc chắn bơm hết toàn bộ lượng insulin trong ống tiêm, nga
Insulin trong pod không đủLệnh chưa được xác nhậnNgười dùng yêu cầu
- Cáu hình đã được cài đặt
+ Hồ sơ đã được cài đặtViệc tạm dừng tiêm chưa được xác nhận! Vui lòng làm mới thủ công trạng thái Pod trong tab Omnipod và tiếp tục tiêm nếu cần.Việc tiêm insulin đã bị tạm dừng
- Múi giờ trên Pod khác với múi giờ trên điện thoại. Tốc độ basal không chính xác. Vui lòng chuyển cấu hình để khắc phục
- Cài đặt cấu hình basal mới thất bại. Đã tạm dừng tiêm
- Cài đặt cấu hình basal có thể đã thất bại. Việc tiêm có thể đã bị tạm dừng! Vui lòng làm mới thủ công trạng thái Pod trong tab Omnipod và tiếp tục tiêm nếu cần.
+ Múi giờ trên Pod khác với múi giờ trên điện thoại. Tốc độ liều nền không chính xác. Vui lòng chuyển Hồ sơ để khắc phục
+ Cài đặt Hồ sơ liều nền mới thất bại. Đã tạm dừng tiêm
+ Cài đặt Hồ sơ liều nền có thể đã thất bại. Việc tiêm có thể đã bị tạm dừng! Vui lòng làm mới thủ công trạng thái Pod trong tab Omnipod và tiếp tục tiêm nếu cần.Trạng thái tiêm bolus chưa chắc chắn. Vui lòng làm mới trạng thái Pod để xác nhận hoặc phủ nhận.
- Trạng thái basal tạm thời không như mong đợi! Nếu trước đó đang chạy basal tạm thời thì nó đã bị hủy. Vui lòng kiểm tra lượng insulin đã tiêm và lịch sử Pod
+ Trạng thái liều nền tạm thời không như mong đợi! Nếu trước đó đang chạy liều nền tạm thời thì nó đã bị hủy. Vui lòng kiểm tra lượng insulin đã tiêm và lịch sử PodĐang kiểm tra trạng thái tiêm
- Cài đặt basal tạm thời có thể đã thất bại. Nếu trước đó đang chạy basal tạm thời thì nó đã bị hủy. Vui lòng làm mới thủ công trạng thái Pod trong tab Omnipod.
- Chưa rõ kết quả hủy basal tạm thời
+ Cài đặt liều nền tạm thời có thể đã thất bại. Nếu trước đó đang chạy liều nền tạm thời thì nó đã bị hủy. Vui lòng làm mới thủ công trạng thái Pod trong tab Omnipod.
+ Chưa rõ kết quả hủy liều nền tạm thờiLệnh tiếp tục bơm chưa xác nhận. Hãy làm mới trạng thái Pod
- Việc hủy basal tạm thời có thể đã thất bại. Nếu trước đó đang chạy basal tạm thời thì có thể nó đã bị hủy. Vui lòng làm mới thủ công trạng thái Pod trong tab Omnipod.
+ Việc hủy liều nền tạm thời có thể đã thất bại. Nếu trước đó đang chạy liều nền tạm thời thì có thể nó đã bị hủy. Vui lòng làm mới thủ công trạng thái Pod trong tab Omnipod.
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/EnDecryptTest.kt
similarity index 94%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/EnDecryptTest.kt
index bb1a2c8e9e5..c5805ad6aa3 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/endecrypt/EnDecryptTest.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm.endecrypt
+package app.aaps.pump.omnipod.common.bledriver.comm.endecrypt
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.message.MessagePacket
+import app.aaps.pump.omnipod.common.bledriver.comm.message.MessagePacket
import app.aaps.shared.tests.AAPSLoggerTest
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessagePacketTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessagePacketTest.kt
similarity index 94%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessagePacketTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessagePacketTest.kt
index c661aeada2f..766a0427654 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessagePacketTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/MessagePacketTest.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.Id
+import app.aaps.pump.omnipod.common.bledriver.comm.Id
import com.google.common.truth.Truth.assertThat
import com.google.crypto.tink.subtle.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadJoinerTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadJoinerTest.kt
similarity index 84%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadJoinerTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadJoinerTest.kt
index ed6eba9f8ac..d39d0de5292 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadJoinerTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadJoinerTest.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.packet.PayloadJoiner
+import app.aaps.pump.omnipod.common.bledriver.comm.packet.PayloadJoiner
import com.google.common.truth.Truth.assertThat
import com.google.crypto.tink.subtle.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitJoinTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadSplitJoinTest.kt
similarity index 78%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitJoinTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadSplitJoinTest.kt
index 6d44a6a6d00..7d1e2f1c4e1 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitJoinTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadSplitJoinTest.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.packet.PayloadJoiner
-import app.aaps.pump.omnipod.dash.driver.comm.packet.PayloadSplitter
+import app.aaps.pump.omnipod.common.bledriver.comm.packet.PayloadJoiner
+import app.aaps.pump.omnipod.common.bledriver.comm.packet.PayloadSplitter
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Test
import java.util.Random
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitterTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadSplitterTest.kt
similarity index 87%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitterTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadSplitterTest.kt
index 4894b61e105..0983fe01848 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitterTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/PayloadSplitterTest.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.comm.packet.PayloadSplitter
+import app.aaps.pump.omnipod.common.bledriver.comm.packet.PayloadSplitter
import com.google.common.truth.Truth.assertThat
import com.google.crypto.tink.subtle.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncodingTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/StringLengthPrefixEncodingTest.kt
similarity index 92%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncodingTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/StringLengthPrefixEncodingTest.kt
index b05fa3349f9..2503147d774 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncodingTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/message/StringLengthPrefixEncodingTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.message
+package app.aaps.pump.omnipod.common.bledriver.comm.message
import app.aaps.core.utils.toHex
import com.google.common.truth.Truth.assertThat
diff --git a/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/KeyExchangeTest.kt
similarity index 90%
rename from pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/KeyExchangeTest.kt
index 75a2b59a9e9..77835371e17 100644
--- a/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/pair/KeyExchangeTest.kt
@@ -1,9 +1,9 @@
-package app.aaps.pump.omnipod.dash.driver.comm.pair
+package app.aaps.pump.omnipod.common.bledriver.comm.pair
import app.aaps.core.interfaces.configuration.Config
import app.aaps.core.utils.toHex
-import app.aaps.pump.omnipod.dash.driver.pod.util.RandomByteGenerator
-import app.aaps.pump.omnipod.dash.driver.pod.util.X25519KeyGenerator
+import app.aaps.pump.omnipod.common.bledriver.pod.util.RandomByteGenerator
+import app.aaps.pump.omnipod.common.bledriver.pod.util.X25519KeyGenerator
import app.aaps.shared.tests.AAPSLoggerTest
import app.aaps.shared.tests.TestBase
import com.google.common.truth.Truth.assertThat
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessageTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapMessageTest.kt
similarity index 91%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessageTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapMessageTest.kt
index dd97e3aaad5..fbb9c02fe38 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessageTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/EapMessageTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import app.aaps.core.utils.toHex
import app.aaps.shared.tests.AAPSLoggerTest
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/MilenageTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/MilenageTest.kt
similarity index 97%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/MilenageTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/MilenageTest.kt
index 98ebee95928..1a578a7eeda 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/MilenageTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/comm/session/MilenageTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.comm.session
+package app.aaps.pump.omnipod.common.bledriver.comm.session
import app.aaps.core.interfaces.configuration.Config
import app.aaps.core.utils.toHex
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/DeactivateCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/DeactivateCommandTest.kt
similarity index 90%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/DeactivateCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/DeactivateCommandTest.kt
index 681e5128dcc..a8487f133f2 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/DeactivateCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/DeactivateCommandTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/GetStatusCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetStatusCommandTest.kt
similarity index 82%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/GetStatusCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetStatusCommandTest.kt
index cd1aed3d2bf..1ff7ce80cc1 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/GetStatusCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetStatusCommandTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.response.ResponseType
+import app.aaps.pump.omnipod.common.bledriver.pod.response.ResponseType
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/GetVersionCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetVersionCommandTest.kt
similarity index 89%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/GetVersionCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetVersionCommandTest.kt
index 71ffc4ad71c..bfaa6ab6008 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/GetVersionCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/GetVersionCommandTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramAlertsCommandTest.kt
similarity index 90%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramAlertsCommandTest.kt
index 536a301c806..a685b212649 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramAlertsCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramAlertsCommandTest.kt
@@ -1,10 +1,10 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertTrigger
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepRepetitionType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertConfiguration
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertTrigger
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepRepetitionType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBasalCommandTest.kt
similarity index 97%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBasalCommandTest.kt
index 890a3c2fba4..4ce96d9730d 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBasalCommandTest.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBeepsCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBeepsCommandTest.kt
similarity index 79%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBeepsCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBeepsCommandTest.kt
index 454767432d9..1f226fa8f0c 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBeepsCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBeepsCommandTest.kt
@@ -1,7 +1,7 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBolusCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBolusCommandTest.kt
similarity index 84%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBolusCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBolusCommandTest.kt
index 0a002137fb2..19b8aec7090 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBolusCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramBolusCommandTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramTempBasalCommandTest.kt
similarity index 95%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramTempBasalCommandTest.kt
index 6d60f629abd..03969b7fc06 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramTempBasalCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/ProgramTempBasalCommandTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.ProgramReminder
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.ProgramReminder
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SetUniqueIdCommandTest.kt
similarity index 92%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SetUniqueIdCommandTest.kt
index 2d3f406c0d7..ea4120371dd 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SetUniqueIdCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SetUniqueIdCommandTest.kt
@@ -1,4 +1,4 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SilenceAlertsCommandTest.kt
similarity index 84%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SilenceAlertsCommandTest.kt
index e02ca398aca..de9269cd6fb 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SilenceAlertsCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SilenceAlertsCommandTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/StopDeliveryCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/StopDeliveryCommandTest.kt
similarity index 90%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/StopDeliveryCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/StopDeliveryCommandTest.kt
index 5a32f9f41ad..fbb4ddf9bb6 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/StopDeliveryCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/StopDeliveryCommandTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SuspendDeliveryCommandTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SuspendDeliveryCommandTest.kt
similarity index 82%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SuspendDeliveryCommandTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SuspendDeliveryCommandTest.kt
index 9671c1bf6cb..9bb3fd4ecc0 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/SuspendDeliveryCommandTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/command/SuspendDeliveryCommandTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.command
+package app.aaps.pump.omnipod.common.bledriver.pod.command
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BeepType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BeepType
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponseTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AlarmStatusResponseTest.kt
similarity index 89%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponseTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AlarmStatusResponseTest.kt
index 4babc92d468..e5d02a9ad84 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/AlarmStatusResponseTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/AlarmStatusResponseTest.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlarmType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlarmType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.DeliveryStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponseTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/DefaultStatusResponseTest.kt
similarity index 97%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponseTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/DefaultStatusResponseTest.kt
index 81f42a39ed5..92730feaaf3 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/DefaultStatusResponseTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/DefaultStatusResponseTest.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlertType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlertType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.DeliveryStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/NakResponseTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/NakResponseTest.kt
similarity index 77%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/NakResponseTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/NakResponseTest.kt
index bc7c5fdf821..3c096adecee 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/NakResponseTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/NakResponseTest.kt
@@ -1,8 +1,8 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.AlarmType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.NakErrorType
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.AlarmType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.NakErrorType
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/SetUniqueIdResponseTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/SetUniqueIdResponseTest.kt
similarity index 94%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/SetUniqueIdResponseTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/SetUniqueIdResponseTest.kt
index e1258de912c..e7d93f78a9f 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/SetUniqueIdResponseTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/SetUniqueIdResponseTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/VersionResponseTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/VersionResponseTest.kt
similarity index 93%
rename from pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/VersionResponseTest.kt
rename to pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/VersionResponseTest.kt
index 11775a474fd..5dcaa4d731a 100644
--- a/pump/omnipod/dash/src/test/kotlin/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/response/VersionResponseTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/common/bledriver/pod/response/VersionResponseTest.kt
@@ -1,6 +1,6 @@
-package app.aaps.pump.omnipod.dash.driver.pod.response
+package app.aaps.pump.omnipod.common.bledriver.pod.response
-import app.aaps.pump.omnipod.dash.driver.pod.definition.PodStatus
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.PodStatus
import com.google.common.truth.Truth.assertThat
import org.apache.commons.codec.binary.Hex
import org.junit.jupiter.api.Test
diff --git a/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/dash/util/FunctionsTest.kt b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/dash/util/FunctionsTest.kt
index 4ea71873e17..b663d75b521 100644
--- a/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/dash/util/FunctionsTest.kt
+++ b/pump/omnipod/dash/src/test/kotlin/app/aaps/pump/omnipod/dash/util/FunctionsTest.kt
@@ -2,7 +2,7 @@ package app.aaps.pump.omnipod.dash.util
import app.aaps.core.interfaces.profile.Profile
import app.aaps.core.interfaces.profile.Profile.ProfileValue
-import app.aaps.pump.omnipod.dash.driver.pod.definition.BasalProgram
+import app.aaps.pump.omnipod.common.bledriver.pod.definition.BasalProgram
import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.Test
import org.mockito.kotlin.mock
diff --git a/pump/omnipod/eros/src/main/java/app/aaps/pump/omnipod/eros/ui/ErosPodManagementActivity.kt b/pump/omnipod/eros/src/main/java/app/aaps/pump/omnipod/eros/ui/ErosPodManagementActivity.kt
index 56fb7ddbde0..55e8d6c0184 100644
--- a/pump/omnipod/eros/src/main/java/app/aaps/pump/omnipod/eros/ui/ErosPodManagementActivity.kt
+++ b/pump/omnipod/eros/src/main/java/app/aaps/pump/omnipod/eros/ui/ErosPodManagementActivity.kt
@@ -6,6 +6,7 @@ import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import app.aaps.core.interfaces.configuration.Config
+import app.aaps.core.interfaces.profile.ProfileFunction
import app.aaps.core.interfaces.queue.Callback
import app.aaps.core.interfaces.queue.CommandQueue
import app.aaps.core.interfaces.resources.ResourceHelper
@@ -57,6 +58,7 @@ class ErosPodManagementActivity : TranslatedDaggerAppCompatActivity() {
@Inject lateinit var uiInteraction: UiInteraction
@Inject lateinit var rh: ResourceHelper
@Inject lateinit var rxBus: RxBus
+ @Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resetRileyLinkConfigurationTaskProvider: Provider
private var disposables: CompositeDisposable = CompositeDisposable()
@@ -75,6 +77,16 @@ class ErosPodManagementActivity : TranslatedDaggerAppCompatActivity() {
supportActionBar?.setDisplayShowHomeEnabled(true)
binding.buttonActivatePod.setOnClickListener {
+ val profile = profileFunction.getProfile()
+ if (profile == null) {
+ OKDialog.show(
+ this,
+ rh.gs(app.aaps.pump.omnipod.common.R.string.omnipod_common_warning),
+ rh.gs(app.aaps.pump.omnipod.common.R.string.omnipod_common_error_failed_to_set_profile_empty_profile)
+ )
+ return@setOnClickListener
+ }
+
val type: PodActivationWizardActivity.Type = if (podStateManager.isPodInitialized
and podStateManager.activationProgress.isAtLeast(ActivationProgress.PRIMING_COMPLETED)
) {
diff --git a/pump/omnipod/eros/src/main/res/values-nl-rNL/strings.xml b/pump/omnipod/eros/src/main/res/values-nl-rNL/strings.xml
index d84ca935243..3d7cf56c108 100644
--- a/pump/omnipod/eros/src/main/res/values-nl-rNL/strings.xml
+++ b/pump/omnipod/eros/src/main/res/values-nl-rNL/strings.xml
@@ -7,6 +7,7 @@
Knop voor het uitlezen van het Pulslog weergeven in het Podbeheer menuKnop voor RileyLink statistieken weergeven in het Omnipod-tabbladLoggen van batterijwissel in Acties inschakelen
+ RileyLinkGeluid voor onzekere TBR notificaties ingeschakeldGeluid voor onzekere SMB notificaties ingeschakeldGeluid voor onzekere bolus notificaties ingeschakeld
@@ -15,6 +16,7 @@
BeschrijvingBronDatum
+ Type:%1$.2f E%1$.2f E, KH=%2$.1f gBasaal: %1$.2f E, Duur: %2$d min
@@ -58,6 +60,7 @@
RileyLink Configuratie resettenPulse log uitlezenPulse log aan het uitlezen…
+ Pulse LogPulse log (gekopieerd naar klembord)Vul een nieuw Pod in met voldoende insuline voor 3 dagen.\n\nLuister naar twee piepjes van de Pod tijdens het vulproces. Deze geven aan dat de minimale hoeveelheid van 80E is bereikt. Ga door met vullen (ook na het horen van de twee piepjes) totdat het vulspuitje volledig leeg is.\n\nNa het vullen van de Pod kun je op Volgendedrukken.\n\nOpmerking: verwijder op dit moment de naaldbeschermer van de Pod.\nOpmerking: Zet de RileyLink rechtop en plaats de Pod ongeveer vijf centimeter ervandaan.
diff --git a/pump/omnipod/eros/src/main/res/values-pl-rPL/strings.xml b/pump/omnipod/eros/src/main/res/values-pl-rPL/strings.xml
index 03b3ca45e08..44e5477b54e 100644
--- a/pump/omnipod/eros/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/omnipod/eros/src/main/res/values-pl-rPL/strings.xml
@@ -7,6 +7,7 @@
Pokaż przycisk Pulse Log w menu zarządzania PodemPokaż przycisk Statystyki RileyLink w menu zarządzania PodemWłącz rejestrowanie zmiany baterii w Akcjach
+ RileyLinkDźwięk dla niepewnych powiadomień TBR włączonyDźwięk dla niepewnych powiadomień SMB włączonyDźwięk dla niepewnych powiadomień o bolusie włączony
@@ -16,6 +17,7 @@
ŹródłoDataTyp:
+ %1$.2f U%1$.2f U, Węgl.=%2$.1f gDawka: %1$.2f U, Czas: %2$d min
diff --git a/pump/omnipod/eros/src/main/res/values-sk-rSK/strings.xml b/pump/omnipod/eros/src/main/res/values-sk-rSK/strings.xml
index 0295af35193..6b34bf4c5c4 100644
--- a/pump/omnipod/eros/src/main/res/values-sk-rSK/strings.xml
+++ b/pump/omnipod/eros/src/main/res/values-sk-rSK/strings.xml
@@ -17,9 +17,9 @@
ZdrojDátumTyp:
- %1$.2f JI
- %1$.2f JI, SACH=%2$.1f g
- Rýchlosť: %1$.2f JI, Doba trvania: %2$d minút
+ %1$.2f U
+ %1$.2f U, SACH=%2$.1f g
+ Rýchlosť: %1$.2f U, Doba trvania: %2$d minútRLBat: %1$d
@@ -52,7 +52,7 @@
Nepodarilo sa automaticky zmeniť čas na Pode. Mali by ste ručne synchronizovať čas na záložke Omnipod.Operácia nie je možná.\n\nNajskôr je nutné nakonfigurovať Omnipod, kým bude možné túto funkciu použiť.Nedá sa overiť, či bol bolus úspešný. Prosím manuálne overte, či Váš Pod podáva bolus počúvaním klikania. Ak ste si istý, že bolus nebol úspešný, mali by ste ručne odstrániť záznam o boluse z ošetrení, aj keď kliknete na \'Zrušiť bolus\' teraz!
- Nedá sa overiť, či bol bolus SMB (%1$.2f JI) úspešne podaný. Pokiaľ ste si istý, že bolus nebol podaný, mali by ste ručne odstrániť položku SMB z Ošetrení.
+ Nedá sa overiť, či bol bolus SMB (%1$.2f U) úspešne podaný. Pokiaľ ste si istý, že bolus nebol podaný, mali by ste ručne odstrániť položku SMB z Ošetrení.Dočasný bazál na Pode prebieha, ale AAPS o tomto dočasnom bazále nevie. Prosím zrušte svoj dočasný bazál ručne.Štatistika RileyLink
diff --git a/pump/omnipod/eros/src/main/res/values-vi-rVN/strings.xml b/pump/omnipod/eros/src/main/res/values-vi-rVN/strings.xml
index 77e6c42332b..338ecab17f3 100644
--- a/pump/omnipod/eros/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/omnipod/eros/src/main/res/values-vi-rVN/strings.xml
@@ -6,9 +6,7 @@
Hiển thị nhật ký Pulse trong menu Quản lý PodHiển thị thống kê RileyLink trong menu Quản lý Pod
- ChatGPT đã nói:
-
-Bật ghi nhật ký thay pin trong mục Actions
+ Bật ghi nhật ký thay pin trong Các thao tácRileyLinkĐã bật âm thanh thông báo TBR không chắc chắnĐã bật âm thanh thông báo SMB không chắc chắn
@@ -41,12 +39,12 @@ Bật ghi nhật ký thay pin trong mục ActionsKhông có phản hồi từ RileyLinkKết nối RileyLink bị gián đoạnKhông có phản hồi từ Pod
- Thiết lập cấu hình basal thất bại. Việc truyền insulin có thể đã bị tạm dừng! Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod và tiếp tục truyền nếu cần.
- Việc thiết lập cấu hình basal có thể đã thất bại. Truyền insulin có thể bị tạm dừng! Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod và tiếp tục truyền nếu cần.
- Thiết lập cấu hình basal thất bại. Việc truyền insulin đã bị tạm dừng! Vui lòng tiếp tục truyền thủ công từ tab Omnipod.
- Việc hủy basal tạm thời có thể đã thất bại. Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod.
- Thiết lập basal tạm thời thất bại. Nếu trước đó đã có basal tạm thời đang chạy, nó có thể đã bị hủy. Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod.
- Việc thiết lập basal tạm thời có thể đã thất bại. Nếu trước đó đã có basal tạm thời đang chạy, nó đã bị hủy. Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod.
+ Thiết lập Hồ sơ liều nền thất bại. Việc truyền insulin có thể đã bị tạm dừng! Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod và tiếp tục truyền nếu cần.
+ Việc thiết lập Hồ sơ liều nền có thể đã thất bại. Truyền insulin có thể bị tạm dừng! Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod và tiếp tục truyền nếu cần.
+ Thiết lập Hồ sơ liều nền thất bại. Việc truyền insulin đã bị tạm dừng! Vui lòng tiếp tục truyền thủ công từ tab Omnipod.
+ Việc hủy liều nền tạm thời có thể đã thất bại. Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod.
+ Thiết lập liều nền tạm thời thất bại. Nếu trước đó đã có liều nền tạm thời đang chạy, nó có thể đã bị hủy. Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod.
+ Việc thiết lập liều nền tạm thời có thể đã thất bại. Nếu trước đó đã có liều nền tạm thời đang chạy, nó đã bị hủy. Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod.Thời lượng TBR phải lớn hơn 0 và là bội số của %1$s phút.Việc cài đặt thời gian có thể đã thất bại. Truyền insulin có thể bị tạm dừng! Vui lòng làm mới trạng thái Pod thủ công từ tab Omnipod và tiếp tục truyền nếu cần.Cài đặt thời gian thất bại. Việc truyền insulin đã bị tạm dừng! Vui lòng tiếp tục truyền thủ công từ tab Omnipod.
@@ -55,7 +53,7 @@ Bật ghi nhật ký thay pin trong mục ActionsKhông thể thực hiện thao tác này.\n\nBạn cần cấu hình Omnipod trước khi có thể sử dụng chức năng này.Không thể xác minh liệu bolus có thành công hay không. Vui lòng kiểm tra thủ công xem Pod có đang tiêm bolus bằng cách nghe tiếng nhấp (clicks). Nếu bạn chắc chắn bolus không thành công, bạn nên xóa thủ công mục bolus trong Treatments, ngay cả khi bạn bấm \'Hủy bỏ bolus\' ngay bây giờ!Không thể xác minh liệu bolus SMB (%1$.2f U) có thành công hay không. Nếu bạn chắc chắn bolus không thành công, bạn nên xóa thủ công mục SMB trong Treatments.
- Một basal tạm thời đang chạy trên Pod, nhưng AAPS không nhận biết được basal tạm thời này. Vui lòng hủy basal tạm thời thủ công.
+ Một liều nền tạm thời đang chạy trên Pod, nhưng AAPS không nhận biết được liều nền tạm thời này. Vui lòng hủy liều nền tạm thời thủ công.Thống kê RileyLinkĐang chờ kết nối với RileyLink…
diff --git a/pump/rileylink/src/main/kotlin/app/aaps/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.kt b/pump/rileylink/src/main/kotlin/app/aaps/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.kt
index 5c5c9162e49..b901949b3f1 100644
--- a/pump/rileylink/src/main/kotlin/app/aaps/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.kt
+++ b/pump/rileylink/src/main/kotlin/app/aaps/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.kt
@@ -6,8 +6,8 @@ import app.aaps.pump.common.hw.rileylink.R
enum class RileyLinkEncodingType(val value: Byte, val key: String?, @StringRes val friendlyName: Int? = null) {
None(0x00, null), // No encoding on RL
Manchester(0x01, null), // Manchester encoding on RL (for Omnipod)
- FourByteSixByteLocal(0x00, "medtronic_pump_encoding_4b6b_local", R.string.medtronic_pump_encoding_4b6b_rileylink),
- FourByteSixByteRileyLink(0x02, "medtronic_pump_encoding_4b6b_rileylink", R.string.medtronic_pump_encoding_4b6b_local), // 4b6b encoding on RL (for Medtronic)
+ FourByteSixByteLocal(0x00, "medtronic_pump_encoding_4b6b_local", R.string.medtronic_pump_encoding_4b6b_local),
+ FourByteSixByteRileyLink(0x02, "medtronic_pump_encoding_4b6b_rileylink", R.string.medtronic_pump_encoding_4b6b_rileylink), // 4b6b encoding on RL (for Medtronic)
; // No encoding on RL, but 4b6b encoding in code
companion object {
diff --git a/pump/rileylink/src/main/res/values-nl-rNL/strings.xml b/pump/rileylink/src/main/res/values-nl-rNL/strings.xml
index de4325bdec6..ebcb257e314 100644
--- a/pump/rileylink/src/main/res/values-nl-rNL/strings.xml
+++ b/pump/rileylink/src/main/res/values-nl-rNL/strings.xml
@@ -9,6 +9,10 @@
Time-out op de communicatiePomp niet bereikbaarOngeldige configuratie
+ Software 4b6b codering
+ Hardware 4b6b codering
+ VS & Canada (916 MHz)
+ Wereldwijd (868 Mhz)ScannenStop
diff --git a/pump/rileylink/src/main/res/values-pl-rPL/strings.xml b/pump/rileylink/src/main/res/values-pl-rPL/strings.xml
index 7c0cfd650d6..da2ca638fb9 100644
--- a/pump/rileylink/src/main/res/values-pl-rPL/strings.xml
+++ b/pump/rileylink/src/main/res/values-pl-rPL/strings.xml
@@ -9,6 +9,10 @@
Przekroczony limit czasu połączeniaPompa nieosiągalnaNieprawidłowa konfiguracja
+ Lokalne kodowanie 4b6b (w oprogramowaniu)
+ Sprzętowe kodowanie 4b6b (w RileyLink)
+ USA & Kanada (916 MHz)
+ Świat (868 Mhz)SkanujStop
diff --git a/pump/rileylink/src/main/res/values-vi-rVN/strings.xml b/pump/rileylink/src/main/res/values-vi-rVN/strings.xml
index 6998475f107..c2211a9d308 100644
--- a/pump/rileylink/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/rileylink/src/main/res/values-vi-rVN/strings.xml
@@ -7,7 +7,7 @@
Kích hoạtLỗi giao tiếpHết thời gian giao tiếp
- Không thể kết nối với Pump
+ Không thể kết nối với BơmCấu hình không hợp lệMã hóa 4b6b phần mềmMã hóa 4b6b phần cứng
@@ -31,7 +31,7 @@
Cài đặtLịch sửTrạng thái RileyLink
- Trạng thái Pump
+ Trạng thái BơmCài đặt RileyLinkRileyLinkĐịa chỉ:
@@ -49,8 +49,8 @@
Phiên bản phần mềm:BLE113: %1$s\nCC110: %2$sFw: %1$s\nHw: %2$s
- Số serial Pump:
- Tần số Pump:
+ Số serial Bơm:
+ Tần số Bơm:%1$.2f MHzĐang khởi tạo Bluetooth…
@@ -59,8 +59,8 @@
Chưa bắt đầuĐang khởi tạo RileyLink…RileyLink lỗi
- Đang hiệu chỉnh RileyLink và Pump
- Gặp sự cố khi kết nối với Pump
+ Đang hiệu chỉnh RileyLink và Bơm
+ Gặp sự cố khi kết nối với BơmĐã kết nốiRileyLink sẵn sàng
@@ -69,10 +69,10 @@
Bluetooth chưa được bậtKhông có bộ điều hợp BluetoothHiệu chỉnh thất bại
- Không thể kết nối với Pump
+ Không thể kết nối với BơmKhông thể kết nối với Pod
- Medtronic Pump
+ Bơm MedtronicOmnipod (Eros)Hiển thị mức pin được báo cáo bởi OrangeLink/EmaLink/DiaLink
diff --git a/pump/virtual/src/main/res/values-vi-rVN/strings.xml b/pump/virtual/src/main/res/values-vi-rVN/strings.xml
index 57a198b0955..f56bd88ae97 100644
--- a/pump/virtual/src/main/res/values-vi-rVN/strings.xml
+++ b/pump/virtual/src/main/res/values-vi-rVN/strings.xml
@@ -1,13 +1,13 @@
- Kiểu bơm ảo
- Cấu hình bơm
- Bolus: Bước = %1$s\nBolus mở rộng: [Bước = %2$s, Thời gian = %3$s phút - %4$s giờ]\nBasal: Bước = %5$s\nTBR: %6$s (bởi %7$s), Thời gian = %8$s phút - %9$s giờ\n%10$s
+ Kiểu Bơm mô phỏng
+ Định nghĩa máy bơm
+ Bolus: Bước = %1$s\nBolus kéo dài: [Bước = %2$s, Thời gian = %3$s phút - %4$s giờ]\nBasal: Bước = %5$s\nTBR: %6$s (bởi %7$s), Thời gian = %8$s phút - %9$s giờ\n%10$sVPUMPTích hợp bơm cho các loại bơm chưa có driver (Chế độ Mạch hở – Open Loop)
- VIRTUAL PUMP
- Cài đặt máy bơm ảo
+ BƠM MÔ PHỎNG
+ Cài đặt Bơm mô phỏng
- *Chỉ hỗ trợ các giá trị rời rạc, không hỗ trợ khoảng giá trị, làm mức độ chi tiết cho basal/bolus trong bơm ảo.
+ *Chỉ hỗ trợ các giá trị rời rạc, không hỗ trợ khoảng giá trị, làm mức độ chi tiết cho basal/bolus trong Bơm mô phỏng.
diff --git a/shared/impl/build.gradle.kts b/shared/impl/build.gradle.kts
index 3b87bb9e24a..634eb1b75b6 100644
--- a/shared/impl/build.gradle.kts
+++ b/shared/impl/build.gradle.kts
@@ -28,6 +28,8 @@ dependencies {
api(libs.com.caverock.androidsvg)
+ api(libs.kotlinx.datetime)
+
api(libs.io.reactivex.rxjava3.rxandroid)
api(libs.net.danlew.android.joda)
diff --git a/shared/impl/src/main/kotlin/app/aaps/shared/impl/utils/DateUtilImpl.kt b/shared/impl/src/main/kotlin/app/aaps/shared/impl/utils/DateUtilImpl.kt
index 829a3877757..1bd2041f0a7 100644
--- a/shared/impl/src/main/kotlin/app/aaps/shared/impl/utils/DateUtilImpl.kt
+++ b/shared/impl/src/main/kotlin/app/aaps/shared/impl/utils/DateUtilImpl.kt
@@ -79,16 +79,16 @@ class DateUtilImpl @Inject constructor(
}
override fun secondsOfTheDayToMillisecondsOfHoursAndMinutes(seconds: Int): Long {
- val startOfToday = LocalDate.now(clock).atStartOfDay(systemZone)
+ val today = LocalDate.now(clock)
val totalMinutes = seconds / 60
- val targetTime = startOfToday.plusMinutes(totalMinutes.toLong())
- return targetTime.toInstant().toEpochMilli()
+ val time = java.time.LocalTime.of(totalMinutes / 60, totalMinutes % 60)
+ return today.atTime(time).atZone(systemZone).toInstant().toEpochMilli()
}
override fun secondsOfTheDayToMilliseconds(seconds: Int): Long {
- val startOfToday = LocalDate.now(clock).atStartOfDay(systemZone)
- val targetTime = startOfToday.plusSeconds(seconds.toLong())
- return targetTime.toInstant().toEpochMilli()
+ val today = LocalDate.now(clock)
+ val time = java.time.LocalTime.ofSecondOfDay(seconds.toLong())
+ return today.atTime(time).atZone(systemZone).toInstant().toEpochMilli()
}
override fun toSeconds(hhColonMm: String): Int {
diff --git a/shared/impl/src/main/res/values-vi-rVN/strings.xml b/shared/impl/src/main/res/values-vi-rVN/strings.xml
index 86911b1923b..41faca78bf6 100644
--- a/shared/impl/src/main/res/values-vi-rVN/strings.xml
+++ b/shared/impl/src/main/res/values-vi-rVN/strings.xml
@@ -1,7 +1,7 @@
Hình nền
- Biểu đồ (đường huyết, insulin nền, đường dự đoán...)
+ Biểu đồ (đường huyết, liều nền, đường dự đoán...)Hình ảnh phía trước biểu đồ và phía sau các ô nhập liệuGhi chú 1Ghi chú 2
@@ -12,11 +12,11 @@
Tổng IOB hoặc (Bolus_IOB | Basal_IOB) nếu ở chế độ chi tiết (từ AAPSClient hoặc AAPSClient2)Giá trị COB (từ AAPSClient hoặc AAPSClient2)Delta BG ngắn hạn (từ AAPSClient hoặc AAPSClient2)
- Delta BG trung bình (15 phút) (từ AAPSClient hoặc AAPSClient2)
+ Trung bình độ lệch đường huyết (15 phút) (từ AAPSClient hoặc AAPSClient2)Mục tiêu tạm thời hoặc Mục tiêu tạm thời thấp – Mục tiêu tạm thời cao (từ AAPSClient hoặc AAPSClient2)Mức insulin trong ống chứa (từ AAPSClient hoặc AAPSClient2)Pin vòng lặp toàn cục (%) (từ AAPSClient hoặc AAPSClient2)
- Insulin nền (từ AAPSClient/AAPSClient2)
+ Tỷ lệ liều nền (từ AAPSClient/AAPSClient2)Giá trị BGI (từ AAPSClient hoặc AAPSClient2)Tổng hợp trạng thái (từ AAPSClient hoặc AAPSClient2)Trạng thái vòng lặp & thời gian (AAPSClient/AAPSClient2)
@@ -28,13 +28,13 @@
Tổng IOB hoặc (Bolus IOB | Basal IOB) nếu ở chế độ chi tiếtNhãn COBGiá trị COB
- Chênh lệch đường huyết
- Chênh lệch BG trung bình (15 phút)
+ Độ lệch đường huyết
+ Trung bình độ lệch đường huyết (15 phút)Mục tiêu tạm thời (Thấp - Cao)Mức InsulinPin điện thoại (%)Global loop battery (%)
- Tỷ lệ liều Basal
+ Tỷ lệ liều nềnGiá trị BGITóm tắt trạng tháiThời gian (HH:MM or HH:MM:SS)
diff --git a/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt b/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt
index 035c9594e99..d484ad0c233 100644
--- a/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt
+++ b/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt
@@ -1,5 +1,6 @@
package app.aaps.shared.tests
+import android.content.SharedPreferences
import android.content.res.Resources
import android.content.res.TypedArray
import androidx.preference.PreferenceManager
@@ -50,11 +51,14 @@ import dagger.android.AndroidInjector
import dagger.android.DaggerApplication
import dagger.android.HasAndroidInjector
import org.json.JSONObject
+import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.mockito.ArgumentMatchers.anyDouble
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
+import org.mockito.MockedStatic
+import org.mockito.Mockito
import org.mockito.invocation.InvocationOnMock
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
@@ -78,6 +82,8 @@ open class TestBaseWithProfile : TestBase() {
@Mock lateinit var constraintsChecker: ConstraintsChecker
@Mock lateinit var theme: Resources.Theme
@Mock lateinit var typedArray: TypedArray
+ @Mock lateinit var sharedPreferences: SharedPreferences
+ @Mock lateinit var sharedPreferencesEditor: SharedPreferences.Editor
lateinit var dateUtil: DateUtil
lateinit var profileUtil: ProfileUtil
@@ -148,6 +154,8 @@ open class TestBaseWithProfile : TestBase() {
lateinit var profileSwitch: PS
lateinit var testPumpPlugin: TestPumpPlugin
+ private lateinit var mockedPreferenceManager: MockedStatic
+
var now = 1656358822000L
@Suppress("PropertyName") val TESTPROFILENAME = "someProfile"
@@ -160,6 +168,19 @@ open class TestBaseWithProfile : TestBase() {
invalidProfileJSON = "{\"dia\":\"1\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
+
+ // Mock SharedPreferences for AdaptiveListIntPreference
+ whenever(sharedPreferences.getInt(any(), any())).thenReturn(-1)
+ whenever(sharedPreferences.edit()).thenReturn(sharedPreferencesEditor)
+ whenever(sharedPreferencesEditor.remove(any())).thenReturn(sharedPreferencesEditor)
+ whenever(sharedPreferencesEditor.putString(any(), any())).thenReturn(sharedPreferencesEditor)
+
+ // Mock static PreferenceManager.getDefaultSharedPreferences
+ mockedPreferenceManager = Mockito.mockStatic(android.preference.PreferenceManager::class.java)
+ mockedPreferenceManager.`when` {
+ android.preference.PreferenceManager.getDefaultSharedPreferences(any())
+ }.thenReturn(sharedPreferences)
+
preferenceManager = PreferenceManager(context)
dateUtil = spy(DateUtilImpl(context))
decimalFormatter = DecimalFormatterImpl(rh)
@@ -310,6 +331,11 @@ open class TestBaseWithProfile : TestBase() {
glucoseStatusCalculatorSMB = GlucoseStatusCalculatorSMB(aapsLogger, iobCobCalculator, dateUtil, decimalFormatter, DeltaCalculator(aapsLogger))
}
+ @AfterEach
+ fun cleanupMock() {
+ mockedPreferenceManager.close()
+ }
+
fun getValidProfileStore(): ProfileStore {
val json = JSONObject()
val store = JSONObject()
diff --git a/ui/src/main/kotlin/app/aaps/ui/dialogs/CarbsDialog.kt b/ui/src/main/kotlin/app/aaps/ui/dialogs/CarbsDialog.kt
index c62c6004b86..ec8a60f48ed 100644
--- a/ui/src/main/kotlin/app/aaps/ui/dialogs/CarbsDialog.kt
+++ b/ui/src/main/kotlin/app/aaps/ui/dialogs/CarbsDialog.kt
@@ -200,9 +200,9 @@ class CarbsDialog : DialogFragmentWithDate() {
((activeTT.timestamp + activeTT.duration) - now) / 60000
// Prevent auto-checking HypoTT when:
- // 1. Active TT target is above Constants.ALLOW_SMB_WITH_HIGH_TT
+ // 1. Active TT target is above normal target
// 2. Active TT lasts longer than the hypoTT preset
- if (activeTarget > Constants.ALLOW_SMB_WITH_HIGH_TT && remainingDurationMin > hypoTTDuration) {
+ if (activeTarget > Constants.NORMAL_TARGET_MGDL && remainingDurationMin > hypoTTDuration) {
shouldAutoCheckHypo = false
}
}
diff --git a/ui/src/main/kotlin/app/aaps/ui/dialogs/FillDialog.kt b/ui/src/main/kotlin/app/aaps/ui/dialogs/FillDialog.kt
index 17d31664908..c57e44fe21c 100644
--- a/ui/src/main/kotlin/app/aaps/ui/dialogs/FillDialog.kt
+++ b/ui/src/main/kotlin/app/aaps/ui/dialogs/FillDialog.kt
@@ -172,7 +172,7 @@ class FillDialog(val fm: FragmentManager) : DialogFragmentWithDate() {
ValueWithUnit.TEType(TE.Type.CANNULA_CHANGE)
).filterNotNull()
).subscribe()
- if (preferences.get(BooleanKey.SiteRotationManageCgm)) {
+ if (preferences.get(BooleanKey.SiteRotationManagePump)) {
SiteRotationDialog().also { srd ->
srd.arguments = Bundle().also { args ->
args.putLong("time", eventTime)
diff --git a/ui/src/main/kotlin/app/aaps/ui/dialogs/InsulinDialog.kt b/ui/src/main/kotlin/app/aaps/ui/dialogs/InsulinDialog.kt
index 30910d2b98e..d076ad8c0a6 100644
--- a/ui/src/main/kotlin/app/aaps/ui/dialogs/InsulinDialog.kt
+++ b/ui/src/main/kotlin/app/aaps/ui/dialogs/InsulinDialog.kt
@@ -128,7 +128,7 @@ class InsulinDialog : DialogFragmentWithDate() {
}
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
- if (loop.runningMode.isSuspended() || !pump.isInitialized()) {
+ if (loop.runningMode.isPumpSuspended() || !pump.isInitialized()) {
binding.recordOnly.isChecked = true
binding.recordOnly.isEnabled = false
binding.recordOnly.setTextColor(rh.gac(app.aaps.core.ui.R.attr.warningColor))
diff --git a/ui/src/main/res/values-nb-rNO/strings.xml b/ui/src/main/res/values-nb-rNO/strings.xml
index ccc5fea2086..588ce27f47a 100644
--- a/ui/src/main/res/values-nb-rNO/strings.xml
+++ b/ui/src/main/res/values-nb-rNO/strings.xml
@@ -48,7 +48,7 @@
Profil for stedsadministrasjonHer angir du om du vil håndtere pumpeområde, CGM-område eller begge deler. Denne innstillingen brukes til automatisk å vise dialogen for stedsadministrasjon hver gang en ny registrering oppdagesKlikk nedenfor for å velge stedsplassering
- Registrer stedsplassering
+ Registrer stedRedigerInfusjonssted: %1$sOmrådepil: %1$s
diff --git a/ui/src/main/res/values-nl-rNL/strings.xml b/ui/src/main/res/values-nl-rNL/strings.xml
index 1705d746f3e..089d6aa02ee 100644
--- a/ui/src/main/res/values-nl-rNL/strings.xml
+++ b/ui/src/main/res/values-nl-rNL/strings.xml
@@ -38,6 +38,22 @@
%1$.0fg IC: %2$.1fTotaal
+ Voorzijde
+ Achterzijde
+ Man
+ Vrouw
+ Kind
+ Gebruikers profiel
+ Het gebruikers profiel wordt gebruikt om meest gebruikte locaties te tonen voor mannen, vrouwen of kinderen
+ Management profiel voor infuus locaties
+ Hier stellen we in of je infuus locaties voor Pomp, CGM of beide wilt beheren. Deze instelling wordt gebruikt om automatisch een nieuwe beheers dialoog te starten
+ Klik hieronder om een site te selecteren
+ Site locatie vastleggen
+ Bewerk
+ Site locatie: %1$s
+ Site pijl %1$s
+ Notitie: %1$s
+ Notitie verwijderdZorg ervoor dat de hoeveelheid overeenkomt met de specificatie van uw infusieset!Markeer een infuuswissel in NS
@@ -136,6 +152,10 @@
Bevestig alstublieft de behandelingHerberekenen
+ Gebruik zwarte kleur
+ Widget configuratie
+ Totdat gewijzigd
+ BeperkingenBeideAlleen positief
diff --git a/ui/src/main/res/values-pl-rPL/strings.xml b/ui/src/main/res/values-pl-rPL/strings.xml
index 900a3a7046d..3184b10215d 100644
--- a/ui/src/main/res/values-pl-rPL/strings.xml
+++ b/ui/src/main/res/values-pl-rPL/strings.xml
@@ -38,6 +38,22 @@
%1$.0fg IC: %2$.1fRazem
+ Przód
+ Tył
+ Mężczyzna
+ Kobieta
+ Dziecko
+ Profil użytkownika
+ Profil użytkownika pokazuje najczęstsze miejsca wkłucia sensorów, pomp i kaniul dostępne u mężczyzn, kobiet lub dzieci
+ Zarządzanie miejscami
+ Tutaj ustawisz czy chcesz odnotowywać miejsca wkłucia sensora CGM, pompy bezdrenowej lub kaniuli, czy oba te typy miejsc. To ustawienie decyduje, czy przy wykrytej zmianie sensora CGM lub miejsca wkłucia - pokazać okno dialogowe do wskazania miejsca wkłucia.
+ Kliknij poniżej, aby wybrać miejsce
+ Zapisz miejsce wkłucia
+ Edytuj
+ Miejsce: %1$s
+ Orientacja miejsca: %1$s
+ Notatka: %1$s
+ Notatka usuniętaProszę upewnij się, że ilość wypełnienia odpowiada ilości właściwej dla twojego wkłucia!Zapisz zmianę wkłucia
@@ -136,6 +152,10 @@
Proszę potwierdzić leczeniePrzelicz
+ Użyj czarnego koloru
+ Konfiguracja widżetu
+ Do zmiany
+ OgraniczeniaObieTylko pozytywne
diff --git a/ui/src/main/res/values-sk-rSK/strings.xml b/ui/src/main/res/values-sk-rSK/strings.xml
index b0227b9a903..c7d36dcd5e8 100644
--- a/ui/src/main/res/values-sk-rSK/strings.xml
+++ b/ui/src/main/res/values-sk-rSK/strings.xml
@@ -126,8 +126,8 @@
Predvolený profilAktuálny profilDostupný profil
- Vek: %1$.0f CDD: %2$.0f JI
- Vek: %1$d CDD: %2$.0f JI %3$d%%
+ Vek: %1$.0f CDD: %2$.0f U
+ Vek: %1$d CDD: %2$.0f U %3$d%%Vek: %1$.0f Hmotnosť: %2$.0f kgPredvolený DPV profilNeplatný vstup %
diff --git a/ui/src/main/res/values-vi-rVN/strings.xml b/ui/src/main/res/values-vi-rVN/strings.xml
index 963df85f480..e0ea787bd22 100644
--- a/ui/src/main/res/values-vi-rVN/strings.xml
+++ b/ui/src/main/res/values-vi-rVN/strings.xml
@@ -1,13 +1,13 @@
- Giới hạn liều bolus đã bật
+ Áp dụng giới hạn liều bolusGiới hạn Carbs đã bậtTTĐã hủy hộp thoại
- Start Activity TT
- Start Eating soon TT
- Start Hypo TT
- Time offset
+ Bắt đầu hoạt động thể lực (TT)
+ Sắp ăn (TT)
+ Bắt đầu hạ đường huyết (TT)
+ Lệch thời gianphútNhắc tiêm bolus sauđặt lời nhắc
@@ -24,10 +24,10 @@
Cân nặng không hợp lệID:Áp dụng
- Tuổi
+ Đã dùngCân nặng
- Cấu hình phổ biến:
- Lưu ý: Chỉ những dữ liệu trên màn hình này sẽ được tải lên ẩn danh. Mỗi cài đặt AAPS sẽ có một ID riêng. Bạn có thể gửi lại dữ liệu nếu thay đổi Cấu hình chính, nhưng hãy để ứng dụng chạy ít nhất một tuần để kết quả về thời gian trong phạm vi được hiển thị. Cảm ơn bạn đã đóng góp dữ liệu.
+ Hồ sơ phổ biến:
+ Lưu ý: Chỉ những dữ liệu trên màn hình này sẽ được tải lên ẩn danh. Mỗi cài đặt AAPS sẽ có một ID riêng. Bạn có thể gửi lại dữ liệu nếu thay đổi hồ sơ chính, nhưng hãy để ứng dụng chạy ít nhất một tuần để kết quả về thời gian trong phạm vi được hiển thị. Cảm ơn bạn đã đóng góp dữ liệu.Loại đường huyếtKhácMáy đo
@@ -43,9 +43,9 @@
NamNữTrẻ em
- Cấu hình người dùng
- Mô tả cấu hình người dùng được dùng để hiển thị các vị trí tiêm phổ biến nhất đối với nam, nữ hoặc trẻ em
- Cấu hình quản lý vị trí tiêm
+ Hồ sơ người dùng
+ Mô tả Hồ sơ người dùng được dùng để hiển thị các vị trí tiêm phổ biến nhất đối với nam, nữ hoặc trẻ em
+ Hồ sơ quản lý vị trí tiêmTại đây bạn có thể chọn quản lý vị trí tiêm, vị trí cảm biến CGM hoặc cả hai. Thiết lập này sẽ được dùng để tự động hiển thị hộp thoại quản lý vị trí mỗi khi phát hiện mục nhập mớiNhấn bên dưới để chọn vị tríGhi lại vị trí tiêm/cảm biến
@@ -69,14 +69,14 @@
Tạm dừng vòng lặp 2 giờTạm dừng vòng lặp 3 giờTạm dừng vòng lặp 10 giờ
- Ngắt kết nối pump
- Ngắt kết nối pump trong 15 phút
- Ngắt kết nối pump trong 30 phút
- Ngắt kết nối pump trong 1 giờ
- Ngắt kết nối pump trong 2 giờ
- Ngắt kết nối pump trong 3 giờ
+ Ngắt kết nối bơm
+ Ngắt kết nối bơm trong 15 phút
+ Ngắt kết nối bơm trong 30 phút
+ Ngắt kết nối bơm trong 1 giờ
+ Ngắt kết nối bơm trong 2 giờ
+ Ngắt kết nối bơm trong 3 giờTiếp tục
- Kết nối lại pump
+ Kết nối lại bơm15 phút30 phút1 giờ
@@ -100,10 +100,10 @@
Carbs:Ratio:IOB:
- Corr
+ Hiệu chỉnhBữa ănMồi bơm
- Carbs and bolus
+ Carb và liều bolusHiển thị bản ghi không hợp lệ / đã xóaẨn bản ghi không hợp lệ / đã xóaHiện các bản ghi không hợp lệ
@@ -116,23 +116,23 @@
Hiện dữ liệu vòng lặpẨn dữ liệu vòng lặp
- Cấu hình 1
- Cấu hình 2
- Loại Cấu hình
+ Hồ sơ 1
+ Hồ sơ 2
+ Loại hồ sơ% của liều nềnChọn:
- So sánh các Cấu hình
- Hỗ trợ cấu hình
- Cấu hình mặc định
- Cấu hình hiện tại
- Cấu hình có sẵn
+ So sánh các Hồ sơ
+ Hỗ trợ Hồ sơ
+ Hồ sơ mặc định
+ Hồ sơ hiện tại
+ Hồ sơ có sẵnAge: %1$d TDD: %2$.0f UAge: %1$d TDD: %2$.0f U %3$d%%Age: %1$d Weight: %2$.0f kg
- Cấu hình mặc định DPV
+ Hồ sơ mặc định DPVGiá trị % không hợp lệ
- Tỷ lệ liều Basal
+ Tỷ lệ liều nềnĐÃ NHẤN DỪNG
diff --git a/wear/src/main/kotlin/app/aaps/wear/interaction/actions/WizardResultFragment.kt b/wear/src/main/kotlin/app/aaps/wear/interaction/actions/WizardResultFragment.kt
index 204ad72ac41..7f8407c2217 100644
--- a/wear/src/main/kotlin/app/aaps/wear/interaction/actions/WizardResultFragment.kt
+++ b/wear/src/main/kotlin/app/aaps/wear/interaction/actions/WizardResultFragment.kt
@@ -173,14 +173,32 @@ class WizardResultFragment : Fragment() {
builder.addCalculationRow(calculationRowsContainer, WizardCalculationRow(getString(R.string.wizard_result_total), totalInsulin))
+ // Calculate new IOB if IOB was used in calculation
+ // New IOB = Total Insulin - Current IOB (because IOB is subtracted in wizard)
+ // Only calculate if IOB was actually used (totalIob is not NaN means it was included)
+ val newIob = if (!totalIob.isNaN()) {
+ totalInsulin - totalIob // totalIob is negative so this is addition
+ } else {
+ null // Don't show New IOB if IOB wasn't used in calculation
+ }
+
// Setup collapsible calculation details
- setupCalculationToggle(view)
+ setupCalculationToggle(view, newIob)
}
- private fun setupCalculationToggle(view: View) {
+ private fun setupCalculationToggle(view: View, newIob: Double?) {
val calculationHeader = view.findViewById(R.id.calculation_header)
val calculationDetails = view.findViewById(R.id.calculation_details)
val expandIcon = view.findViewById(R.id.expand_icon)
+ val newIobText = view.findViewById(R.id.new_iob_text)
+
+ // Set new IOB value - only show if IOB was used in calculation
+ if (newIob != null) {
+ newIobText.text = getString(R.string.wizard_result_new_iob, decimalFormat.format(newIob))
+ newIobText.visibility = View.VISIBLE
+ } else {
+ newIobText.visibility = View.GONE
+ }
var isExpanded = false
diff --git a/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt b/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt
index 7f77a4ae2b4..9e3255d7d63 100644
--- a/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt
+++ b/wear/src/main/kotlin/app/aaps/wear/watchfaces/utils/BgGraphBuilder.kt
@@ -12,8 +12,14 @@ import lecho.lib.hellocharts.model.AxisValue
import lecho.lib.hellocharts.model.Line
import lecho.lib.hellocharts.model.LineChartData
import lecho.lib.hellocharts.model.PointValue
-import java.util.Calendar
-import java.util.GregorianCalendar
+import kotlinx.datetime.Clock
+import kotlinx.datetime.DateTimeUnit
+import kotlinx.datetime.Instant
+import kotlinx.datetime.LocalDateTime
+import kotlinx.datetime.TimeZone
+import kotlinx.datetime.plus
+import kotlinx.datetime.toInstant
+import kotlinx.datetime.toLocalDateTime
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
@@ -402,16 +408,14 @@ class BgGraphBuilder(
val xAxisValues: MutableList = ArrayList()
//get the time-tick at the full hour after start_time
- val startGC = GregorianCalendar()
- startGC.timeInMillis = startingTime
- startGC[Calendar.MILLISECOND] = 0
- startGC[Calendar.SECOND] = 0
- startGC[Calendar.MINUTE] = 0
- startGC.add(Calendar.HOUR, 1)
+ val tz = TimeZone.currentSystemDefault()
+ val startLocal = Instant.fromEpochMilliseconds(startingTime).toLocalDateTime(tz)
+ val truncatedHour = LocalDateTime(startLocal.year, startLocal.month, startLocal.dayOfMonth, startLocal.hour, 0)
+ var hourInstant = truncatedHour.toInstant(tz).plus(1, DateTimeUnit.HOUR, tz)
//Display current time on the graph
xAxisValues.add(AxisValue(fuzz(timeNow)).setLabel(dateUtil.timeString(timeNow)))
- var hourTick = startGC.timeInMillis
+ var hourTick = hourInstant.toEpochMilliseconds()
// add all full hours within the timeframe
while (hourTick < endingTime) {
@@ -422,8 +426,9 @@ class BgGraphBuilder(
xAxisValues.add(AxisValue(fuzz(hourTick)).setLabel(""))
}
- //increment by one hour
- hourTick += (60 * 60 * 1000).toLong()
+ //increment by one hour using wall-clock time to handle DST correctly
+ hourInstant = hourInstant.plus(1, DateTimeUnit.HOUR, tz)
+ hourTick = hourInstant.toEpochMilliseconds()
}
xAxis.values = xAxisValues
xAxis.textSize = 10
diff --git a/wear/src/main/res/layout/fragment_wizard_result.xml b/wear/src/main/res/layout/fragment_wizard_result.xml
index 5185e037d9b..ddb26728bf3 100644
--- a/wear/src/main/res/layout/fragment_wizard_result.xml
+++ b/wear/src/main/res/layout/fragment_wizard_result.xml
@@ -118,6 +118,16 @@
android:textStyle="bold"
android:textColor="#B0BEC5" />
+
+
diff --git a/wear/src/main/res/values-cs-rCZ/strings.xml b/wear/src/main/res/values-cs-rCZ/strings.xml
index c880ad70ff2..6ca4f4b5e74 100644
--- a/wear/src/main/res/values-cs-rCZ/strings.xml
+++ b/wear/src/main/res/values-cs-rCZ/strings.xml
@@ -243,6 +243,7 @@
GL (DC: %1$s)15min trendIOB
+ Nové IOB: %1$sUCOB (%1$.1f g)Sacharidy (%1$d g)Mezisoučet
diff --git a/wear/src/main/res/values-es-rES/strings.xml b/wear/src/main/res/values-es-rES/strings.xml
index af0664014cc..79b5c800b87 100644
--- a/wear/src/main/res/values-es-rES/strings.xml
+++ b/wear/src/main/res/values-es-rES/strings.xml
@@ -243,6 +243,7 @@
BG (TT: %1$s)Tend. 15 minIOB
+ Nuevo IOB: %1$s UCOB (%1$.1f g)Carbs (%1$d g)Subtotal
diff --git a/wear/src/main/res/values-it-rIT/strings.xml b/wear/src/main/res/values-it-rIT/strings.xml
index 3ee1588478d..faf05ed0ad0 100644
--- a/wear/src/main/res/values-it-rIT/strings.xml
+++ b/wear/src/main/res/values-it-rIT/strings.xml
@@ -243,6 +243,7 @@
BG (TT: %1$s)Trend di 15minIOB
+ Nuovo IOB: %1$s UCOB (%1$.1f g)Carboidrati (%1$d g)Subtotale
diff --git a/wear/src/main/res/values-nb-rNO/strings.xml b/wear/src/main/res/values-nb-rNO/strings.xml
index 9636c927ec1..288e4436064 100644
--- a/wear/src/main/res/values-nb-rNO/strings.xml
+++ b/wear/src/main/res/values-nb-rNO/strings.xml
@@ -243,6 +243,7 @@
BS (Midl. mål: %1$s)15\' trendIOB
+ Ny IOB: %1$s ECOB (%1$.1f g)Karbo (%1$d g)Delsum
diff --git a/wear/src/main/res/values-nl-rNL/strings.xml b/wear/src/main/res/values-nl-rNL/strings.xml
index 75842a66381..a86804719b6 100644
--- a/wear/src/main/res/values-nl-rNL/strings.xml
+++ b/wear/src/main/res/values-nl-rNL/strings.xml
@@ -90,6 +90,7 @@
StandaardMenuXL
+ Duur\n[minuten]Tijdelijk streefdoel aangevraagdQuickWizard aangevraagdGebruiker actie aangevraagd
@@ -99,15 +100,24 @@
Vullen aangevraagdKoolhydraten aangevraagdProfiel wisselen aangevraagd
+ Streefdoel\n[%s]
+ Laag\n[%s]
+ Hoog\n[%s]Koolhydraten
+ Koolhydraten [g]eCarbs
+ Percentage\n[%]
+ Start\n[minuten]Duur [h]
+ Duur\n[uren]Insuline
+ Insuline [E]Voorinstelling 1Voorinstelling 2Voorinstelling 3Vrije hoeveelheidBEVESTIGEN
+ Tijdsverschuiving\n[uren]Bolus voortgangdruk om te annulerenBOLUS ANNULEREN
@@ -146,10 +156,14 @@
Externe weergaven opnemen in sjabloonExterne data wijzigen in watchfaceToon seconden
+ Jouw stijlgeen stijlminimale stijlvormstijlvolledige stijl
+ Jouw kleur
+ Jouw kleurverzadiging
+ Jouw kleurentransparantieAAPS Bolus VoortgangAAPS Bolus Voortgang StilBolus voortgang en annuleer
@@ -204,14 +218,22 @@
Volledige statusVolledige status (omgedraaid)Bloed glucose
+ Bloed glucose Ex1
+ Bloed glucose Ex2BR, CoB & IoB
+ BR, CoB & IoB Ext1
+ BR, CoB & IoB Ext2BR & IOB
+ Basaal snelheidCoB & IoBCoB icoonGedetailleerde CoBIoB icoonGedetailleerde IoBUploader/Telefoon Batterij
+ Loop status
+ AAPS(Loop status)
+ Loop status aangevraagdTotale insulineBerekening%1$d gr koolhydraten
@@ -221,6 +243,7 @@
BG (TT: %1$s)15min trendIOB
+ Nieuwe IOB: %1$s ECOB (%1$.1f g)Koolhydraten (%1$d g)Subtotaal
@@ -230,4 +253,35 @@
Corr. %1$d%%Klik om rekendetails uit te vouwenVerzonden
+ Tegel instellingen
+ Status kon niet geladen worden
+ %1$d min (%2$s)
+ %1$d min
+ %1$.2f E/uur (%2$d%%)
+ %1$d min resterend
+ Tijdelijk basaal blijft actief
+ Instellen tijdelijk basaal
+ %1$.2f E
+ N.v.t.
+ Gesloten loop
+ Open loop
+ Gestopt voor lage glucose
+ Loop gedeactiveerd
+ Loop onderbroken
+ Pomp ontkoppeld
+ Superbolus
+ Onbekend
+ Loop resultaat
+ Laatste uitvoering & toepassen
+ Laatst uitgevoerd
+ Laatst toegepast
+ SMB
+ Dosis
+ Tijdsduur
+ OpenAPS reden
+ Streefdoelen
+ Tijdelijk streefdoel
+ Interval
+ Streefwaarde
+ Loop status
diff --git a/wear/src/main/res/values-pl-rPL/strings.xml b/wear/src/main/res/values-pl-rPL/strings.xml
index 9ec70815353..a7102dd1505 100644
--- a/wear/src/main/res/values-pl-rPL/strings.xml
+++ b/wear/src/main/res/values-pl-rPL/strings.xml
@@ -90,6 +90,7 @@
DomyślnieMenuXL
+ Czas trwania\n[minuty]Żądany cel tymczasowySzybki kreatorWymagane działanie użytkownika
@@ -99,15 +100,24 @@
WypełnijŻądane węglowodanyProśba o zmianę profilu
+ Cel\n[%s]
+ Niski\n[%s]
+ Wysoki\n[%s]Węglowodany
+ Węgle [g]eCarbs
+ Procent\n[%]
+ Start\n[minuty]Czas trwania [h]
+ Czas trwania\n[godziny]Insulina
+ Insulina [U]Ustawienie 1Ustawienie 2Ustawienie 3Podana wartośćPOTWIERDŹ
+ Przes. Czasu\n[godziny]Postęp bolusanaciśnij aby anulowaćANULUJ BOLUS
@@ -146,10 +156,14 @@
Uwzględnij zewnętrzne widoki w szabloniePrzełącz dane zewnętrzne na tarczyPokaż sekundy
+ Twój stylbrak styluminimalistycznykształtnypełny
+ Twój kolor
+ Twoje nasycenie koloru
+ Twoja przezroczystość koloruPostęp bolusa AAPSPostęp bolusa AAPS (Cichszy)Informacja o postępie w podawaniu / anulowaniu bolusa
@@ -204,12 +218,69 @@
Pełny statusPełny status (odwrócony)Glikemia
+ Glikemia Ext1
+ Glikemia Ext2Baza, CoB & IoB
+ Baza, CoB & IoB Ext1
+ Baza, CoB & IoB Ext2BR & IoB
+ Dawka bazowaCoB & IoBIkona CoBSzczegółowe CoBIkona IoBSzczegółowa IoBBateria uploadera/telefonu
+ Status pętli
+ AAPS(stan pętli)
+ Zapytano o stan pętli
+ Insulina całkowita
+ Obliczenie
+ %1$d g węgli
+ IC: %1$s | ISF: %2$s
+ Przesuń w lewo, aby potwierdzić
+ BG
+ BG (TT: %1$s)
+ 15\' trend
+ IOB
+ COB (%1$.1f g)
+ Węgle (%1$d g)
+ Suma częściowa
+ Razem
+ %1$s U
+ U
+ Kor. %1$d%%
+ Kliknij, aby rozwinąć szczegóły obliczeń
+ Wysłano
+ Ustawienia kafelka
+ Nie udało się odświeżyć statusu
+ %1$d min (%2$s)
+ %1$d min
+ %1$.2f U/h (%2$d%%)
+ pozostało %1$d min
+ Baza tymczasowa jest kontynuowana
+ Ustawianie zwykłej bazy
+ %1$.2f U
+ BRAK
+ Zamknięta pętla
+ Otwarta pętla
+ Zawieszenie przy niskiej glikemii
+ Pętla wyłączona
+ Pętla wstrzymana
+ Pompa odłączona
+ Superbolus
+ Nieznany
+ Wynik pętli
+ Ostatni przebieg & działanie
+ Ostatni przebieg
+ Ostatnie działanie
+ SMB
+ Dawka
+ Czas trwania
+ Powód OpenAPS
+ Cele
+ Cel tymczasowy
+ Zakres
+ Cel
+ Status pętli
diff --git a/wear/src/main/res/values-ru-rRU/strings.xml b/wear/src/main/res/values-ru-rRU/strings.xml
index 8d7f7cb703f..64452d9d985 100644
--- a/wear/src/main/res/values-ru-rRU/strings.xml
+++ b/wear/src/main/res/values-ru-rRU/strings.xml
@@ -156,10 +156,14 @@
Включить внешние представления в шаблонВключить внешние данные на циферблатеПоказывать секунды
+ Ваш стильбез стиляминималистскийстиль формыполный стиль
+ Ваш цвет
+ Ваша цветовая насыщенность
+ Ваша непрозрачность цветаВводится болюсБеззвучный ввод болюсаВвод и отмена болюса
@@ -230,4 +234,54 @@
Состояние циклаAAPS(состояние цикла)Запрошено состояние цикла
+ Суммарное количество инсулина
+ Расчет
+ %1$d г углеводов
+ IC: %1$s | ISF: %2$s
+ Смахните влево для подтверждения
+ ГК
+ ГК (ВЦ: %1$s)
+ тренд 15\'
+ IOB акт инс
+ Новый активный инсулин IOB %1$s ед
+ акт угл COB (%1$.1f g)
+ Углеводы (%1$d g)
+ Подытог
+ Итого
+ %1$s ед
+ ед
+ Корр. %1$d%%
+ Нажмите, чтобы показать детали вычисления
+ Отправлено
+ Настройки плиток
+ Не удалось загрузить статус
+ %1$d мин (%2$s)
+ %1$d мин
+ %1$.2f ед/ч (%2$d%%)
+ %1$d мин осталось
+ Временный базал продолжается
+ Установка обычного базала
+ %1$.2f ед
+ Н/Д
+ Замкнутый цикл
+ Открытый цикл
+ Приостановка помпы на низкой ГК
+ Цикличность неактивирована
+ ЗЦикл остановлен
+ Связь с помпой отключена
+ Суперболюс
+ Неизвестно
+ Результат цикла
+ Последний запуск & Вкл
+ Последний запуск
+ Последнее включение
+ SMB / СМБ
+ Скорость
+ Продолжительность
+ OpenAPS Причина
+ Цели
+ Врем. цель
+ Диапазон
+ Целевое значение ГК:
+ Статус цикла
diff --git a/wear/src/main/res/values-sk-rSK/strings.xml b/wear/src/main/res/values-sk-rSK/strings.xml
index 7580add1b32..294948c4409 100644
--- a/wear/src/main/res/values-sk-rSK/strings.xml
+++ b/wear/src/main/res/values-sk-rSK/strings.xml
@@ -16,7 +16,7 @@
Žiadne dáta od %1$s! Skontroluj, či AAPS na telefóne posiela dáta na hodinkyAAPS dáta sú %1$s staré! Skontroluj tvoj senzor, xDrip+, NS, AAPS nastavenia atď.!Zavibrovať pri boluse
- J
+ UDisplejGrafRozhranie
@@ -111,7 +111,7 @@
Trvanie [h]Trvanie\n[hodiny]Inzulín
- Inzulín [J]
+ Inzulín [U]Predvoľba 1Predvoľba 2Predvoľba 3
@@ -184,12 +184,12 @@
prírastokzníženiepriemer
- --JI
+ --U--g
- -.--JI/h
+ -.--U/h000g00,0
- 0,00JI
+ 0,00UAAPS Potvrdenie výstrahyOdosielanie potvrdení do AAPSt
@@ -243,13 +243,45 @@
GL (DC: %1$s)15min trendIOB
+ Nové IOB: %1$sUCOB (%1$.1f g)Sacharidy (%1$d g)MedzisúčetSpolu
- %1$s JI
- JI
+ %1$s U
+ UKorekcia %1$d%%Kliknutím rozbalíte podrobnosti výpočtuOdoslané
+ Nastavenie dlaždice
+ Nepodarilo sa načítať stav
+ %1$d min (%2$s)
+ %1$d min
+ %1$.2f U/h (%2$d%%)
+ Zostáva %1$d min
+ Dočasný bazál pokračuje
+ Nastavujem normálny bazál
+ %1$.2f U
+ Nie je k dispozícii
+ Uzavretý okruh
+ Otvorený okruh
+ Ochrana pred nízkou glykémiou
+ Uzavretý okruh je deaktivovaný
+ Uzavretý okruh je pozastavený
+ Pumpa je odpojená
+ Superbolus
+ Neznámy
+ Výsledok uzavretého okruhu
+ Posledné spustenie & vykonanie
+ Posledné spustenie
+ Naposledy vykonané
+ SMB
+ Bazál
+ Trvanie
+ OpenAPS dôvod
+ Ciele
+ Dočasný cieľ
+ Rozsah
+ Cieľ
+ Stav okruhu
diff --git a/wear/src/main/res/values-vi-rVN/strings.xml b/wear/src/main/res/values-vi-rVN/strings.xml
index 4e5ad2cab24..039c7f96ea2 100644
--- a/wear/src/main/res/values-vi-rVN/strings.xml
+++ b/wear/src/main/res/values-vi-rVN/strings.xml
@@ -31,7 +31,7 @@
Hiển thị AvgDeltaHiển thị pin điện thoạiHiển thị mức pin Rig
- Hiển thị liều basal
+ Hiển thị tỷ lệ liều nềnHiển thị mục tiêu tạm thờiHiển thị mức insulinHiển thị trạng thái vòng lặp
@@ -99,7 +99,7 @@
Yêu cầu tính toánYêu cầu nạp insulinLượng carb cần nạp
- Yêu cầu chuyển đổi cấu hình
+ Yêu cầu chuyển đổi Hồ sơMục tiêu\n [%s]Thấp\n[%s]Cao\n[%s]
@@ -122,8 +122,8 @@
nhấn để hủyHỦY LIỀU BOLUSPump
- Loop
- Chuyển cấu hình
+ Vòng lặp
+ Chuyển Hồ sơTDDCarbIOB
@@ -224,7 +224,7 @@
BR, CoB & IoB Ext1BR, CoB & IoB Ext2BR & IoB
- Tỷ lệ liều Basal
+ Tỷ lệ liều nềnCoB & IoBBiểu tượng CoBChi tiết CoB
@@ -234,7 +234,7 @@
Trạng thái vòng lặpAAPS(Trạng thái vòng lặp)Đã yêu cầu trạng thái vòng lặp
- Tổng insulin
+ Tổng InsulinTính toán%1$d g carbsIC: %1$s | ISF: %2$s
@@ -243,13 +243,14 @@
BG (TT: %1$s)Xu hướng 15 phútIOB
+ IOB mới: %1$s UCOB (%1$.1f g)Carbs (%1$d g)Tổng phụTổng%1$s UU
- Corr. %1$d%%
+ Hiệu chỉnh. %1$d%%Nhấn để mở rộng chi tiết tính toánGửiCài đặt Tile
@@ -258,8 +259,8 @@
%1$d phút%1$.2f U/h (%2$d%%)Còn %1$d phút
- Tiếp tục liều Basal tạm thời
- Đang thiết lập basal thường
+ Tiếp tục liều nền tạm thời
+ Đang thiết lập liều nền thường%1$.2f UN/AVòng lặp kín
@@ -267,7 +268,7 @@
Tạm ngừng khi đường huyết thấpĐã tắt vòng lặpĐã tạm dừng vòng lặp
- Pump đã ngắt kết nối
+ Bơm đã ngắt kết nốiSuperbolusKhông xác địnhKết quả vòng lặp
diff --git a/wear/src/main/res/values-zh-rTW/strings.xml b/wear/src/main/res/values-zh-rTW/strings.xml
index e04a859311e..81cdabbc258 100644
--- a/wear/src/main/res/values-zh-rTW/strings.xml
+++ b/wear/src/main/res/values-zh-rTW/strings.xml
@@ -243,6 +243,7 @@
血糖(目標時間:%1$s)15 分鐘趨勢IOB
+ 新的 IOB:%1$s UCOB(%1$.1f g)碳水(%1$d g)小計
diff --git a/wear/src/main/res/values/strings.xml b/wear/src/main/res/values/strings.xml
index bf451a66254..3a9a4ca39bf 100644
--- a/wear/src/main/res/values/strings.xml
+++ b/wear/src/main/res/values/strings.xml
@@ -301,6 +301,7 @@
BG (TT: %1$s)15\' trendIOB
+ New IOB: %1$s UCOB (%1$.1f g)Carbs (%1$d g)Subtotal