[EOPatch]

1. Fix dialog box display error
2. Invalid basal rate check
3. Fix profile setting error when EOPatch is not connected
4. Insulin remaining over 50U is displayed as 50U+
5. Fixed bolus injection progress display error
6. typo correction
This commit is contained in:
jungsomyeong 2022-09-27 20:54:44 +09:00
parent 50c2a19743
commit 812906cba5
25 changed files with 197 additions and 75 deletions

Binary file not shown.

View file

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

View file

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

View file

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

View file

@ -146,6 +146,8 @@
<string name="nochangerequested">변경사항 없음</string>
<!-- ProfileSwitch-->
<string name="zerovalueinprofile">유효하지 않은 프로파일: %1$s</string>
<string name="unsupportedBasalRate">지원하지 않는 베이젤 속도: %1$s</string>
<!-- Temptarget-->
<string name="mins">%1$d 분</string>
<!-- Translator-->

View file

@ -241,6 +241,7 @@
<!-- ProfileSwitch-->
<string name="zerovalueinprofile">Invalid profile: %1$s</string>
<string name="unsupportedBasalRate">Unsupported basal rate: %1$s</string>
<!-- Temptarget-->
<string name="mins">%1$d min</string>

View file

@ -87,10 +87,6 @@ object CommonUtils {
}
}
fun nearlyNotEqual(a: Float, b: Float, epsilon: Float): Boolean {
return !nearlyEqual(a, b, epsilon)
}
fun <T : Any> clone(src: T): T {
return GsonHelper.sharedGson().fromJson(GsonHelper.sharedGson().toJson(src), src.javaClass)
}

View file

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

View file

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

View file

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

View file

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

View file

@ -35,6 +35,8 @@ public interface IPatchManager {
boolean isActivated();
boolean isDeactivated();
Single<? extends BaseResponse> resumeBasal();
Observable<PatchLifecycle> observePatchLifeCycle();

View file

@ -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<Boolean> startBond(String mac) {
return patchManager.startBond(mac);
}
@ -249,24 +256,24 @@ public class PatchManager implements IPatchManager {
public Single<Boolean> 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);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -37,7 +37,8 @@ class NormalBasalManager : IPreference<NormalBasalManager> {
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
}
}

View file

@ -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<PatchState> {
@Transient
@ -129,9 +128,23 @@ class PatchState: IPreference<PatchState> {
}
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
}
//==============================================================================================

View file

@ -21,8 +21,9 @@
<string name="eopatch_temp_basal_rate">일시기초주입 속도</string>
<string name="eopatch_total_delivered">총 주입량</string>
<string name="unsupported_basal_rate">프로파일에 설정된 베이젤 속도가 0.05 U/hr 보다 작습니다. 이오패치는 최소 주입 단위가 0.05U 입니다. 최소 주입 단위 이상으로 프로파일 설정 후 다시 시도해 주세요.</string>
<string name="invalid_basal_rate">프로파일에 설정된 베이젤 속도가 0.05 U/hr 보다 작습니다. 이오패치는 최소 주입 단위가 0.05U 입니다. 최소 주입 단위 이상으로 프로파일 설정 후 다시 시도해 주세요.</string>
<string name="no_profile_selected">프로파일이 선택되지 않았습니다. 프로파일 선택 후 다시 시도해 주세요.</string>
<string name="unsupported_basal_rate">베이젤 속도 %1$s U/hr는 이오패치에서 지원되지 않습니다.</string>
<string name="symbol_day">day</string>
<string name="symbol_plus">+</string>
@ -136,4 +137,5 @@
<string name="patch_connection_fail">패치 통신 점검 후 다시 시도하세요.</string>
<string name="string_pause_failed">주입 정지가 실패하였습니다.</string>
<string name="string_resume_failed">주입 재개가 실패하였습니다.</string>
<string name="date_format_yyyy_m_d_e_a_hh_mm_comma">yyyy. M. d (E) a hh:mm</string>
</resources>

View file

