diff --git a/app/libs/eopatch_core.aar b/app/libs/eopatch_core.aar index 837d402724..938f227251 100644 Binary files a/app/libs/eopatch_core.aar and b/app/libs/eopatch_core.aar differ diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt index 18c902f6a4..adce68295e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatusLightHandler.kt @@ -47,6 +47,8 @@ class StatusLightHandler @Inject constructor( val insulinUnit = rh.gs(R.string.insulin_unit_shortname) if (pump.model() == PumpType.OMNIPOD_EROS || pump.model() == PumpType.OMNIPOD_DASH) { handleOmnipodReservoirLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, insulinUnit) + } else if (pump.model() == PumpType.EOFLOW_EOPATCH2) { + handleEopatchReservoirLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, insulinUnit) } else { handleLevel(careportal_reservoir_level, R.string.key_statuslights_res_critical, 10.0, R.string.key_statuslights_res_warning, 80.0, pump.reservoirLevel, insulinUnit) } @@ -103,4 +105,14 @@ class StatusLightHandler @Inject constructor( } } + @Suppress("SameParameterValue") + private fun handleEopatchReservoirLevel(view: TextView?, criticalSetting: Int, criticalDefaultValue: Double, warnSetting: Int, warnDefaultValue: Double, level: Double, units: String) { + if (level > 50.0) { + @Suppress("SetTextI18n") + view?.text = " 50+$units" + view?.setTextColor(rh.gac(view.context, R.attr.defaultTextColor)) + } else { + handleLevel(view, criticalSetting, criticalDefaultValue, warnSetting, warnDefaultValue, level, units) + } + } } diff --git a/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt b/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt index 6c3e5b29db..3f61fff560 100644 --- a/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt +++ b/core/src/main/java/info/nightscout/androidaps/data/ProfileSealed.kt @@ -22,6 +22,7 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.interfaces.ResourceHelper +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import org.json.JSONArray import org.json.JSONObject import java.text.DecimalFormat @@ -98,6 +99,8 @@ sealed class ProfileSealed( override fun isValid(from: String, pump: Pump, config: Config, rh: ResourceHelper, rxBus: RxBus, hardLimits: HardLimits, sendNotifications: Boolean): Profile.ValidityCheck { val validityCheck = Profile.ValidityCheck() val description = pump.pumpDescription + val notSupportedBasalRate = StringBuffer() + for (basal in basalBlocks) { val basalAmount = basal.amount * percentage / 100.0 if (!description.is30minBasalRatesCapable) { @@ -141,7 +144,22 @@ sealed class ProfileSealed( validityCheck.reasons.add(rh.gs(R.string.maximumbasalvaluereplaced, from)) break } + + if(pump.model() == PumpType.EOFLOW_EOPATCH2 && pct == 100){ + val mod = (basalAmount * 1000) % (PumpType.EOFLOW_EOPATCH2.baseBasalStep * 1000) + if(!mod.nearlyEqual(0.0, 0.00000001)){ + notSupportedBasalRate.append( + if(notSupportedBasalRate.isEmpty()) String.format("%.2f", basalAmount) else String.format(", %.2f", basalAmount) + ) + } + } } + + if(notSupportedBasalRate.isNotEmpty()){ + validityCheck.isValid = false + validityCheck.reasons.add(rh.gs(R.string.unsupportedBasalRate, "$notSupportedBasalRate U/h")) + } + if (!hardLimits.isInRange(dia, hardLimits.minDia(), hardLimits.maxDia())) { validityCheck.isValid = false validityCheck.reasons.add(rh.gs(R.string.value_out_of_hard_limits, rh.gs(R.string.profile_dia), dia)) diff --git a/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt index d77090bc2d..4bf0626089 100644 --- a/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/ProfileSwitchExtension.kt @@ -14,6 +14,7 @@ import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.T import org.json.JSONObject import java.util.* +import kotlin.math.abs fun List.isPSEvent5minBack(time: Long): Boolean { for (event in this) { @@ -158,3 +159,16 @@ fun ProfileSwitch.getCustomizedName(): String { fun ProfileSwitch.GlucoseUnit.Companion.fromConstant(units: GlucoseUnit): ProfileSwitch.GlucoseUnit = if (units == GlucoseUnit.MGDL) ProfileSwitch.GlucoseUnit.MGDL else ProfileSwitch.GlucoseUnit.MMOL + +fun Double.nearlyEqual(b: Double, epsilon: Double): Boolean { + val absA = abs(this) + val absB = abs(b) + val diff = abs(this - b) + return if (this == b) { + true + } else if (this == 0.0 || b == 0.0 || absA + absB < java.lang.Float.MIN_NORMAL) { + diff < epsilon * java.lang.Double.MIN_NORMAL + } else { + diff / (absA + absB).coerceAtMost(Double.MAX_VALUE) < epsilon + } +} diff --git a/core/src/main/res/values-ko-rKR/strings.xml b/core/src/main/res/values-ko-rKR/strings.xml index f75531ba68..7190f2668f 100644 --- a/core/src/main/res/values-ko-rKR/strings.xml +++ b/core/src/main/res/values-ko-rKR/strings.xml @@ -146,6 +146,8 @@ 변경사항 없음 유효하지 않은 프로파일: %1$s + 지원하지 않는 베이젤 속도: %1$s + %1$d 분 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 56ed54ace4..b27684d643 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -241,6 +241,7 @@ Invalid profile: %1$s + Unsupported basal rate: %1$s %1$d min diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/CommonUtils.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/CommonUtils.kt index 1ac00e6306..27c85df6fd 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/CommonUtils.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/CommonUtils.kt @@ -87,10 +87,6 @@ object CommonUtils { } } - fun nearlyNotEqual(a: Float, b: Float, epsilon: Float): Boolean { - return !nearlyEqual(a, b, epsilon) - } - fun clone(src: T): T { return GsonHelper.sharedGson().fromJson(GsonHelper.sharedGson().toJson(src), src.javaClass) } diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/EopatchPumpPlugin.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/EopatchPumpPlugin.kt index b919ff15bd..309d91881d 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/EopatchPumpPlugin.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/EopatchPumpPlugin.kt @@ -19,14 +19,15 @@ import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.eopatch.alarm.IAlarmManager import info.nightscout.androidaps.plugins.pump.eopatch.ble.IPatchManager import info.nightscout.androidaps.plugins.pump.eopatch.ble.IPreferenceManager import info.nightscout.androidaps.plugins.pump.eopatch.code.BolusExDuration import info.nightscout.androidaps.plugins.pump.eopatch.code.SettingKeys -import info.nightscout.androidaps.plugins.pump.eopatch.extension.takeOne import info.nightscout.androidaps.plugins.pump.eopatch.ui.EopatchOverviewFragment import info.nightscout.androidaps.plugins.pump.eopatch.vo.TempBasal import info.nightscout.androidaps.queue.commands.CustomCommand @@ -94,7 +95,6 @@ class EopatchPumpPlugin @Inject constructor( .toObservable(EventAppInitialized::class.java) .observeOn(aapsSchedulers.io) .subscribe({ - aapsLogger.debug(LTag.PUMP,"EventAppInitialized") preferenceManager.init() patchManager.init() alarmManager.init() @@ -103,7 +103,7 @@ class EopatchPumpPlugin @Inject constructor( } override fun specialEnableCondition(): Boolean { - //BG -> FG 시 패치 활성화 재진행 및 미처리 알람 발생 + //BG -> FG, restart patch activation and trigger unhandled alarm if(preferenceManager.isInitDone()) { patchManager.checkActivationProcess() alarmManager.restartAll() @@ -129,7 +129,7 @@ class EopatchPumpPlugin @Inject constructor( } override fun isConnected(): Boolean { - return patchManager.patchConnectionState.isConnected + return if(patchManager.isDeactivated) true else patchManager.patchConnectionState.isConnected } override fun isConnecting(): Boolean { @@ -199,19 +199,25 @@ class EopatchPumpPlugin @Inject constructor( disposable.dispose() aapsLogger.info(LTag.PUMP, "Basal Profile was set: ${isSuccess?:false}") - return PumpEnactResult(injector).apply{ success = isSuccess?:false } + if(isSuccess?:false) { + rxBus.send(EventNewNotification(Notification(Notification.PROFILE_SET_OK, rh.gs(R.string.profile_set_ok), Notification.INFO, 60))) + return PumpEnactResult(injector).success(true).enacted(true) + }else{ + return PumpEnactResult(injector) + } } }else{ preferenceManager.getNormalBasalManager().setNormalBasal(profile) preferenceManager.flushNormalBasalManager() - return PumpEnactResult(injector) + rxBus.send(EventNewNotification(Notification(Notification.PROFILE_SET_OK, rh.gs(R.string.profile_set_ok), Notification.INFO, 60))) + return PumpEnactResult(injector).success(true).enacted(true) } } override fun isThisProfileSet(profile: Profile): Boolean { - if (!patchManager.isActivated) { - return true - } + // if (!patchManager.isActivated) { + // return true + // } val ret = preferenceManager.getNormalBasalManager().isEqual(profile) aapsLogger.info(LTag.PUMP, "Is this profile set? $ret") @@ -236,9 +242,8 @@ class EopatchPumpPlugin @Inject constructor( if (!patchManager.isActivated) { return 0.0 } - val reservoirLevel = patchManager.patchState.remainedInsulin.toDouble() - return (reservoirLevel > 50.0).takeOne(50.0, reservoirLevel) + return patchManager.patchState.remainedInsulin.toDouble() } override val batteryLevel: Int @@ -275,6 +280,10 @@ class EopatchPumpPlugin @Inject constructor( }) ) + val tr = detailedBolusInfo.let { + EventOverviewBolusProgress.Treatment(it.insulin, it.carbs.toInt(), it.bolusType === DetailedBolusInfo.BolusType.SMB, it.id) + } + do{ SystemClock.sleep(100) if(patchManager.patchConnectionState.isConnected) { @@ -282,6 +291,7 @@ class EopatchPumpPlugin @Inject constructor( rxBus.send(EventOverviewBolusProgress.apply { status = rh.gs(R.string.bolusdelivering, delivering) percent = min((delivering / detailedBolusInfo.insulin * 100).toInt(), 100) + t = tr }) } }while(!patchManager.bolusCurrent.nowBolus.endTimeSynced && isSuccess) diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmCode.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmCode.kt index 1fc2754f06..ed47f06f2f 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmCode.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmCode.kt @@ -32,6 +32,7 @@ enum class AlarmCode(messageResId: Int) { A116(R.string.string_a116), //"Patch Error" A117(R.string.string_a117), //"Patch Error" A118(R.string.string_a118), //"Patch Error" + B000(R.string.string_b000), B001(R.string.string_b001), //"End of insulin suspend" B003(R.string.string_b003), //"Low reservoir" B005(R.string.string_b005), //"Patch operating life expired" diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmManager.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmManager.kt index 9d26583d75..0c88b0d6d0 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmManager.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmManager.kt @@ -27,6 +27,8 @@ import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable +import java.text.SimpleDateFormat +import java.util.Locale import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton @@ -138,7 +140,13 @@ class AlarmManager @Inject constructor() : IAlarmManager { } private fun showNotification(alarmCode: AlarmCode, timeOffset: Long = 0L){ - val notification = EONotification(Notification.EOELOW_PATCH_ALERTS + (alarmCode.aeCode + 10000), resourceHelper.gs(alarmCode.resId), Notification.URGENT) + var alarmMsg = resourceHelper.gs(alarmCode.resId) + if(alarmCode == B000){ + val expireTimeValue = pm.getPatchWakeupTimestamp() + TimeUnit.HOURS.toMillis(84) + val expireTimeString = SimpleDateFormat(resourceHelper.gs(R.string.date_format_yyyy_m_d_e_a_hh_mm_comma), Locale.US).format(expireTimeValue) + alarmMsg = resourceHelper.gs(alarmCode.resId, expireTimeString) + } + val notification = EONotification(Notification.EOELOW_PATCH_ALERTS + (alarmCode.aeCode + 10000), alarmMsg, Notification.URGENT) notification.action(R.string.confirm) { compositeDisposable.add( diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmProcess.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmProcess.kt index 8ebfdfc998..95efd7050f 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmProcess.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmProcess.kt @@ -41,7 +41,7 @@ class AlarmProcess(val patchManager: IPatchManager, val rxBus: RxBus) : IAlarmPr A117, A118 -> patchDeactivationAction(context) A007 -> inappropriateTemperatureAction(context) A016 -> needleInsertionErrorAction(context) - B003, B018 -> Single.just(IAlarmProcess.ALARM_HANDLED) + B000, B003, B018 -> Single.just(IAlarmProcess.ALARM_HANDLED) B005, B006 -> Single.just(IAlarmProcess.ALARM_HANDLED) B012 -> Single.just(IAlarmProcess.ALARM_HANDLED) } diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/IPatchManager.java b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/IPatchManager.java index ed6f829238..1cd9b5eef2 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/IPatchManager.java +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/IPatchManager.java @@ -35,6 +35,8 @@ public interface IPatchManager { boolean isActivated(); + boolean isDeactivated(); + Single resumeBasal(); Observable observePatchLifeCycle(); diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/PatchManager.java b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/PatchManager.java index faa98c6412..5bef9e5a6d 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/PatchManager.java +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ble/PatchManager.java @@ -22,6 +22,7 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.plugins.pump.eopatch.R; import info.nightscout.androidaps.plugins.pump.eopatch.RxAction; import info.nightscout.androidaps.plugins.pump.eopatch.alarm.AlarmCode; +import info.nightscout.androidaps.plugins.pump.eopatch.alarm.IAlarmRegistry; import info.nightscout.androidaps.plugins.pump.eopatch.code.BolusExDuration; import info.nightscout.androidaps.plugins.pump.eopatch.code.DeactivationStatus; import info.nightscout.androidaps.plugins.pump.eopatch.code.PatchLifecycle; @@ -51,6 +52,7 @@ import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.rx.AapsSchedulers; import info.nightscout.shared.logging.AAPSLogger; import info.nightscout.shared.sharedPreferences.SP; +import io.reactivex.rxjava3.core.Maybe; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Single; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -73,6 +75,7 @@ public class PatchManager implements IPatchManager { @Inject DateUtil dateUtil; @Inject RxAction rxAction; @Inject AapsSchedulers aapsSchedulers; + @Inject IAlarmRegistry alarmRegistry; private IPatchScanner patchScanner; private final CompositeDisposable mCompositeDisposable = new CompositeDisposable(); @@ -222,6 +225,10 @@ public class PatchManager implements IPatchManager { return pm.getPatchConfig().isActivated(); } + public boolean isDeactivated() { + return pm.getPatchConfig().isDeactivated(); + } + public Single startBond(String mac) { return patchManager.startBond(mac); } @@ -249,24 +256,24 @@ public class PatchManager implements IPatchManager { public Single patchActivation(long timeout) { return patchManager.patchActivation(timeout) .doOnSuccess(success -> { - if (success) { - pumpSync.insertTherapyEventIfNewWithTimestamp( - getPatchConfig().getPatchWakeupTimestamp(), - DetailedBolusInfo.EventType.CANNULA_CHANGE, - null, - null, - PumpType.EOFLOW_EOPATCH2, - getPatchConfig().getPatchSerialNumber() - ); - pumpSync.insertTherapyEventIfNewWithTimestamp( - getPatchConfig().getPatchWakeupTimestamp(), - DetailedBolusInfo.EventType.INSULIN_CHANGE, - null, - null, - PumpType.EOFLOW_EOPATCH2, - getPatchConfig().getPatchSerialNumber() - ); - } +// if (success) { +// pumpSync.insertTherapyEventIfNewWithTimestamp( +// getPatchConfig().getPatchWakeupTimestamp(), +// DetailedBolusInfo.EventType.CANNULA_CHANGE, +// null, +// null, +// PumpType.EOFLOW_EOPATCH2, +// getPatchConfig().getPatchSerialNumber() +// ); +// pumpSync.insertTherapyEventIfNewWithTimestamp( +// getPatchConfig().getPatchWakeupTimestamp(), +// DetailedBolusInfo.EventType.INSULIN_CHANGE, +// null, +// null, +// PumpType.EOFLOW_EOPATCH2, +// getPatchConfig().getPatchSerialNumber() +// ); +// } }); } @@ -404,6 +411,14 @@ public class PatchManager implements IPatchManager { if (isActivated()) { mCompositeDisposable.add(setLowReservoir(doseUnit, hours) .observeOn(aapsSchedulers.getMain()) + .doOnSubscribe(disposable -> { + if(pc.getPatchExpireAlertTime() != hours){ + Maybe.just(AlarmCode.B000) + .flatMap(alarmCode -> alarmRegistry.remove(alarmCode)) + .flatMap(alarmCode -> alarmRegistry.add(alarmCode, (pc.getExpireTimestamp() - System.currentTimeMillis() - TimeUnit.HOURS.toMillis(hours)), false)) + .subscribe(); + } + }) .subscribe(patchBooleanResponse -> { pc.setLowReservoirAlertAmount(doseUnit); pc.setPatchExpireAlertTime(hours); diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/code/EventType.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/code/EventType.kt index efc8207243..fba95d8629 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/code/EventType.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/code/EventType.kt @@ -6,6 +6,7 @@ enum class EventType { SUSPEND_CLICKED, RESUME_CLICKED, INVALID_BASAL_RATE, + UNSUPPORTED_BASAL_RATE, PROFILE_NOT_SET, SHOW_PATCH_COMM_DIALOG, DISMISS_PATCH_COMM_DIALOG, diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/extension/FloatExtension.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/extension/FloatExtension.kt index 08692f540a..304ae4a849 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/extension/FloatExtension.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/extension/FloatExtension.kt @@ -2,19 +2,15 @@ package info.nightscout.androidaps.plugins.pump.eopatch.extension import kotlin.math.abs -fun Float.nearlyEqual(b: Float, epsilon: Float): Boolean { +fun Double.nearlyEqual(b: Double, epsilon: Double): Boolean { val absA = abs(this) val absB = abs(b) val diff = abs(this - b) return if (this == b) { true - } else if (this == 0f || b == 0f || absA + absB < java.lang.Float.MIN_NORMAL) { - diff < epsilon * java.lang.Float.MIN_NORMAL + } else if (this == 0.0 || b == 0.0 || absA + absB < java.lang.Float.MIN_NORMAL) { + diff < epsilon * java.lang.Double.MIN_NORMAL } else { - diff / (absA + absB).coerceAtMost(Float.MAX_VALUE) < epsilon + diff / (absA + absB).coerceAtMost(Double.MAX_VALUE) < epsilon } -} - -fun Float.nearlyNotEqual(b: Float, epsilon: Float): Boolean { - return !nearlyEqual(b, epsilon) -} +} \ No newline at end of file diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/EopatchOverviewFragment.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/EopatchOverviewFragment.kt index cc4a4f7017..ec3e90c4e9 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/EopatchOverviewFragment.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/EopatchOverviewFragment.kt @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.pump.eopatch.ui -import android.app.AlertDialog import android.content.Intent import android.os.Bundle import android.view.View @@ -18,6 +17,7 @@ import info.nightscout.androidaps.plugins.pump.eopatch.code.EventType import info.nightscout.androidaps.plugins.pump.eopatch.databinding.FragmentEopatchOverviewBinding import info.nightscout.androidaps.plugins.pump.eopatch.extension.takeOne import info.nightscout.androidaps.plugins.pump.eopatch.ui.viewmodel.EopatchOverviewViewModel +import info.nightscout.androidaps.utils.alertDialogs.AlertDialogHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.shared.logging.AAPSLogger import io.reactivex.rxjava3.disposables.CompositeDisposable @@ -52,8 +52,9 @@ class EopatchOverviewFragment: EoBaseFragment() EventType.DEACTIVATION_CLICKED -> requireContext().apply { startActivity(EopatchActivity.createIntentForChangePatch(this)) } EventType.SUSPEND_CLICKED -> suspend() EventType.RESUME_CLICKED -> resume() - EventType.INVALID_BASAL_RATE -> showToast(R.string.unsupported_basal_rate) - EventType.PROFILE_NOT_SET -> showToast(R.string.no_profile_selected) + EventType.INVALID_BASAL_RATE -> showToast(R.string.invalid_basal_rate) + EventType.UNSUPPORTED_BASAL_RATE -> showToast(R.string.unsupported_basal_rate, evt.value) + EventType.PROFILE_NOT_SET -> showToast(R.string.no_profile_selected) EventType.PAUSE_BASAL_FAILED -> showToast(R.string.string_pause_failed) EventType.RESUME_BASAL_FAILED -> showToast(R.string.string_resume_failed) else -> Unit @@ -90,14 +91,17 @@ class EopatchOverviewFragment: EoBaseFragment() binding.viewmodel?.startBasalRateUpdate() } - private fun showToast(@StringRes strId: Int){ - Toast.makeText(requireContext(), strId, Toast.LENGTH_SHORT).show() + private fun showToast(@StringRes strId: Int, value: Any? = null){ + if(value == null) + Toast.makeText(requireContext(), strId, Toast.LENGTH_SHORT).show() + else + Toast.makeText(requireContext(), getString(strId, value.toString()), Toast.LENGTH_SHORT).show() } private fun suspend() { binding.viewmodel?.apply { activity?.let { - val builder = AlertDialog.Builder(it) + val builder = AlertDialogHelper.Builder(it) val msg = getSuspendDialogText() val dialog = builder.setTitle(R.string.string_suspend) @@ -116,7 +120,7 @@ class EopatchOverviewFragment: EoBaseFragment() private fun resume() { binding.viewmodel?.apply { activity?.let { - val builder = AlertDialog.Builder(it) + val builder = AlertDialogHelper.Builder(it) val dialog = builder.setTitle(R.string.string_resume_insulin_delivery_title) .setMessage(R.string.string_resume_insulin_delivery_message) .setPositiveButton(R.string.confirm) { _, _ -> @@ -137,7 +141,7 @@ class EopatchOverviewFragment: EoBaseFragment() private fun openPauseTimePicker() { binding.viewmodel?.apply { activity?.let{ - val builder = AlertDialog.Builder(it) + val builder = AlertDialogHelper.Builder(it) val listArr = requireContext().resources.getStringArray(R.array.suspend_duration_array) var select = 0 val dialog = builder.setTitle(R.string.string_suspend_time_insulin_delivery_title) diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/dialogs/CommonDialog.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/dialogs/CommonDialog.kt index 5e0ab3d1d2..2c2775e556 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/dialogs/CommonDialog.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/dialogs/CommonDialog.kt @@ -1,12 +1,12 @@ package info.nightscout.androidaps.plugins.pump.eopatch.ui.dialogs -import android.app.AlertDialog import android.app.Dialog import android.content.DialogInterface import android.os.Bundle import dagger.android.support.DaggerDialogFragment import info.nightscout.shared.logging.AAPSLogger import info.nightscout.androidaps.plugins.pump.eopatch.R +import info.nightscout.androidaps.utils.alertDialogs.AlertDialogHelper import java.lang.IllegalStateException import javax.inject.Inject @@ -24,7 +24,7 @@ class CommonDialog : DaggerDialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return activity?.let{ - val builder = AlertDialog.Builder(it).apply { + val builder = AlertDialogHelper.Builder(it).apply { if(title != 0) setTitle(title) if(message != 0) setMessage(message) setPositiveButton(positiveBtn, diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchOverviewViewModel.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchOverviewViewModel.kt index 895f53e97a..05501cae12 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchOverviewViewModel.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchOverviewViewModel.kt @@ -16,6 +16,7 @@ import info.nightscout.androidaps.plugins.pump.eopatch.vo.Alarms import info.nightscout.androidaps.plugins.pump.eopatch.vo.PatchConfig import info.nightscout.androidaps.plugins.pump.eopatch.vo.PatchState import info.nightscout.androidaps.interfaces.ResourceHelper +import info.nightscout.androidaps.plugins.pump.eopatch.extension.nearlyEqual import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.Disposable @@ -168,16 +169,31 @@ class EopatchOverviewViewModel @Inject constructor( fun onClickActivation(){ val profile = profileFunction.getProfile() - - if(profile != null && profile.getBasal() >= 0.05) { - patchManager.preferenceManager.getNormalBasalManager().setNormalBasal(profile) - patchManager.preferenceManager.flushNormalBasalManager() - - _eventHandler.postValue(UIEvent(EventType.ACTIVATION_CLICKED)) - }else if(profile != null && profile.getBasal() < 0.05){ - _eventHandler.postValue(UIEvent(EventType.INVALID_BASAL_RATE)) - }else{ + if(profile == null){ _eventHandler.postValue(UIEvent(EventType.PROFILE_NOT_SET)) + }else{ + val basalValues = profile.getBasalValues() + var isValid = true + for(basalRate in basalValues){ + if(basalRate.value < 0.049999){ + _eventHandler.postValue(UIEvent(EventType.INVALID_BASAL_RATE)) + isValid = false + break + } + val mod = (basalRate.value * 1000) % (0.05 * 1000) + if(!mod.nearlyEqual(0.0, 0.00000001)){ + _eventHandler.postValue(UIEvent(EventType.UNSUPPORTED_BASAL_RATE).apply { value = basalRate.value }) + isValid = false + break + } + } + + if(isValid) { + patchManager.preferenceManager.getNormalBasalManager().setNormalBasal(profile) + patchManager.preferenceManager.flushNormalBasalManager() + + _eventHandler.postValue(UIEvent(EventType.ACTIVATION_CLICKED)) + } } } diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchViewModel.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchViewModel.kt index 08e1e7edf6..374aead3c5 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchViewModel.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/ui/viewmodel/EopatchViewModel.kt @@ -5,6 +5,7 @@ import androidx.annotation.StringRes import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Transformations +import info.nightscout.androidaps.interfaces.ResourceHelper import info.nightscout.androidaps.plugins.pump.eopatch.CommonUtils import info.nightscout.androidaps.plugins.pump.eopatch.R import info.nightscout.androidaps.plugins.pump.eopatch.RxAction @@ -14,6 +15,7 @@ import info.nightscout.androidaps.plugins.pump.eopatch.ble.IPatchManager import info.nightscout.androidaps.plugins.pump.eopatch.code.EventType import info.nightscout.androidaps.plugins.pump.eopatch.code.PatchLifecycle import info.nightscout.androidaps.plugins.pump.eopatch.code.PatchStep +import info.nightscout.androidaps.plugins.pump.eopatch.code.SettingKeys.Companion.EXPIRATION_REMINDERS import info.nightscout.androidaps.plugins.pump.eopatch.core.define.IPatchConstant import info.nightscout.androidaps.plugins.pump.eopatch.core.scan.BleConnectionState import info.nightscout.androidaps.plugins.pump.eopatch.core.scan.PatchSelfTestResult.TEST_SUCCESS @@ -28,10 +30,10 @@ import info.nightscout.androidaps.plugins.pump.eopatch.ui.viewmodel.EopatchViewM import info.nightscout.androidaps.plugins.pump.eopatch.vo.PatchConfig import info.nightscout.androidaps.plugins.pump.eopatch.vo.PatchLifecycleEvent import info.nightscout.androidaps.plugins.pump.eopatch.vo.PatchState -import info.nightscout.androidaps.interfaces.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.LTag +import info.nightscout.shared.sharedPreferences.SP import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.Single @@ -49,7 +51,8 @@ class EopatchViewModel @Inject constructor( private val alarmRegistry: IAlarmRegistry, private val aapsLogger: AAPSLogger, private val aapsSchedulers: AapsSchedulers, - private val rxAction: RxAction + private val rxAction: RxAction, + private val sp: SP ) : EoBaseViewModel() { companion object { private const val MAX_ELAPSED_MILLIS_AFTER_EXPIRATION = -12L * 60 * 60 * 1000 @@ -491,9 +494,12 @@ class EopatchViewModel @Inject constructor( PatchStep.COMPLETE, PatchStep.BASAL_SCHEDULE -> { val now = System.currentTimeMillis() val expireTimeStamp = patchConfig.expireTimestamp + val milllisBeforeExpiration = TimeUnit.HOURS.toMillis(sp.getInt(EXPIRATION_REMINDERS, 0).toLong()) + Maybe.just(AlarmCode.B012) .flatMap { alarmRegistry.remove(it) } .flatMap { alarmRegistry.remove(AlarmCode.A020) } + .flatMap { alarmRegistry.add(AlarmCode.B000, expireTimeStamp - now - milllisBeforeExpiration) } .flatMap { alarmRegistry.add(AlarmCode.B005, expireTimeStamp - now) } .flatMap { alarmRegistry.add(AlarmCode.B006, expireTimeStamp - now + IPatchConstant.SERVICE_TIME_MILLI - TimeUnit.HOURS.toMillis(1)) } .flatMap { alarmRegistry.add(AlarmCode.A003, expireTimeStamp - now + IPatchConstant.SERVICE_TIME_MILLI) } diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/NormalBasalManager.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/NormalBasalManager.kt index dbd198cf4d..fe85271de9 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/NormalBasalManager.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/NormalBasalManager.kt @@ -37,7 +37,8 @@ class NormalBasalManager : IPreference { if(TimeUnit.SECONDS.toMinutes(it.getBasalValues()[i].timeAsSeconds.toLong()) != normalBasal.list.get(i).start){ return false } - if(CommonUtils.nearlyNotEqual(it.getBasalValues()[i].value.toFloat(), normalBasal.list.get(i).doseUnitPerHour, 0.0000001f)){ + if(!CommonUtils.nearlyEqual(it.getBasalValues()[i].value.toFloat(), normalBasal + .list.get(i).doseUnitPerHour, 0.0000001f)){ return false } } diff --git a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/PatchState.kt b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/PatchState.kt index 7986eabe35..f40e3c732d 100644 --- a/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/PatchState.kt +++ b/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/vo/PatchState.kt @@ -14,7 +14,6 @@ import java.util.* import java.util.concurrent.TimeUnit import java.util.function.Consumer import java.util.stream.IntStream -import kotlin.math.roundToInt class PatchState: IPreference { @Transient @@ -129,9 +128,23 @@ class PatchState: IPreference { } fun batteryLevel(): Int { - if((get(D7) + 145) > 300) return 100 + val volt = (get(D7) + 145) * 10 + val batteryLevel: Int + if (volt >= 3000) { + batteryLevel = 100 + } else if (volt > 2900) { + batteryLevel = 100 - ((3000 - volt) * 10) / 100 + } else if (volt > 2740) { + batteryLevel = 90 - ((2900 - volt) * 20) / 160 + } else if (volt > 2440) { + batteryLevel = 70 - ((2740 - volt) * 50) / 300 + } else if (volt > 2100) { + batteryLevel = 20 - ((2440 - volt) * 20) / 340 + } else { + batteryLevel = 0 + } - return ((get(D7) + 145 - 210) * 100.0 / 90).roundToInt() + return batteryLevel } //============================================================================================== diff --git a/eopatch/src/main/res/values-ko/strings.xml b/eopatch/src/main/res/values-ko/strings.xml index ad5cd875d0..c6bf5de970 100644 --- a/eopatch/src/main/res/values-ko/strings.xml +++ b/eopatch/src/main/res/values-ko/strings.xml @@ -21,8 +21,9 @@ 일시기초주입 속도 총 주입량 - 프로파일에 설정된 베이젤 속도가 0.05 U/hr 보다 작습니다. 이오패치는 최소 주입 단위가 0.05U 입니다. 최소 주입 단위 이상으로 프로파일 설정 후 다시 시도해 주세요. + 프로파일에 설정된 베이젤 속도가 0.05 U/hr 보다 작습니다. 이오패치는 최소 주입 단위가 0.05U 입니다. 최소 주입 단위 이상으로 프로파일 설정 후 다시 시도해 주세요. 프로파일이 선택되지 않았습니다. 프로파일 선택 후 다시 시도해 주세요. + 베이젤 속도 %1$s U/hr는 이오패치에서 지원되지 않습니다. day + @@ -136,4 +137,5 @@ 패치 통신 점검 후 다시 시도하세요. 주입 정지가 실패하였습니다. 주입 재개가 실패하였습니다. + yyyy. M. d (E) a hh:mm diff --git a/eopatch/src/main/res/values-ko/strings_alarm.xml b/eopatch/src/main/res/values-ko/strings_alarm.xml index 80b50896e6..4a1aa9c1f0 100644 --- a/eopatch/src/main/res/values-ko/strings_alarm.xml +++ b/eopatch/src/main/res/values-ko/strings_alarm.xml @@ -22,6 +22,7 @@ 패치 오류\n패치 사용 및 인슐린 주입이 중단되었습니다. 즉시 패치를 교체하세요. 패치 오류\n패치 사용 및 인슐린 주입이 중단되었습니다. 즉시 패치를 교체하세요. 패치 오류\n패치 사용 및 인슐린 주입이 중단되었습니다. 즉시 패치를 교체하세요. + 패치 사용기간이 %s 에 만료됩니다. 패치 교체를 준비하세요. 인슐린 주입정지 종료\n\'주입재개\'를 눌러 기초 주입을 다시 시작하세요. 인슐린 부족\n곧 패치를 교체하세요. 패치 사용기간 만료\n즉시 패치를 교체하세요. diff --git a/eopatch/src/main/res/values/strings.xml b/eopatch/src/main/res/values/strings.xml index cb5a4f1b01..2ed40e4bfb 100644 --- a/eopatch/src/main/res/values/strings.xml +++ b/eopatch/src/main/res/values/strings.xml @@ -32,8 +32,9 @@ Temp Basal Rate Total Delivered - The basal of the profile is less than 0.05 U/hr. EOPatch has a minimum injection unit of 0.05U. Please try again after setting the profile to more than the minimum injection unit. + The basal of the profile is less than 0.05 U/hr. EOPatch has a minimum injection unit of 0.05U. Please try again after setting the profile to more than the minimum injection unit. No profile selected. Please select a profile and try again. + Basal rate %1$s U/hr is not supported by EOPatch. day + @@ -110,9 +111,9 @@ Cancel pairing days  U - Upon the suspend, the currently deliverying Bolus & Temp basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s\n& Insulin to go : %3$.2f U - Upon the suspend, the currently deliverying Bolus will be canceled. \n\nInsulin to go : %1$.2f U - Upon the suspend, the currently deliverying Temp Basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s + Upon the suspend, the currently delivering Bolus & Temp basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s\n& Insulin to go : %3$.2f U + Upon the suspend, the currently delivering Bolus will be canceled. \n\nInsulin to go : %1$.2f U + Upon the suspend, the currently delivering Temp Basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s Insulin delivery will be suspended. Discard/Change Patch Activate Patch @@ -131,7 +132,7 @@ Processing Retry [Caution] DO NOT remove the needle cap and the adhesive backing until further instruction. - Are you sure to deiscard the current Patch? + Are you sure to discard the current Patch? Due to an unconfirmed bolus information, Bolus calc cannot be used until %s.\n\nAre you sure to discard the current Patch? Needle insertion Error. Check the direction of the hole left after turning the lever is straight and then Tap \'Retry\'. @@ -147,4 +148,5 @@ Retry after Patch communication check. Suspension failed. Resume failed. + EEE, d MMM, yyyy hh:mm a \ No newline at end of file diff --git a/eopatch/src/main/res/values/strings_alarm.xml b/eopatch/src/main/res/values/strings_alarm.xml index 50dbd4bcaa..7ed5091eb2 100644 --- a/eopatch/src/main/res/values/strings_alarm.xml +++ b/eopatch/src/main/res/values/strings_alarm.xml @@ -22,6 +22,7 @@ Patch Error\nPatch has been deactivated and insulin delivery stopped. Change Patch now. Patch Error\nPatch has been deactivated and insulin delivery stopped. Change Patch now. Patch Error\nPatch has been deactivated and insulin delivery stopped. Change Patch now. + Patch operating life will expire %s. Be ready to change Patch. End of insulin suspend\nTap \'Resume\' to restart the insulin delivery. Low reservoir\nReplace Patch soon. Patch operating life expired\nChange Patch now.