commit
64e09aadbf
|
@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.text.format.DateFormat
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.activities.ErrorHelperActivity.Companion.runAlarm
|
import info.nightscout.androidaps.activities.ErrorHelperActivity.Companion.runAlarm
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||||
|
@ -11,6 +12,9 @@ import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||||
import info.nightscout.androidaps.events.EventTempBasalChange
|
import info.nightscout.androidaps.events.EventTempBasalChange
|
||||||
|
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
|
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
||||||
|
import info.nightscout.androidaps.extensions.toStringFull
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
@ -40,6 +44,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Constants
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram
|
||||||
import info.nightscout.androidaps.queue.commands.Command
|
import info.nightscout.androidaps.queue.commands.Command
|
||||||
import info.nightscout.androidaps.queue.commands.CustomCommand
|
import info.nightscout.androidaps.queue.commands.CustomCommand
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.TimeChangeType
|
import info.nightscout.androidaps.utils.TimeChangeType
|
||||||
|
@ -51,6 +57,7 @@ import io.reactivex.Single
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import java.lang.Exception
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -73,6 +80,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val aapsSchedulers: AapsSchedulers,
|
private val aapsSchedulers: AapsSchedulers,
|
||||||
private val fabricPrivacy: FabricPrivacy,
|
private val fabricPrivacy: FabricPrivacy,
|
||||||
|
private val dateUtil: DateUtil,
|
||||||
|
|
||||||
injector: HasAndroidInjector,
|
injector: HasAndroidInjector,
|
||||||
aapsLogger: AAPSLogger,
|
aapsLogger: AAPSLogger,
|
||||||
|
@ -84,7 +92,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
|
|
||||||
private val handler: Handler = Handler(Looper.getMainLooper())
|
private val handler: Handler = Handler(Looper.getMainLooper())
|
||||||
private lateinit var statusChecker: Runnable
|
private lateinit var statusChecker: Runnable
|
||||||
var nextPodWarningCheck: Long = 0
|
private var nextPodWarningCheck: Long = 0
|
||||||
@Volatile var stopConnecting: CountDownLatch? = null
|
@Volatile var stopConnecting: CountDownLatch? = null
|
||||||
private var disposables: CompositeDisposable = CompositeDisposable()
|
private var disposables: CompositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
@ -574,7 +582,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
).filter { podEvent -> podEvent.isCommandSent() }
|
).filter { podEvent -> podEvent.isCommandSent() }
|
||||||
.map { pumpSyncBolusStart(requestedBolusAmount, detailedBolusInfo.bolusType) }
|
.map { pumpSyncBolusStart(requestedBolusAmount, detailedBolusInfo.bolusType) }
|
||||||
.ignoreElements(),
|
.ignoreElements(),
|
||||||
post = waitForBolusDeliveryToComplete(BOLUS_RETRIES, requestedBolusAmount, detailedBolusInfo.bolusType)
|
post = waitForBolusDeliveryToComplete(requestedBolusAmount, detailedBolusInfo.bolusType)
|
||||||
.map {
|
.map {
|
||||||
deliveredBolusAmount = it
|
deliveredBolusAmount = it
|
||||||
aapsLogger.info(LTag.PUMP, "deliverTreatment: deliveredBolusAmount=$deliveredBolusAmount")
|
aapsLogger.info(LTag.PUMP, "deliverTreatment: deliveredBolusAmount=$deliveredBolusAmount")
|
||||||
|
@ -638,14 +646,13 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun waitForBolusDeliveryToComplete(
|
private fun waitForBolusDeliveryToComplete(
|
||||||
maxTries: Int,
|
|
||||||
requestedBolusAmount: Double,
|
requestedBolusAmount: Double,
|
||||||
bolusType: DetailedBolusInfo.BolusType
|
bolusType: DetailedBolusInfo.BolusType
|
||||||
): Single<Double> = Single.defer {
|
): Single<Double> = Single.defer {
|
||||||
|
|
||||||
if (bolusCanceled && podStateManager.activeCommand != null) {
|
if (bolusCanceled && podStateManager.activeCommand != null) {
|
||||||
var errorGettingStatus: Throwable? = null
|
var errorGettingStatus: Throwable? = null
|
||||||
for (tries in 1..maxTries) {
|
for (tries in 1..BOLUS_RETRIES) {
|
||||||
errorGettingStatus = getPodStatus().blockingGet()
|
errorGettingStatus = getPodStatus().blockingGet()
|
||||||
if (errorGettingStatus != null) {
|
if (errorGettingStatus != null) {
|
||||||
aapsLogger.debug(LTag.PUMP, "waitForBolusDeliveryToComplete errorGettingStatus=$errorGettingStatus")
|
aapsLogger.debug(LTag.PUMP, "waitForBolusDeliveryToComplete errorGettingStatus=$errorGettingStatus")
|
||||||
|
@ -676,7 +683,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (tryNumber in 1..maxTries) {
|
for (tryNumber in 1..BOLUS_RETRIES) {
|
||||||
updateBolusProgressDialog("Checking delivery status", 100)
|
updateBolusProgressDialog("Checking delivery status", 100)
|
||||||
|
|
||||||
val cmd = if (bolusCanceled)
|
val cmd = if (bolusCanceled)
|
||||||
|
@ -778,7 +785,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
val ret = executeProgrammingCommand(
|
val ret = executeProgrammingCommand(
|
||||||
pre = observeNoActiveTempBasal(true),
|
pre = observeNoActiveTempBasal(),
|
||||||
historyEntry = history.createRecord(
|
historyEntry = history.createRecord(
|
||||||
commandType = OmnipodCommandType.SET_TEMPORARY_BASAL,
|
commandType = OmnipodCommandType.SET_TEMPORARY_BASAL,
|
||||||
tempBasalRecord = TempBasalRecord(duration = durationInMinutes, rate = absoluteRate)
|
tempBasalRecord = TempBasalRecord(duration = durationInMinutes, rate = absoluteRate)
|
||||||
|
@ -848,24 +855,15 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeNoActiveTempBasal(enforceNew: Boolean): Completable {
|
private fun observeNoActiveTempBasal(): Completable {
|
||||||
return Completable.defer {
|
return Completable.defer {
|
||||||
when {
|
if (podStateManager.deliveryStatus !in
|
||||||
podStateManager.deliveryStatus !in
|
arrayOf(DeliveryStatus.TEMP_BASAL_ACTIVE, DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE)
|
||||||
arrayOf(DeliveryStatus.TEMP_BASAL_ACTIVE, DeliveryStatus.BOLUS_AND_TEMP_BASAL_ACTIVE) -> {
|
) {
|
||||||
// TODO: what happens if we try to cancel nonexistent temp basal?
|
// TODO: what happens if we try to cancel nonexistent temp basal?
|
||||||
aapsLogger.info(LTag.PUMP, "No temporary basal to cancel")
|
aapsLogger.info(LTag.PUMP, "No temporary basal to cancel")
|
||||||
Completable.complete()
|
Completable.complete()
|
||||||
}
|
} else {
|
||||||
|
|
||||||
!enforceNew ->
|
|
||||||
Completable.error(
|
|
||||||
IllegalStateException(
|
|
||||||
"Temporary basal already active and enforceNew is not set."
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
// enforceNew == true
|
// enforceNew == true
|
||||||
aapsLogger.info(LTag.PUMP, "Canceling existing temp basal")
|
aapsLogger.info(LTag.PUMP, "Canceling existing temp basal")
|
||||||
executeProgrammingCommand(
|
executeProgrammingCommand(
|
||||||
|
@ -883,7 +881,6 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTempBasalPercent(
|
override fun setTempBasalPercent(
|
||||||
percent: Int,
|
percent: Int,
|
||||||
|
@ -954,9 +951,54 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject {
|
override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject {
|
||||||
// TODO
|
val now = System.currentTimeMillis()
|
||||||
|
if (podStateManager.lastUpdatedSystem + 60 * 60 * 1000L < now) {
|
||||||
return JSONObject()
|
return JSONObject()
|
||||||
}
|
}
|
||||||
|
val pumpJson = JSONObject()
|
||||||
|
val status = JSONObject()
|
||||||
|
val extended = JSONObject()
|
||||||
|
try {
|
||||||
|
val podStatus = when {
|
||||||
|
podStateManager.isPodRunning && podStateManager.isSuspended ->
|
||||||
|
"suspended"
|
||||||
|
podStateManager.isPodRunning ->
|
||||||
|
"normal"
|
||||||
|
else ->
|
||||||
|
"no active Pod"
|
||||||
|
}
|
||||||
|
status.put("status", podStatus)
|
||||||
|
status.put("timestamp", dateUtil.toISOString(podStateManager.lastUpdatedSystem))
|
||||||
|
|
||||||
|
extended.put("Version", version)
|
||||||
|
try {
|
||||||
|
extended.put("ActiveProfile", profileName)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
}
|
||||||
|
val tb = pumpSync.expectedPumpState().temporaryBasal
|
||||||
|
tb?.run {
|
||||||
|
extended.put("TempBasalAbsoluteRate", this.convertedToAbsolute(now, profile))
|
||||||
|
extended.put("TempBasalStart", dateUtil.dateAndTimeString(this.timestamp))
|
||||||
|
extended.put("TempBasalRemaining", this.plannedRemainingMinutes)
|
||||||
|
}
|
||||||
|
podStateManager.lastBolus?.run {
|
||||||
|
extended.put("LastBolus", dateUtil.dateAndTimeString(this.startTime))
|
||||||
|
extended.put("LastBolusAmount", this.deliveredUnits() ?: this.requestedUnits)
|
||||||
|
}
|
||||||
|
extended.put("BaseBasalRate", baseBasalRate)
|
||||||
|
|
||||||
|
pumpJson.put("status", status)
|
||||||
|
pumpJson.put("extended", extended)
|
||||||
|
if (podStateManager.pulsesRemaining == null) {
|
||||||
|
pumpJson.put("reservoir_display_override", "50+")
|
||||||
|
}
|
||||||
|
pumpJson.put("reservoir", reservoirLevel.toInt())
|
||||||
|
pumpJson.put("clock", dateUtil.toISOString(now))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
aapsLogger.error(LTag.PUMP, "Unhandled exception: $e")
|
||||||
|
}
|
||||||
|
return pumpJson
|
||||||
|
}
|
||||||
|
|
||||||
override val pumpDescription: PumpDescription = Companion.pumpDescription
|
override val pumpDescription: PumpDescription = Companion.pumpDescription
|
||||||
|
|
||||||
|
@ -974,8 +1016,33 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shortStatus(veryShort: Boolean): String {
|
override fun shortStatus(veryShort: Boolean): String {
|
||||||
// TODO
|
if (!podStateManager.isActivationCompleted) {
|
||||||
return "TODO"
|
return resourceHelper.gs(R.string.omnipod_common_short_status_no_active_pod)
|
||||||
|
}
|
||||||
|
var ret = ""
|
||||||
|
if (podStateManager.lastUpdatedSystem != 0L) {
|
||||||
|
val agoMsec: Long = System.currentTimeMillis() - podStateManager.lastUpdatedSystem
|
||||||
|
val agoMin = (agoMsec / 60.0 / 1000.0).toInt()
|
||||||
|
ret += resourceHelper.gs(R.string.omnipod_common_short_status_last_connection, agoMin) + "\n"
|
||||||
|
}
|
||||||
|
podStateManager.lastBolus?.run {
|
||||||
|
ret += resourceHelper.gs(
|
||||||
|
R.string.omnipod_common_short_status_last_bolus, to2Decimal(this.deliveredUnits() ?: this.requestedUnits),
|
||||||
|
DateFormat.format("HH:mm", Date(this.startTime))
|
||||||
|
) + "\n"
|
||||||
|
}
|
||||||
|
val (temporaryBasal, extendedBolus, _, profile) = pumpSync.expectedPumpState()
|
||||||
|
temporaryBasal?.run {
|
||||||
|
ret += resourceHelper.gs(
|
||||||
|
R.string.omnipod_common_short_status_temp_basal,
|
||||||
|
this.toStringFull(dateUtil)
|
||||||
|
) + "\n"
|
||||||
|
}
|
||||||
|
ret += resourceHelper.gs(
|
||||||
|
R.string.omnipod_common_short_status_reservoir,
|
||||||
|
podStateManager.pulsesRemaining?.let { reservoirLevel.toString() } ?: "50+"
|
||||||
|
)
|
||||||
|
return ret.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isFakingTempsByExtendedBoluses: Boolean
|
override val isFakingTempsByExtendedBoluses: Boolean
|
||||||
|
@ -1348,7 +1415,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
||||||
pumpId = historyEntry.pumpId(),
|
pumpId = historyEntry.pumpId(),
|
||||||
pumpType = PumpType.OMNIPOD_DASH,
|
pumpType = PumpType.OMNIPOD_DASH,
|
||||||
pumpSerial = serialNumber(),
|
pumpSerial = serialNumber(),
|
||||||
type = null // TODO: set the correct bolus type here!!!
|
type = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
rxBus.send(EventDismissNotification(Notification.OMNIPOD_UNCERTAIN_SMB))
|
rxBus.send(EventDismissNotification(Notification.OMNIPOD_UNCERTAIN_SMB))
|
||||||
|
|
|
@ -9,9 +9,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.*
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.GetVersionCommand.Companion.DEFAULT_UNIQUE_ID
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.GetVersionCommand.Companion.DEFAULT_UNIQUE_ID
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.*
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.*
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.MAX_POD_LIFETIME
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.MAX_POD_LIFETIME
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_ALERT_HOURS
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_ALERT_HOURS_DURATION
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_ALERT_HOURS_DURATION
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_IMMINENT_ALERT_HOURS
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_IMMINENT_ALERT_HOURS
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants.Companion.POD_EXPIRATION_ALERT_HOURS
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.*
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.*
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition
|
||||||
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class PodConstants {
|
class PodConstants {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.AlertUtil
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.AlertUtil
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Flag
|
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
|
|
|
@ -629,8 +629,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
override fun connectionSuccessRatio(): Float {
|
override fun connectionSuccessRatio(): Float {
|
||||||
if (connectionAttempts == 0) {
|
if (connectionAttempts == 0) {
|
||||||
return 0.0F
|
return 0.0F
|
||||||
}
|
} else if (connectionAttempts <= successfulConnections) {
|
||||||
else if (connectionAttempts <= successfulConnections) {
|
|
||||||
// Prevent bogus quality > 1 during initialisation
|
// Prevent bogus quality > 1 during initialisation
|
||||||
return 1.0F
|
return 1.0F
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.databinding.OmnipodD
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.databinding.OmnipodDashOverviewBluetoothStatusBinding
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.databinding.OmnipodDashOverviewBluetoothStatusBinding
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ActivationProgress
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ActivationProgress
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
|
||||||
import info.nightscout.androidaps.queue.Callback
|
import info.nightscout.androidaps.queue.Callback
|
||||||
import info.nightscout.androidaps.queue.events.EventQueueChanged
|
import info.nightscout.androidaps.queue.events.EventQueueChanged
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
|
Loading…
Reference in a new issue