@ -22,6 +22,7 @@
<string name="string_a116">패치 오류\n패치 사용 및 인슐린 주입이 중단되었습니다. 즉시 패치를 교체하세요.</string>
<string name="string_a117">패치 오류\n패치 사용 및 인슐린 주입이 중단되었습니다. 즉시 패치를 교체하세요.</string>
<string name="string_a118">패치 오류\n패치 사용 및 인슐린 주입이 중단되었습니다. 즉시 패치를 교체하세요.</string>
<string name="string_b000">패치 사용기간이 %s 에 만료됩니다. 패치 교체를 준비하세요.</string>
<string name="string_b001">인슐린 주입정지 종료\n\'주입재개\'를 눌러 기초 주입을 다시 시작하세요.</string>
<string name="string_b003">인슐린 부족\n곧 패치를 교체하세요.</string>
<string name="string_b005">패치 사용기간 만료\n즉시 패치를 교체하세요.</string>

View file

@ -32,8 +32,9 @@
<string name="eopatch_temp_basal_rate">Temp Basal Rate</string>
<string name="eopatch_total_delivered">Total Delivered</string>
<string name="unsupported_basal_rate">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.</string>
<string name="invalid_basal_rate">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.</string>
<string name="no_profile_selected">No profile selected. Please select a profile and try again.</string>
<string name="unsupported_basal_rate">Basal rate %1$s U/hr is not supported by EOPatch.</string>
<string name="symbol_day">day</string>
<string name="symbol_plus">+</string>
@ -110,9 +111,9 @@
<string name="patch_cancel_pairing">Cancel pairing</string>
<string name="symbol_days">days</string>
<string name="all_dose_unit">&#160;U</string>
<string name="insulin_suspend_msg1">Upon the suspend, the currently deliverying Bolus &amp; Temp basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s\n&amp; Insulin to go : %3$.2f U</string>
<string name="insulin_suspend_msg2">Upon the suspend, the currently deliverying Bolus will be canceled. \n\nInsulin to go : %1$.2f U</string>
<string name="insulin_suspend_msg3">Upon the suspend, the currently deliverying Temp Basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s</string>
<string name="insulin_suspend_msg1">Upon the suspend, the currently delivering Bolus &amp; Temp basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s\n&amp; Insulin to go : %3$.2f U</string>
<string name="insulin_suspend_msg2">Upon the suspend, the currently delivering Bolus will be canceled. \n\nInsulin to go : %1$.2f U</string>
<string name="insulin_suspend_msg3">Upon the suspend, the currently delivering Temp Basal will be canceled. \n\nRate : %1$s U/hr\nRemaining time : %2$s</string>
<string name="insulin_suspend_msg4">Insulin delivery will be suspended.</string>
<string name="string_change_patch">Discard/Change Patch</string>
<string name="string_activate_patch">Activate Patch</string>
@ -131,7 +132,7 @@
<string name="string_in_progress">Processing</string>
<string name="retry">Retry</string>
<string name="string_caution_not_remove_needle_cap">[Caution] DO NOT remove the needle cap and the adhesive backing until further instruction.</string>
<string name="string_are_you_sure_to_discard_current_patch">Are you sure to deiscard the current Patch?</string>
<string name="string_are_you_sure_to_discard_current_patch">Are you sure to discard the current Patch?</string>
<string name="string_unconfirmed_bolus_info_discard_confirm_message">Due to an unconfirmed bolus information, Bolus calc cannot be used until %s.\n\nAre you sure to discard the current Patch?</string>
<string name="needle_insertion_error_1">Needle insertion Error.</string>
<string name="needle_insertion_error_2">Check the direction of the hole left after turning the lever is straight and then Tap \'Retry\'.</string>
@ -147,4 +148,5 @@
<string name="patch_connection_fail">Retry after Patch communication check.</string>
<string name="string_pause_failed">Suspension failed.</string>
<string name="string_resume_failed">Resume failed.</string>
<string name="date_format_yyyy_m_d_e_a_hh_mm_comma">EEE, d MMM, yyyy hh:mm a</string>
</resources>

View file

@ -22,6 +22,7 @@
<string name="string_a116">Patch Error\nPatch has been deactivated and insulin delivery stopped. Change Patch now.</string>
<string name="string_a117">Patch Error\nPatch has been deactivated and insulin delivery stopped. Change Patch now.</string>
<string name="string_a118">Patch Error\nPatch has been deactivated and insulin delivery stopped. Change Patch now.</string>
<string name="string_b000">Patch operating life will expire %s. Be ready to change Patch.</string>
<string name="string_b001">End of insulin suspend\nTap \'Resume\' to restart the insulin delivery.</string>
<string name="string_b003">Low reservoir\nReplace Patch soon.</string>
<string name="string_b005">Patch operating life expired\nChange Patch now.</string>