From e1a996b3f7c316790937b91c2e14c22579e269ec Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 27 Jun 2021 01:38:34 +0200 Subject: [PATCH 01/29] wip --- .../driver/comm/OmnipodDashBleManagerImpl.kt | 3 +- .../dash/driver/comm/session/Connection.kt | 99 +++++++------------ 2 files changed, 40 insertions(+), 62 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt index 73a91f070a..1afb561c81 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt @@ -210,9 +210,10 @@ class OmnipodDashBleManagerImpl @Inject constructor( emitter.onNext(PodEvent.BluetoothConnected(podAddress)) emitter.onNext(PodEvent.Pairing) + val mIO = conn.msgIO ?: throw ConnectException("Connection lost") val ltkExchanger = LTKExchanger( aapsLogger, - conn.msgIO, + mIO, ids, ) val pairResult = ltkExchanger.negotiateLTK() diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index 98d4c9ff8c..2211bc672d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -13,6 +13,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Ids import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ServiceDiscoverer import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt.EnDecrypt +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ConnectException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleSendSuccess import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.CharacteristicType @@ -24,94 +25,67 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.Omn sealed class ConnectionState +object Connecting: ConnectionState() +object Handshaking: ConnectionState() object Connected : ConnectionState() object NotConnected : ConnectionState() class Connection( private val podDevice: BluetoothDevice, private val aapsLogger: AAPSLogger, - context: Context, + private val context: Context, private val podState: OmnipodDashPodStateManager ) : DisconnectHandler { private val incomingPackets = IncomingPackets() private val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets, this) - private val gattConnection: BluetoothGatt + private var gattConnection: BluetoothGatt? = null private val bluetoothManager: BluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - // The session is Synchronized because we can lose the connection right when establishing it + @Volatile var session: Session? = null - @Synchronized get - @Synchronized set - private val cmdBleIO: CmdBleIO - private val dataBleIO: DataBleIO - init { - aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to ${podDevice.address}") - - val autoConnect = false - podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING - gattConnection = podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) - // OnDisconnect can be called after this point!!! - val state = waitForConnection(2) - if (state !is Connected) { - podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED - throw FailedToConnectException(podDevice.address) - } - podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED - val discoverer = ServiceDiscoverer(aapsLogger, gattConnection, bleCommCallbacks) - val discoveredCharacteristics = discoverer.discoverServices() - cmdBleIO = CmdBleIO( - aapsLogger, - discoveredCharacteristics[CharacteristicType.CMD]!!, - incomingPackets - .cmdQueue, - gattConnection, - bleCommCallbacks - ) - dataBleIO = DataBleIO( - aapsLogger, - discoveredCharacteristics[CharacteristicType.DATA]!!, - incomingPackets - .dataQueue, - gattConnection, - bleCommCallbacks - ) - - val sendResult = cmdBleIO.hello() - if (sendResult !is BleSendSuccess) { - throw FailedToConnectException("Could not send HELLO command to ${podDevice.address}") - } - cmdBleIO.readyToRead() - dataBleIO.readyToRead() - } - - val msgIO = MessageIO(aapsLogger, cmdBleIO, dataBleIO) + @Volatile + var msgIO: MessageIO? = null fun connect(timeoutMultiplier: Int) { - if (session != null) { - disconnect() - } aapsLogger.debug("Connecting") podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING - - if (!gattConnection.connect()) { + val autoConnect = false + val gatt = gattConnection ?: + podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) + gattConnection = gatt + if (!gatt.connect()) { throw FailedToConnectException("connect() returned false") } - + // TODO: loop if (waitForConnection(timeoutMultiplier) !is Connected) { podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED throw FailedToConnectException(podDevice.address) } podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED - val discoverer = ServiceDiscoverer(aapsLogger, gattConnection, bleCommCallbacks) + val discoverer = ServiceDiscoverer(aapsLogger, gatt, bleCommCallbacks) val discovered = discoverer.discoverServices() - dataBleIO.characteristic = discovered[CharacteristicType.DATA]!! - cmdBleIO.characteristic = discovered[CharacteristicType.CMD]!! - + val cmdBleIO = CmdBleIO( + aapsLogger, + discovered[CharacteristicType.CMD]!!, + incomingPackets + .cmdQueue, + gatt, + bleCommCallbacks + ) + val dataBleIO = DataBleIO( + aapsLogger, + discovered[CharacteristicType.DATA]!!, + incomingPackets + .dataQueue, + gatt, + bleCommCallbacks + ) + msgIO = MessageIO(aapsLogger, cmdBleIO, dataBleIO) // val ret = gattConnection.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH) // aapsLogger.info(LTag.PUMPBTCOMM, "requestConnectionPriority: $ret") cmdBleIO.hello() @@ -123,9 +97,10 @@ class Connection( aapsLogger.debug(LTag.PUMPBTCOMM, "Disconnecting") podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED - gattConnection.disconnect() + gattConnection?.disconnect() bleCommCallbacks.resetConnection() session = null + msgIO = null } private fun waitForConnection(timeoutMultiplier: Int): ConnectionState { @@ -148,7 +123,9 @@ class Connection( } fun establishSession(ltk: ByteArray, msgSeq: Byte, ids: Ids, eapSqn: ByteArray): EapSqn? { - val eapAkaExchanger = SessionEstablisher(aapsLogger, msgIO, ltk, eapSqn, ids, msgSeq) + val mIO = msgIO ?: throw ConnectException("Connection lost") + + val eapAkaExchanger = SessionEstablisher(aapsLogger, mIO, ltk, eapSqn, ids, msgSeq) return when (val keys = eapAkaExchanger.negotiateSessionKeys()) { is SessionNegotiationResynchronization -> { if (BuildConfig.DEBUG) { @@ -168,7 +145,7 @@ class Connection( keys.nonce, keys.ck ) - session = Session(aapsLogger, msgIO, ids, sessionKeys = keys, enDecrypt = enDecrypt) + session = Session(aapsLogger, mIO, ids, sessionKeys = keys, enDecrypt = enDecrypt) null } } From 9c0aa54e6b2ad829afb5ac566364770cf71ac9fa Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 27 Jun 2021 13:19:01 +0200 Subject: [PATCH 02/29] stop on CountDownLatch --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 2 +- .../dash/driver/comm/OmnipodDashBleManager.kt | 8 ++++- .../driver/comm/OmnipodDashBleManagerImpl.kt | 30 ++++++++-------- .../driver/comm/callbacks/BleCommCallbacks.kt | 5 +-- .../dash/driver/comm/session/Connection.kt | 35 +++++++++++++++---- 5 files changed, 54 insertions(+), 26 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index b2d0fe6b83..9585f79885 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -71,7 +71,7 @@ class OmnipodDashPumpPlugin @Inject constructor( ) : PumpPluginBase(pluginDescription, injector, aapsLogger, resourceHelper, commandQueue), Pump { @Volatile var bolusCanceled = false private val handler: Handler = Handler(Looper.getMainLooper()) - lateinit private var statusChecker: Runnable + private lateinit var statusChecker: Runnable var nextPodWarningCheck : Long = 0 companion object { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt index b2400713c7..135fdf295f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt @@ -1,10 +1,12 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.Connection import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.ConnectionState import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response import io.reactivex.Observable +import java.util.concurrent.CountDownLatch import kotlin.reflect.KClass interface OmnipodDashBleManager { @@ -13,7 +15,11 @@ interface OmnipodDashBleManager { fun getStatus(): ConnectionState - fun connect(): Observable + // used for sync connections + fun connect(timeoutMs: Long = Connection.BASE_CONNECT_TIMEOUT_MS*3): Observable + + // used for async connections + fun connect(stopConnectionLatch: CountDownLatch): Observable fun pairNewPod(): Observable diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt index 1afb561c81..8e78afd954 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt @@ -16,6 +16,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.b import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import io.reactivex.Observable +import java.util.concurrent.CountDownLatch import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject import javax.inject.Singleton @@ -100,8 +101,19 @@ class OmnipodDashBleManagerImpl @Inject constructor( return connection?.let { it.connectionState() } ?: NotConnected } + // used for sync connections + override fun connect(timeoutMs: Long): Observable { + return connect(ConnectionWaitCondition(timeoutMs = timeoutMs)) + } - override fun connect(): Observable = Observable.create { emitter -> + // used for async connections + override fun connect(stopConnectionLatch: CountDownLatch): Observable { + return connect(ConnectionWaitCondition(stopConnection = stopConnectionLatch)) + } + + private fun connect(connectionWaitCond: ConnectionWaitCondition): Observable = Observable + .create { + emitter -> if (!busy.compareAndSet(false, true)) { throw BusyException() } @@ -121,20 +133,7 @@ class OmnipodDashBleManagerImpl @Inject constructor( return@create } - // two retries - for (i in 1..MAX_NUMBER_OF_CONNECTION_ATTEMPTS) { - try { - // wait i * CONNECTION_TIMEOUT - conn.connect(4) - break - } catch (e: Exception) { - aapsLogger.warn(LTag.PUMPBTCOMM, "connect error=$e") - if (i == MAX_NUMBER_OF_CONNECTION_ATTEMPTS) { - emitter.onError(e) - return@create - } - } - } + conn.connect(connectionWaitCond) emitter.onNext(PodEvent.BluetoothConnected(podAddress)) emitter.onNext(PodEvent.EstablishingSession) @@ -207,6 +206,7 @@ class OmnipodDashBleManagerImpl @Inject constructor( val podDevice = bluetoothAdapter.getRemoteDevice(podAddress) val conn = Connection(podDevice, aapsLogger, context, podState) connection = conn + conn.connect(ConnectionWaitCondition(timeoutMs = 3 * Connection.BASE_CONNECT_TIMEOUT_MS)) emitter.onNext(PodEvent.BluetoothConnected(podAddress)) emitter.onNext(PodEvent.Pairing) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index 3d4d3d1339..471467235d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -53,12 +53,13 @@ class BleCommCallbacks( } } - fun waitForConnection(timeoutMs: Int) { + fun waitForConnection(timeoutMs: Long): Boolean { try { - connected.await(timeoutMs.toLong(), TimeUnit.MILLISECONDS) + connected.await(timeoutMs, TimeUnit.MILLISECONDS) } catch (e: InterruptedException) { aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while waiting for Connection") } + return connected.count == 0L } fun startServiceDiscovery() { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index 2211bc672d..3ea2fc44e1 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -15,13 +15,14 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callback import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt.EnDecrypt import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ConnectException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleSendSuccess import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.CharacteristicType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.CmdBleIO import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.DataBleIO import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.IncomingPackets import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageIO import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager +import java.lang.IllegalArgumentException +import java.util.concurrent.CountDownLatch sealed class ConnectionState @@ -30,6 +31,17 @@ object Handshaking: ConnectionState() object Connected : ConnectionState() object NotConnected : ConnectionState() +data class ConnectionWaitCondition(val timeoutMs: Long?=null, val stopConnection: CountDownLatch?=null) { + init { + if (timeoutMs == null && stopConnection == null) { + throw IllegalArgumentException("One of timeoutMs or stopConnection has to be non null") + } + if (timeoutMs != null && stopConnection != null) { + throw IllegalArgumentException("One of timeoutMs or stopConnection has to be null") + } + } +} + class Connection( private val podDevice: BluetoothDevice, private val aapsLogger: AAPSLogger, @@ -50,8 +62,9 @@ class Connection( @Volatile var msgIO: MessageIO? = null - fun connect(timeoutMultiplier: Int) { + fun connect(connectionWaitCond: ConnectionWaitCondition) { aapsLogger.debug("Connecting") + podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING val autoConnect = false val gatt = gattConnection ?: @@ -60,8 +73,7 @@ class Connection( if (!gatt.connect()) { throw FailedToConnectException("connect() returned false") } - // TODO: loop - if (waitForConnection(timeoutMultiplier) !is Connected) { + if (waitForConnection(connectionWaitCond) !is Connected) { podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED throw FailedToConnectException(podDevice.address) } @@ -103,9 +115,18 @@ class Connection( msgIO = null } - private fun waitForConnection(timeoutMultiplier: Int): ConnectionState { + private fun waitForConnection(connectionWaitCond: ConnectionWaitCondition): ConnectionState { try { - bleCommCallbacks.waitForConnection(BASE_CONNECT_TIMEOUT_MS * timeoutMultiplier) + connectionWaitCond.timeoutMs?.let { + bleCommCallbacks.waitForConnection(it) + } + connectionWaitCond.stopConnection?.let { + while (!bleCommCallbacks.waitForConnection(300)) { + if (it.count == 0L) { + return NotConnected + } + } + } } catch (e: InterruptedException) { // We are still going to check if connection was successful aapsLogger.info(LTag.PUMPBTCOMM, "Interrupted while waiting for connection") @@ -158,6 +179,6 @@ class Connection( } companion object { - private const val BASE_CONNECT_TIMEOUT_MS = 10000 + const val BASE_CONNECT_TIMEOUT_MS = 10000L } } From 0582fe03268dcd7465dfb1e3252effb3d8bb6978 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 27 Jun 2021 22:12:21 +0200 Subject: [PATCH 03/29] timeout for service discovery --- .../dash/driver/comm/ServiceDiscoverer.kt | 19 +++++++++++----- .../driver/comm/callbacks/BleCommCallbacks.kt | 4 ++-- .../dash/driver/comm/session/Connection.kt | 22 +++++++++++++++---- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt index 664db805e0..1d1e24ba42 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -7,6 +7,8 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ConnectException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.CharacteristicType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.Connection.Companion.STOP_CONNECTING_CHECK_INTERVAL_MS +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.ConnectionWaitCondition import java.math.BigInteger import java.util.* @@ -19,14 +21,23 @@ class ServiceDiscoverer( /*** * This is first step after connection establishment */ - fun discoverServices(): Map { + fun discoverServices(connectionWaitCond: ConnectionWaitCondition): Map { logger.debug(LTag.PUMPBTCOMM, "Discovering services") bleCallbacks.startServiceDiscovery() val discover = gatt.discoverServices() if (!discover) { throw ConnectException("Could not start discovering services`") } - bleCallbacks.waitForServiceDiscovery(DISCOVER_SERVICES_TIMEOUT_MS) + connectionWaitCond.timeoutMs?.let { + bleCallbacks.waitForServiceDiscovery(it) + } + connectionWaitCond.stopConnection?.let { + while (!bleCallbacks.waitForConnection(STOP_CONNECTING_CHECK_INTERVAL_MS)) { + if (it.count == 0L) { + throw ConnectException("stopConnecting called") + } + } + } logger.debug(LTag.PUMPBTCOMM, "Services discovered") val service = gatt.getService(SERVICE_UUID.toUuid()) ?: throw ConnectException("Service not found: $SERVICE_UUID") @@ -34,11 +45,10 @@ class ServiceDiscoverer( ?: throw ConnectException("Characteristic not found: ${CharacteristicType.CMD.value}") val dataChar = service.getCharacteristic(CharacteristicType.DATA.uuid) ?: throw ConnectException("Characteristic not found: ${CharacteristicType.DATA.value}") - var chars = mapOf( + return mapOf( CharacteristicType.CMD to cmdChar, CharacteristicType.DATA to dataChar ) - return chars } private fun String.toUuid(): UUID = UUID( @@ -49,6 +59,5 @@ class ServiceDiscoverer( companion object { private const val SERVICE_UUID = "1a7e-4024-e3ed-4464-8b7e-751e03d0dc5f" - private const val DISCOVER_SERVICES_TIMEOUT_MS = 5000 } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index 471467235d..2a668065f0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -66,9 +66,9 @@ class BleCommCallbacks( serviceDiscoveryComplete = CountDownLatch(1) } - fun waitForServiceDiscovery(timeoutMs: Int) { + fun waitForServiceDiscovery(timeoutMs: Long) { try { - serviceDiscoveryComplete.await(timeoutMs.toLong(), TimeUnit.MILLISECONDS) + serviceDiscoveryComplete.await(timeoutMs, TimeUnit.MILLISECONDS) } catch (e: InterruptedException) { aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while waiting for ServiceDiscovery") } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index 3ea2fc44e1..d86fc8cbc0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -5,6 +5,7 @@ import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothProfile import android.content.Context +import android.os.SystemClock import info.nightscout.androidaps.extensions.toHex import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -23,6 +24,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message. import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import java.lang.IllegalArgumentException import java.util.concurrent.CountDownLatch +import kotlin.math.absoluteValue sealed class ConnectionState @@ -31,7 +33,7 @@ object Handshaking: ConnectionState() object Connected : ConnectionState() object NotConnected : ConnectionState() -data class ConnectionWaitCondition(val timeoutMs: Long?=null, val stopConnection: CountDownLatch?=null) { +data class ConnectionWaitCondition(var timeoutMs: Long?=null, val stopConnection: CountDownLatch?=null) { init { if (timeoutMs == null && stopConnection == null) { throw IllegalArgumentException("One of timeoutMs or stopConnection has to be non null") @@ -73,14 +75,24 @@ class Connection( if (!gatt.connect()) { throw FailedToConnectException("connect() returned false") } + val before = SystemClock.elapsedRealtime() if (waitForConnection(connectionWaitCond) !is Connected) { podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED throw FailedToConnectException(podDevice.address) } + val waitedMs = SystemClock.elapsedRealtime() - before + val timeoutMs = connectionWaitCond.timeoutMs + if (timeoutMs != null) { + var newTimeout = timeoutMs - waitedMs + if (newTimeout < MIN_DISCOVERY_TIMEOUT_MS) { + newTimeout = MIN_DISCOVERY_TIMEOUT_MS + } + connectionWaitCond.timeoutMs = newTimeout + } podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED val discoverer = ServiceDiscoverer(aapsLogger, gatt, bleCommCallbacks) - val discovered = discoverer.discoverServices() + val discovered = discoverer.discoverServices(connectionWaitCond) val cmdBleIO = CmdBleIO( aapsLogger, discovered[CharacteristicType.CMD]!!, @@ -121,9 +133,9 @@ class Connection( bleCommCallbacks.waitForConnection(it) } connectionWaitCond.stopConnection?.let { - while (!bleCommCallbacks.waitForConnection(300)) { + while (!bleCommCallbacks.waitForConnection(STOP_CONNECTING_CHECK_INTERVAL_MS)) { if (it.count == 0L) { - return NotConnected + ConnectException("stopConnecting called") } } } @@ -180,5 +192,7 @@ class Connection( companion object { const val BASE_CONNECT_TIMEOUT_MS = 10000L + const val MIN_DISCOVERY_TIMEOUT_MS = 10000L + const val STOP_CONNECTING_CHECK_INTERVAL_MS = 500L } } From b4777a1312135799695170662ea3512e190c9be9 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Mon, 28 Jun 2021 20:54:47 +0200 Subject: [PATCH 04/29] wip: stop connecting --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 23 +++++++++++++++---- .../omnipod/dash/driver/OmnipodDashManager.kt | 4 ++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 9585f79885..7c9059c558 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -48,8 +48,10 @@ import io.reactivex.Completable import io.reactivex.Single import org.json.JSONObject import java.util.* +import java.util.concurrent.CountDownLatch import javax.inject.Inject import javax.inject.Singleton +import kotlin.concurrent.thread import kotlin.math.ceil import kotlin.random.Random @@ -73,6 +75,7 @@ class OmnipodDashPumpPlugin @Inject constructor( private val handler: Handler = Handler(Looper.getMainLooper()) private lateinit var statusChecker: Runnable var nextPodWarningCheck : Long = 0 + @Volatile var stopConnecting: CountDownLatch? = null companion object { private const val BOLUS_RETRY_INTERVAL_MS = 2000.toLong() @@ -171,19 +174,29 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun connect(reason: String) { - // empty on purpose + thread( + start = true, + name = "ConnectionThread", + ) { + // TODO quadruple check that we are not creating a party of Threads here + try { + val stop = CountDownLatch(1) + stopConnecting = stop + omnipodManager.connect(stop) + } finally { + stopConnecting = null + } + } } override fun disconnect(reason: String) { - // TODO + omnipodManager.disconnect() } override fun stopConnecting() { - // TODO + stopConnecting?.let { it.countDown() } } - - override fun getPumpStatus(reason: String) { aapsLogger.debug(LTag.PUMP, "getPumpStatus reason=$reason") if (reason != "REQUESTED BY USER" && !podStateManager.isActivationCompleted) { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt index 0a5b743f94..a905016f99 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType import io.reactivex.Observable import java.util.* +import java.util.concurrent.CountDownLatch interface OmnipodDashManager { @@ -39,4 +40,7 @@ interface OmnipodDashManager { fun silenceAlerts(alertTypes: EnumSet): Observable fun deactivatePod(): Observable + + fun disconnect() + fun connect(stop: CountDownLatch) } From 131c187bb1a150bab430c5d50b92bb09aac99c8a Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Mon, 28 Jun 2021 23:02:16 +0200 Subject: [PATCH 05/29] fake tbr when the pod is not active --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 24 +++++++++++++++++-- .../action/DashInsertCannulaViewModel.kt | 6 +++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index b2d0fe6b83..1ab98f1983 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -51,6 +51,7 @@ import java.util.* import javax.inject.Inject import javax.inject.Singleton import kotlin.math.ceil +import kotlin.math.exp import kotlin.random.Random @Singleton @@ -95,10 +96,31 @@ class OmnipodDashPumpPlugin @Inject constructor( statusChecker = Runnable { refreshStatusOnUnacknowledgedCommands() updatePodWarnings() + createFakeTBRWhenNoActivePod() handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS) } } + private fun createFakeTBRWhenNoActivePod() { + if (!podStateManager.isPodRunning) { + val expectedState = pumpSync.expectedPumpState() + val tbr = expectedState.temporaryBasal + if (tbr == null || tbr.rate!=0.0) { + aapsLogger.info(LTag.PUMP, "createFakeTBRWhenNoActivePod") + pumpSync.syncTemporaryBasalWithPumpId( + timestamp = System.currentTimeMillis(), + rate = 0.0, + duration = T.mins(PodConstants.MAX_POD_LIFETIME.standardMinutes).msecs(), + isAbsolute = true, + type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, + pumpId = Random.Default.nextLong(), // we don't use this, just make sure it's unique + pumpType = PumpType.OMNIPOD_DASH, + pumpSerial = serialNumber() + ) + } + } + } + private fun updatePodWarnings() { if (System.currentTimeMillis() > nextPodWarningCheck) { if (!podStateManager.isPodRunning) { @@ -182,8 +204,6 @@ class OmnipodDashPumpPlugin @Inject constructor( // TODO } - - override fun getPumpStatus(reason: String) { aapsLogger.debug(LTag.PUMP, "getPumpStatus reason=$reason") if (reason != "REQUESTED BY USER" && !podStateManager.isActivationCompleted) { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index 143fb8fb91..874ccbd4f1 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -71,6 +71,12 @@ class DashInsertCannulaViewModel @Inject constructor( pumpType = PumpType.OMNIPOD_DASH, pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" ) + pumpSync.syncStopTemporaryBasalWithPumpId( + timestamp = System.currentTimeMillis(), + endPumpId = System.currentTimeMillis(), + pumpType = PumpType.OMNIPOD_DASH, + pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" + ) source.onSuccess(PumpEnactResult(injector).success(true)) } ) From 33891e509a8c62aacc45d18fc73a5b1b6b1f9163 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Tue, 29 Jun 2021 19:46:11 +0200 Subject: [PATCH 06/29] connect --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 9 ++++++--- .../omnipod/dash/driver/OmnipodDashManager.kt | 3 ++- .../dash/driver/OmnipodDashManagerImpl.kt | 20 +++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 7c9059c558..80508a90e7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -156,12 +156,13 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun isConnected(): Boolean { - return true + return !podStateManager.isPodRunning || + podStateManager.bluetoothConnectionState == OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED } override fun isConnecting(): Boolean { // TODO - return false + return stopConnecting != null } override fun isHandshakeInProgress(): Boolean { @@ -182,7 +183,8 @@ class OmnipodDashPumpPlugin @Inject constructor( try { val stop = CountDownLatch(1) stopConnecting = stop - omnipodManager.connect(stop) + val error = omnipodManager.connect(stop).ignoreElements().blockingGet() + aapsLogger.info(LTag.PUMPCOMM, "connect error=$error") } finally { stopConnecting = null } @@ -190,6 +192,7 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun disconnect(reason: String) { + stopConnecting?.let { it.countDown() } omnipodManager.disconnect() } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt index a905016f99..24b09dfc79 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt @@ -42,5 +42,6 @@ interface OmnipodDashManager { fun deactivatePod(): Observable fun disconnect() - fun connect(stop: CountDownLatch) + + fun connect(stop: CountDownLatch): Observable } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index 487ecf2c6c..e504f2a3b7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -15,6 +15,7 @@ import io.reactivex.Observable import io.reactivex.functions.Action import io.reactivex.functions.Consumer import java.util.* +import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton @@ -74,6 +75,25 @@ class OmnipodDashManagerImpl @Inject constructor( } } + override fun disconnect() { + bleManager.disconnect() + } + + override fun connect(stop: CountDownLatch): Observable { + return observeConnectToPodWithStop(stop) + // TODO these would be common for any observable returned in a public function in this class + .doOnNext(PodEventInterceptor()) + .doOnError(ErrorInterceptor()) + .subscribeOn(aapsSchedulers.io) + } + + private fun observeConnectToPodWithStop(stop: CountDownLatch): Observable { + return Observable.defer { + bleManager.connect(stop) + .doOnError { throwable -> logger.warn(LTag.PUMPBTCOMM, "observeConnectToPodWithStop error=$throwable") } + } + } + private val observeConnectToPod: Observable get() = Observable.defer { bleManager.connect() From 4fc0a347852c0550a952abb5bb672dbd87f1df4d Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 18:05:06 +0200 Subject: [PATCH 07/29] cleanup --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 3 ++- .../omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt | 4 ---- .../pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt | 2 +- .../omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt | 3 ++- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index cdaf088247..d56796b68c 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -99,7 +99,8 @@ class OmnipodDashPumpPlugin @Inject constructor( statusChecker = Runnable { refreshStatusOnUnacknowledgedCommands() updatePodWarnings() - createFakeTBRWhenNoActivePod() + // createFakeTBRWhenNoActivePod() + // TODO: this is called from the main thread handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS) } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt index 7565be0acd..1c873bd8ab 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt @@ -186,7 +186,6 @@ class OmnipodDashBleManagerImpl @Inject constructor( throw BusyException() } try { - if (podState.ltk != null) { emitter.onNext(PodEvent.AlreadyPaired) emitter.onComplete() @@ -222,7 +221,6 @@ class OmnipodDashBleManagerImpl @Inject constructor( if (BuildConfig.DEBUG) { aapsLogger.info(LTag.PUMPCOMM, "Got LTK: ${pairResult.ltk.toHex()}") } - emitter.onNext(PodEvent.EstablishingSession) establishSession(pairResult.msgSeq) emitter.onNext(PodEvent.Connected) @@ -241,8 +239,6 @@ class OmnipodDashBleManagerImpl @Inject constructor( } companion object { - const val MAX_NUMBER_OF_CONNECTION_ATTEMPTS = 2 const val CONTROLLER_ID = 4242 // TODO read from preferences or somewhere else. - private const val CONNECT_TIMEOUT_MULTIPLIER = 4 } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt index 1d1e24ba42..3bc367d47c 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -32,7 +32,7 @@ class ServiceDiscoverer( bleCallbacks.waitForServiceDiscovery(it) } connectionWaitCond.stopConnection?.let { - while (!bleCallbacks.waitForConnection(STOP_CONNECTING_CHECK_INTERVAL_MS)) { + while (!bleCallbacks.waitForServiceDiscovery(STOP_CONNECTING_CHECK_INTERVAL_MS)) { if (it.count == 0L) { throw ConnectException("stopConnecting called") } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index 2a668065f0..7f8b907ec8 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -66,12 +66,13 @@ class BleCommCallbacks( serviceDiscoveryComplete = CountDownLatch(1) } - fun waitForServiceDiscovery(timeoutMs: Long) { + fun waitForServiceDiscovery(timeoutMs: Long): Boolean { try { serviceDiscoveryComplete.await(timeoutMs, TimeUnit.MILLISECONDS) } catch (e: InterruptedException) { aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while waiting for ServiceDiscovery") } + return serviceDiscoveryComplete.count == 0L } fun confirmWrite(expectedPayload: ByteArray, expectedUUID: String, timeoutMs: Long): WriteConfirmation { From 99ca414d877a5db891af669be4df9c61b0956170 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 18:19:41 +0200 Subject: [PATCH 08/29] dismiss OMNIPOD_POD_NOT_ATTACHED on pod activation. add logging --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 3 +++ .../viewmodel/action/DashInsertCannulaViewModel.kt | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index d56796b68c..056c39813f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -198,6 +198,7 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun connect(reason: String) { + aapsLogger.info(LTag.PUMP, "connect reason=$reason") thread( start = true, name = "ConnectionThread", @@ -215,11 +216,13 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun disconnect(reason: String) { + aapsLogger.info(LTag.PUMP, "disconnect reason=$reason") stopConnecting?.let { it.countDown() } omnipodManager.disconnect() } override fun stopConnecting() { + aapsLogger.info(LTag.PUMP, "stopConnecting") stopConnecting?.let { it.countDown() } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index 874ccbd4f1..2d3883d4d4 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -8,6 +8,9 @@ import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel import info.nightscout.androidaps.plugins.pump.omnipod.dash.R @@ -23,6 +26,8 @@ class DashInsertCannulaViewModel @Inject constructor( private val profileFunction: ProfileFunction, private val pumpSync: PumpSync, private val podStateManager: OmnipodDashPodStateManager, + private val rxBus: RxBusWrapper, + injector: HasAndroidInjector, logger: AAPSLogger ) : InsertCannulaViewModel(injector, logger) { @@ -77,6 +82,7 @@ class DashInsertCannulaViewModel @Inject constructor( pumpType = PumpType.OMNIPOD_DASH, pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" ) + rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED)) source.onSuccess(PumpEnactResult(injector).success(true)) } ) From 7a72cf2f19070ec73caa43ce05d843b2644775a9 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 18:35:28 +0200 Subject: [PATCH 09/29] pod expiry: use let --- .../dash/driver/comm/session/Connection.kt | 1 - .../dash/ui/OmnipodDashOverviewFragment.kt | 23 ++++++++----------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index d86fc8cbc0..4b4ca44f00 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -29,7 +29,6 @@ import kotlin.math.absoluteValue sealed class ConnectionState object Connecting: ConnectionState() -object Handshaking: ConnectionState() object Connected : ConnectionState() object NotConnected : ConnectionState() diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 59e90ef7dc..e2644da1b9 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -1,6 +1,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui import android.content.Intent +import android.content.res.ColorStateList import android.graphics.Color import android.os.Bundle import android.os.Handler @@ -284,19 +285,15 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // Update Pod expiry time val expiresAt = podStateManager.expiry - if (expiresAt == null) { - podInfoBinding.podExpiryDate.text = PLACEHOLDER - podInfoBinding.podExpiryDate.setTextColor(Color.WHITE) - } else { - podInfoBinding.podExpiryDate.text = readableZonedTime(expiresAt) - podInfoBinding.podExpiryDate.setTextColor( - if (DateTime.now().isAfter(expiresAt)) { - Color.RED - } else { - Color.WHITE - } - ) - } + podInfoBinding.podExpiryDate.text = expiresAt?.let { + readableZonedTime(it) } + ?: PLACEHOLDER + podInfoBinding.podExpiryDate.setTextColor( + if (expiresAt != null && DateTime.now().isAfter(expiresAt)) + Color.RED + else + Color.WHITE + ) podStateManager.alarmType?.let { errors.add( From 9a009d2f961fa864517902fb96eadfb89bc046ae Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 19:24:52 +0200 Subject: [PATCH 10/29] throw exception when connection fails --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 1 - .../pump/omnipod/dash/driver/comm/session/Connection.kt | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 056c39813f..bbeecce4cf 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -203,7 +203,6 @@ class OmnipodDashPumpPlugin @Inject constructor( start = true, name = "ConnectionThread", ) { - // TODO quadruple check that we are not creating a party of Threads here try { val stop = CountDownLatch(1) stopConnecting = stop diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index 4b4ca44f00..889abc1278 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -127,6 +127,7 @@ class Connection( } private fun waitForConnection(connectionWaitCond: ConnectionWaitCondition): ConnectionState { + aapsLogger.debug(LTag.PUMPBTCOMM, "waitForConnection connectionWaitCond=$connectionWaitCond") try { connectionWaitCond.timeoutMs?.let { bleCommCallbacks.waitForConnection(it) @@ -134,7 +135,7 @@ class Connection( connectionWaitCond.stopConnection?.let { while (!bleCommCallbacks.waitForConnection(STOP_CONNECTING_CHECK_INTERVAL_MS)) { if (it.count == 0L) { - ConnectException("stopConnecting called") + throw ConnectException("stopConnecting called") } } } From f289cd50c5d7176b6821681e781bba03071488a8 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 20:11:46 +0200 Subject: [PATCH 11/29] ktlint. update ktlint gradle plugin --- build.gradle | 2 +- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 24 +++++--- .../dash/driver/comm/OmnipodDashBleManager.kt | 2 +- .../driver/comm/OmnipodDashBleManagerImpl.kt | 58 +++++++++---------- .../dash/driver/comm/session/Connection.kt | 9 ++- .../driver/comm/session/EapAkaAttribute.kt | 1 - .../dash/driver/comm/session/Session.kt | 7 +-- .../pod/state/OmnipodDashPodStateManager.kt | 3 - .../state/OmnipodDashPodStateManagerImpl.kt | 43 +++++++------- .../dash/ui/OmnipodDashOverviewFragment.kt | 6 +- 10 files changed, 78 insertions(+), 77 deletions(-) diff --git a/build.gradle b/build.gradle index cf4d289cfa..83722e0290 100644 --- a/build.gradle +++ b/build.gradle @@ -63,7 +63,7 @@ buildscript { plugins { id "io.gitlab.arturbosch.detekt" version "1.16.0-RC2" - id "org.jlleitschuh.gradle.ktlint" version "9.4.1" + id "org.jlleitschuh.gradle.ktlint" version "10.1.0" } allprojects { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index bbeecce4cf..98759597c1 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -53,7 +53,6 @@ import javax.inject.Inject import javax.inject.Singleton import kotlin.concurrent.thread import kotlin.math.ceil -import kotlin.math.exp import kotlin.random.Random @Singleton @@ -75,7 +74,7 @@ class OmnipodDashPumpPlugin @Inject constructor( @Volatile var bolusCanceled = false private val handler: Handler = Handler(Looper.getMainLooper()) private lateinit var statusChecker: Runnable - var nextPodWarningCheck : Long = 0 + var nextPodWarningCheck: Long = 0 @Volatile var stopConnecting: CountDownLatch? = null companion object { @@ -99,7 +98,7 @@ class OmnipodDashPumpPlugin @Inject constructor( statusChecker = Runnable { refreshStatusOnUnacknowledgedCommands() updatePodWarnings() - // createFakeTBRWhenNoActivePod() + // createFakeTBRWhenNoActivePod() // TODO: this is called from the main thread handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS) } @@ -109,7 +108,7 @@ class OmnipodDashPumpPlugin @Inject constructor( if (!podStateManager.isPodRunning) { val expectedState = pumpSync.expectedPumpState() val tbr = expectedState.temporaryBasal - if (tbr == null || tbr.rate!=0.0) { + if (tbr == null || tbr.rate != 0.0) { aapsLogger.info(LTag.PUMP, "createFakeTBRWhenNoActivePod") pumpSync.syncTemporaryBasalWithPumpId( timestamp = System.currentTimeMillis(), @@ -147,7 +146,17 @@ class OmnipodDashPumpPlugin @Inject constructor( rxBus.send(EventNewNotification(notification)) } else { rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) - // TODO: time out of sync notification? + if (!TimeZone.getDefault().equals(podStateManager.timeZone)) { + val notification = + Notification( + Notification.OMNIPOD_TIME_OUT_OF_SYNC, + "Timezone on pod is different from the timezone on phone. " + + "Basal rate is incorrect" + + "Switch profile to fix", + Notification.NORMAL + ) + rxBus.send(EventNewNotification(notification)) + } } } nextPodWarningCheck = DateTimeUtil.getTimeInFutureFromMinutes(15) @@ -158,7 +167,8 @@ class OmnipodDashPumpPlugin @Inject constructor( if (podStateManager.isPodRunning && podStateManager.activeCommand != null && commandQueue.size() == 0 && - commandQueue.performing() == null) { + commandQueue.performing() == null + ) { commandQueue.readStatus("Unconfirmed command", null) } } @@ -180,7 +190,7 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun isConnected(): Boolean { return !podStateManager.isPodRunning || - podStateManager.bluetoothConnectionState == OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED + podStateManager.bluetoothConnectionState == OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED } override fun isConnecting(): Boolean { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt index 135fdf295f..d0aa9013f2 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt @@ -16,7 +16,7 @@ interface OmnipodDashBleManager { fun getStatus(): ConnectionState // used for sync connections - fun connect(timeoutMs: Long = Connection.BASE_CONNECT_TIMEOUT_MS*3): Observable + fun connect(timeoutMs: Long = Connection.BASE_CONNECT_TIMEOUT_MS * 3): Observable // used for async connections fun connect(stopConnectionLatch: CountDownLatch): Observable diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt index 1c873bd8ab..4a13d50585 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt @@ -114,40 +114,40 @@ class OmnipodDashBleManagerImpl @Inject constructor( private fun connect(connectionWaitCond: ConnectionWaitCondition): Observable = Observable .create { emitter -> - if (!busy.compareAndSet(false, true)) { - throw BusyException() - } - try { - emitter.onNext(PodEvent.BluetoothConnecting) - - val podAddress = - podState.bluetoothAddress - ?: throw FailedToConnectException("Missing bluetoothAddress, activate the pod first") - val podDevice = bluetoothAdapter.getRemoteDevice(podAddress) - val conn = connection - ?: Connection(podDevice, aapsLogger, context, podState) - connection = conn - if (conn.connectionState() is Connected && conn.session != null) { - emitter.onNext(PodEvent.AlreadyConnected(podAddress)) - emitter.onComplete() - return@create + if (!busy.compareAndSet(false, true)) { + throw BusyException() } + try { + emitter.onNext(PodEvent.BluetoothConnecting) - conn.connect(connectionWaitCond) + val podAddress = + podState.bluetoothAddress + ?: throw FailedToConnectException("Missing bluetoothAddress, activate the pod first") + val podDevice = bluetoothAdapter.getRemoteDevice(podAddress) + val conn = connection + ?: Connection(podDevice, aapsLogger, context, podState) + connection = conn + if (conn.connectionState() is Connected && conn.session != null) { + emitter.onNext(PodEvent.AlreadyConnected(podAddress)) + emitter.onComplete() + return@create + } - emitter.onNext(PodEvent.BluetoothConnected(podAddress)) - emitter.onNext(PodEvent.EstablishingSession) - establishSession(1.toByte()) - emitter.onNext(PodEvent.Connected) + conn.connect(connectionWaitCond) - emitter.onComplete() - } catch (ex: Exception) { - disconnect() - emitter.tryOnError(ex) - } finally { - busy.set(false) + emitter.onNext(PodEvent.BluetoothConnected(podAddress)) + emitter.onNext(PodEvent.EstablishingSession) + establishSession(1.toByte()) + emitter.onNext(PodEvent.Connected) + + emitter.onComplete() + } catch (ex: Exception) { + disconnect() + emitter.tryOnError(ex) + } finally { + busy.set(false) + } } - } private fun establishSession(msgSeq: Byte) { val conn = assertConnected() diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index 889abc1278..ea219b7b80 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -24,15 +24,14 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message. import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import java.lang.IllegalArgumentException import java.util.concurrent.CountDownLatch -import kotlin.math.absoluteValue sealed class ConnectionState -object Connecting: ConnectionState() +object Connecting : ConnectionState() object Connected : ConnectionState() object NotConnected : ConnectionState() -data class ConnectionWaitCondition(var timeoutMs: Long?=null, val stopConnection: CountDownLatch?=null) { +data class ConnectionWaitCondition(var timeoutMs: Long? = null, val stopConnection: CountDownLatch? = null) { init { if (timeoutMs == null && stopConnection == null) { throw IllegalArgumentException("One of timeoutMs or stopConnection has to be non null") @@ -68,8 +67,8 @@ class Connection( podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING val autoConnect = false - val gatt = gattConnection ?: - podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) + val gatt = gattConnection + ?: podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) gattConnection = gatt if (!gatt.connect()) { throw FailedToConnectException("connect() returned false") diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapAkaAttribute.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapAkaAttribute.kt index 94379b181c..b81d5c1216 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapAkaAttribute.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapAkaAttribute.kt @@ -1,7 +1,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session import info.nightscout.androidaps.extensions.toHex -import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.MessageIOException import java.util.* diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt index 87fccc725e..4c4531689a 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Session.kt @@ -11,7 +11,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message. import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response -import kotlin.reflect.KClass sealed class CommandSendResult object CommandSendSuccess : CommandSendResult() @@ -113,10 +112,10 @@ class Session( // TODO verify length - //val uniqueId = data.copyOfRange(0, 4) - //val lenghtAndSequenceNumber = data.copyOfRange(4, 6) + // val uniqueId = data.copyOfRange(0, 4) + // val lenghtAndSequenceNumber = data.copyOfRange(4, 6) val payload = data.copyOfRange(6, data.size - 2) - //val crc = data.copyOfRange(data.size - 2, data.size) + // val crc = data.copyOfRange(data.size - 2, data.size) // TODO validate uniqueId, sequenceNumber and crc diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index ebf81c8de9..a440ca9bb8 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair.PairResult -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse @@ -11,10 +10,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response. import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.VersionResponse import io.reactivex.Completable import io.reactivex.Maybe -import io.reactivex.Observable import io.reactivex.Single import org.joda.time.DateTime -import org.joda.time.DateTimeZone import org.joda.time.Duration import java.io.Serializable import java.util.* diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 2656a6149c..d89e290581 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -11,7 +11,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.R import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair.PairResult import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.EapSqn -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse @@ -20,10 +19,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response. import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.Completable import io.reactivex.Maybe -import io.reactivex.Observable import io.reactivex.Single import org.joda.time.DateTime -import org.joda.time.DateTimeZone import org.joda.time.Duration import java.io.Serializable import java.util.* @@ -283,29 +280,29 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( requestedBolus: Double? ): Single { - return Single.create { source -> - if (activeCommand == null) { - val command = OmnipodDashPodStateManager.ActiveCommand( - podState.messageSequenceNumber, - createdRealtime = SystemClock.elapsedRealtime(), - historyId = historyId, - sendError = null, - basalProgram = basalProgram, - tempBasal = tempBasal, - requestedBolus = requestedBolus + return Single.create { source -> + if (activeCommand == null) { + val command = OmnipodDashPodStateManager.ActiveCommand( + podState.messageSequenceNumber, + createdRealtime = SystemClock.elapsedRealtime(), + historyId = historyId, + sendError = null, + basalProgram = basalProgram, + tempBasal = tempBasal, + requestedBolus = requestedBolus + ) + podState.activeCommand = command + source.onSuccess(command) + } else { + source.onError( + java.lang.IllegalStateException( + "Trying to send a command " + + "and the last command was not confirmed" ) - podState.activeCommand = command - source.onSuccess(command) - } else { - source.onError( - java.lang.IllegalStateException( - "Trying to send a command " + - "and the last command was not confirmed" - ) - ) - } + ) } } + } @Synchronized override fun observeNoActiveCommand(): Completable { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index e2644da1b9..59963a1dc0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -1,7 +1,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui import android.content.Intent -import android.content.res.ColorStateList import android.graphics.Color import android.os.Bundle import android.os.Handler @@ -286,12 +285,13 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // Update Pod expiry time val expiresAt = podStateManager.expiry podInfoBinding.podExpiryDate.text = expiresAt?.let { - readableZonedTime(it) } + readableZonedTime(it) + } ?: PLACEHOLDER podInfoBinding.podExpiryDate.setTextColor( if (expiresAt != null && DateTime.now().isAfter(expiresAt)) Color.RED - else + else Color.WHITE ) From d1f99bfb7101ffcf41e370248d0fb0a1865c4337 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 21:19:57 +0200 Subject: [PATCH 12/29] remove Joda --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 12 +-- .../driver/pod/definition/PodConstants.kt | 4 +- .../pod/state/OmnipodDashPodStateManager.kt | 10 +-- .../state/OmnipodDashPodStateManagerImpl.kt | 26 ++++-- .../dash/ui/OmnipodDashOverviewFragment.kt | 88 ++++++------------- 5 files changed, 60 insertions(+), 80 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 98759597c1..70fed1a899 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -113,7 +113,7 @@ class OmnipodDashPumpPlugin @Inject constructor( pumpSync.syncTemporaryBasalWithPumpId( timestamp = System.currentTimeMillis(), rate = 0.0, - duration = T.mins(PodConstants.MAX_POD_LIFETIME.standardMinutes).msecs(), + duration = T.mins(PodConstants.MAX_POD_LIFETIME.toMinutes()).msecs(), isAbsolute = true, type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, pumpId = Random.Default.nextLong(), // we don't use this, just make sure it's unique @@ -146,7 +146,7 @@ class OmnipodDashPumpPlugin @Inject constructor( rxBus.send(EventNewNotification(notification)) } else { rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) - if (!TimeZone.getDefault().equals(podStateManager.timeZone)) { + if (!podStateManager.sameTimeZone) { val notification = Notification( Notification.OMNIPOD_TIME_OUT_OF_SYNC, @@ -277,7 +277,7 @@ class OmnipodDashPumpPlugin @Inject constructor( pumpSync.syncTemporaryBasalWithPumpId( timestamp = System.currentTimeMillis(), rate = 0.0, - duration = T.mins(PodConstants.MAX_POD_LIFETIME.standardMinutes).msecs(), + duration = T.mins(PodConstants.MAX_POD_LIFETIME.toMinutes()).msecs(), isAbsolute = true, type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, pumpId = Random.Default.nextLong(), // we don't use this, just make sure it's unique @@ -371,7 +371,7 @@ class OmnipodDashPumpPlugin @Inject constructor( .map { pumpSyncTempBasal( 0.0, - PodConstants.MAX_POD_LIFETIME.standardMinutes, + PodConstants.MAX_POD_LIFETIME.toMinutes(), PumpSync.TemporaryBasalType.PUMP_SUSPEND ) rxBus.send(EventTempBasalChange()) @@ -961,7 +961,7 @@ class OmnipodDashPumpPlugin @Inject constructor( .map { pumpSyncTempBasal( 0.0, - PodConstants.MAX_POD_LIFETIME.standardMinutes, + PodConstants.MAX_POD_LIFETIME.toMinutes(), PumpSync.TemporaryBasalType.PUMP_SUSPEND ) } @@ -1116,6 +1116,7 @@ class OmnipodDashPumpPlugin @Inject constructor( rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) } rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) + rxBus.send(EventDismissNotification(Notification.OMNIPOD_TIME_OUT_OF_SYNC)) } OmnipodCommandType.SET_BASAL_PROFILE -> { @@ -1137,6 +1138,7 @@ class OmnipodDashPumpPlugin @Inject constructor( rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) rxBus.send(EventDismissNotification(Notification.FAILED_UPDATE_PROFILE)) rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) + rxBus.send(EventDismissNotification(Notification.OMNIPOD_TIME_OUT_OF_SYNC)) } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/PodConstants.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/PodConstants.kt index f52cc8fb5f..ae648dd656 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/PodConstants.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/PodConstants.kt @@ -1,9 +1,9 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition -import org.joda.time.Duration +import java.time.Duration class PodConstants { companion object { - val MAX_POD_LIFETIME = Duration.standardHours(80) + val MAX_POD_LIFETIME = Duration.ofMinutes(80) } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index a440ca9bb8..b8a561a8c0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -11,9 +11,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response. import io.reactivex.Completable import io.reactivex.Maybe import io.reactivex.Single -import org.joda.time.DateTime -import org.joda.time.Duration import java.io.Serializable +import java.time.ZonedDateTime import java.util.* sealed class CommandConfirmationFromState @@ -34,11 +33,12 @@ interface OmnipodDashPodStateManager { var bluetoothConnectionState: BluetoothConnectionState var timeZone: TimeZone + val sameTimeZone: Boolean // The TimeZone is the same on the phone and on the pod val lastUpdatedSystem: Long // System.currentTimeMillis() val lastStatusResponseReceived: Long - val time: DateTime? - val timeDrift: Duration? - val expiry: DateTime? + val time: ZonedDateTime? + val timeDrift: java.time.Duration? + val expiry: ZonedDateTime? val messageSequenceNumber: Short val sequenceNumberOfLastProgrammingCommand: Short? diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index d89e290581..5e9848d814 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -20,9 +20,10 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.Completable import io.reactivex.Maybe import io.reactivex.Single -import org.joda.time.DateTime -import org.joda.time.Duration import java.io.Serializable +import java.time.Duration +import java.time.Instant +import java.time.ZonedDateTime import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -104,6 +105,12 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( store() } + override val sameTimeZone: Boolean + get() { + val now = System.currentTimeMillis() + return TimeZone.getDefault().getOffset(now) == timeZone.getOffset(now) + } + override val bluetoothVersion: SoftwareVersion? get() = podState.bleVersion @@ -180,30 +187,31 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( override val lastStatusResponseReceived: Long get() = podState.lastStatusResponseReceived - override val time: DateTime? + override val time: ZonedDateTime? get() { val minutesSinceActivation = podState.minutesSinceActivation val activationTime = podState.activationTime if ((activationTime != null) && (minutesSinceActivation != null)) { - return DateTime(activationTime) - .plusMinutes(minutesSinceActivation.toInt()) - .plus(Duration(podState.lastUpdatedSystem, System.currentTimeMillis())) + return ZonedDateTime.from(Instant.ofEpochMilli(activationTime)) + .plusMinutes(minutesSinceActivation.toLong()) + .plus(Duration.ofMillis(System.currentTimeMillis() - lastUpdatedSystem)) } return null } override val timeDrift: Duration? get() { - return Duration(DateTime.now(), time) + return Duration.between(ZonedDateTime.now(), time) } - override val expiry: DateTime? + override val expiry: ZonedDateTime? // TODO: Consider storing expiry datetime in pod state saving continuously recalculating to the same value get() { val podLifeInHours = podLifeInHours val activationTime = podState.activationTime if (podLifeInHours != null && activationTime != null) { - return DateTime(podState.activationTime).plusHours(podLifeInHours.toInt()) + return return ZonedDateTime.from(Instant.ofEpochMilli(activationTime)) + .plusHours(podLifeInHours.toLong()) } return null } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 59963a1dc0..a834835865 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -44,8 +44,8 @@ import info.nightscout.androidaps.utils.ui.UIRunnable import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import org.apache.commons.lang3.StringUtils -import org.joda.time.DateTime -import org.joda.time.Duration +import java.time.Duration +import java.time.ZonedDateTime import java.util.* import javax.inject.Inject import kotlin.collections.ArrayList @@ -269,27 +269,34 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // Update time on Pod podInfoBinding.timeOnPod.text = podStateManager.time?.let { - readableZonedTime(it) + resourceHelper.gs( + R.string.omnipod_common_time_with_timezone, + dateUtil.dateAndTimeString(it.toEpochSecond()), + podStateManager.timeZone.getDisplayName(true, TimeZone.SHORT) + ) } ?: PLACEHOLDER podInfoBinding.timeOnPod.setTextColor( - podStateManager.timeDrift?.let { - if (it.abs().isLongerThan(Duration.standardMinutes(MAX_TIME_DEVIATION_MINUTES))) { - Color.RED - } else { + when { + !podStateManager.sameTimeZone -> + Color.MAGENTA + podStateManager.timeDrift?.abs()?.minus( + Duration.ofMinutes(MAX_TIME_DEVIATION_MINUTES) + )?.isNegative ?: false -> + Color.YELLOW + else -> Color.WHITE - } - } ?: Color.WHITE + } ) // Update Pod expiry time val expiresAt = podStateManager.expiry podInfoBinding.podExpiryDate.text = expiresAt?.let { - readableZonedTime(it) + dateUtil.dateAndTimeString(it.toEpochSecond()) } ?: PLACEHOLDER podInfoBinding.podExpiryDate.setTextColor( - if (expiresAt != null && DateTime.now().isAfter(expiresAt)) + if (expiresAt != null && ZonedDateTime.now().isAfter(expiresAt)) Color.RED else Color.WHITE @@ -368,14 +375,14 @@ class OmnipodDashOverviewFragment : DaggerFragment() { private fun updateLastConnection() { if (podStateManager.isUniqueIdSet) { podInfoBinding.lastConnection.text = readableDuration( - Duration( - podStateManager.lastUpdatedSystem, - System - .currentTimeMillis() + Duration.ofMillis( + System.currentTimeMillis() - + podStateManager.lastUpdatedSystem, + ) ) val lastConnectionColor = - if (omnipodDashPumpPlugin.isUnreachableAlertTimeoutExceeded(getPumpUnreachableTimeout().millis)) { + if (omnipodDashPumpPlugin.isUnreachableAlertTimeoutExceeded(getPumpUnreachableTimeout().toMillis())) { Color.RED } else { Color.WHITE @@ -441,7 +448,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { R.string.omnipod_common_overview_last_bolus_value, omnipodDashPumpPlugin.model().determineCorrectBolusSize(requestedBolus), resourceHelper.gs(R.string.insulin_unit_shortname), - readableDuration(Duration(it.createdRealtime, SystemClock.elapsedRealtime())) + readableDuration(Duration.ofMillis(SystemClock.elapsedRealtime() - it.createdRealtime)) ) text += " (uncertain) " textColor = Color.RED @@ -461,7 +468,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { R.string.omnipod_common_overview_last_bolus_value, omnipodDashPumpPlugin.model().determineCorrectBolusSize(bolusSize), resourceHelper.gs(R.string.insulin_unit_shortname), - readableDuration(Duration(it.startTime, System.currentTimeMillis())) + readableDuration(Duration.ofMillis(System.currentTimeMillis() - it.startTime)) ) if (!it.deliveryComplete) { textColor = Color.YELLOW @@ -597,47 +604,10 @@ class OmnipodDashOverviewFragment : DaggerFragment() { } } - // private fun getTimeZone(): DateTimeZone { - // // return getSafe(() -> podState.getTimeZone()); - // return podStateManager.timeZone - // } - private fun getTimeZone(): TimeZone { - // Return timezone ID (e.g "Europe/Amsterdam") - return podStateManager.timeZone - } - - private fun readableZonedTime(time: DateTime): String { - val timeAsJavaData = time.toLocalDateTime().toDate() - return dateUtil.dateAndTimeString(timeAsJavaData.time) - - // // TODO: Handle timeZone ID - // val timeZone = getTimeZone() - // if (timeZone == "") { - // // No timezone defined, use local time (default) - // return dateUtil.dateAndTimeString(timeAsJavaData.time) - // } - // else { - // // Get full timezoned time - // val isDaylightTime = timeZone.inDaylightTime(timeAsJavaData) - // val locale = resources.configuration.locales.get(0) - // val timeZoneDisplayName = - // timeZone.getDisplayName(isDaylightTime, TimeZone.SHORT, locale) + " " + timeZone.getDisplayName( - // isDaylightTime, - // TimeZone.LONG, - // locale - // ) - // return resourceHelper.gs( - // R.string.omnipod_common_time_with_timezone, - // dateUtil.dateAndTimeString(timeAsJavaData.time), - // timeZoneDisplayName - // ) - // } - } - private fun readableDuration(duration: Duration): String { - val hours = duration.standardHours.toInt() - val minutes = duration.standardMinutes.toInt() - val seconds = duration.standardSeconds.toInt() + val hours = duration.toHours().toInt() + val minutes = duration.toMinutes().toInt() + val seconds = duration.seconds when { seconds < 10 -> { return resourceHelper.gs(R.string.omnipod_common_moments_ago) @@ -680,7 +650,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // FIXME ideally we should just have access to LocalAlertUtils here private fun getPumpUnreachableTimeout(): Duration { - return Duration.standardMinutes( + return Duration.ofMinutes( sp.getInt( R.string.key_pump_unreachable_threshold_minutes, Constants.DEFAULT_PUMP_UNREACHABLE_THRESHOLD_MINUTES From 465ae7ee8a8640956f3a60e0d8563becbda25f73 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 21:35:40 +0200 Subject: [PATCH 13/29] remove joda --- .../pod/state/OmnipodDashPodStateManagerImpl.kt | 11 +++++++---- .../omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 5e9848d814..2cb57bcf15 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -23,6 +23,7 @@ import io.reactivex.Single import java.io.Serializable import java.time.Duration import java.time.Instant +import java.time.LocalDateTime import java.time.ZonedDateTime import java.util.* import javax.inject.Inject @@ -192,7 +193,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( val minutesSinceActivation = podState.minutesSinceActivation val activationTime = podState.activationTime if ((activationTime != null) && (minutesSinceActivation != null)) { - return ZonedDateTime.from(Instant.ofEpochMilli(activationTime)) + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(activationTime), timeZone.toZoneId()) .plusMinutes(minutesSinceActivation.toLong()) .plus(Duration.ofMillis(System.currentTimeMillis() - lastUpdatedSystem)) } @@ -208,10 +209,12 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( // TODO: Consider storing expiry datetime in pod state saving continuously recalculating to the same value get() { val podLifeInHours = podLifeInHours - val activationTime = podState.activationTime - if (podLifeInHours != null && activationTime != null) { - return return ZonedDateTime.from(Instant.ofEpochMilli(activationTime)) + val minutesSinceActivation = podState.minutesSinceActivation + if (podLifeInHours != null && minutesSinceActivation != null) { + return ZonedDateTime.now() .plusHours(podLifeInHours.toLong()) + .minusMinutes(minutesSinceActivation.toLong()) + .plus(Duration.ofMillis(System.currentTimeMillis() - lastUpdatedSystem)) } return null } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index a834835865..a7a3f7a302 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -271,7 +271,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { podInfoBinding.timeOnPod.text = podStateManager.time?.let { resourceHelper.gs( R.string.omnipod_common_time_with_timezone, - dateUtil.dateAndTimeString(it.toEpochSecond()), + dateUtil.dateAndTimeString(it.toEpochSecond()*1000), podStateManager.timeZone.getDisplayName(true, TimeZone.SHORT) ) } ?: PLACEHOLDER @@ -292,7 +292,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // Update Pod expiry time val expiresAt = podStateManager.expiry podInfoBinding.podExpiryDate.text = expiresAt?.let { - dateUtil.dateAndTimeString(it.toEpochSecond()) + dateUtil.dateAndTimeString(it.toEpochSecond()*1000) } ?: PLACEHOLDER podInfoBinding.podExpiryDate.setTextColor( From 80b47f57c40e15977a3f3f42e5306d43b03d0ce1 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 11 Jul 2021 21:44:15 +0200 Subject: [PATCH 14/29] fix time display --- .../pod/state/OmnipodDashPodStateManagerImpl.kt | 1 - .../omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 13 ++++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 2cb57bcf15..dc582bce16 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -23,7 +23,6 @@ import io.reactivex.Single import java.io.Serializable import java.time.Duration import java.time.Instant -import java.time.LocalDateTime import java.time.ZonedDateTime import java.util.* import javax.inject.Inject diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index a7a3f7a302..ea37bf5aeb 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -271,18 +271,21 @@ class OmnipodDashOverviewFragment : DaggerFragment() { podInfoBinding.timeOnPod.text = podStateManager.time?.let { resourceHelper.gs( R.string.omnipod_common_time_with_timezone, - dateUtil.dateAndTimeString(it.toEpochSecond()*1000), + dateUtil.dateAndTimeString(it.toEpochSecond() * 1000), podStateManager.timeZone.getDisplayName(true, TimeZone.SHORT) ) } ?: PLACEHOLDER + val timeDeviationTooBig = podStateManager.timeDrift?.let { + Duration.ofMinutes(MAX_TIME_DEVIATION_MINUTES).minus( + it.abs() + ).isNegative + } ?: false podInfoBinding.timeOnPod.setTextColor( when { !podStateManager.sameTimeZone -> Color.MAGENTA - podStateManager.timeDrift?.abs()?.minus( - Duration.ofMinutes(MAX_TIME_DEVIATION_MINUTES) - )?.isNegative ?: false -> + timeDeviationTooBig -> Color.YELLOW else -> Color.WHITE @@ -292,7 +295,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // Update Pod expiry time val expiresAt = podStateManager.expiry podInfoBinding.podExpiryDate.text = expiresAt?.let { - dateUtil.dateAndTimeString(it.toEpochSecond()*1000) + dateUtil.dateAndTimeString(it.toEpochSecond() * 1000) } ?: PLACEHOLDER podInfoBinding.podExpiryDate.setTextColor( From bf81db0f6eed63ce1e83dde8ce685672ae5403ab Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Tue, 13 Jul 2021 21:01:36 +0200 Subject: [PATCH 15/29] read message if it's waiting. stop discovery if connection is lost --- .../pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt | 7 +++++-- .../plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt | 10 ++++++++-- .../pump/omnipod/dash/driver/comm/io/CmdBleIO.kt | 2 ++ .../pump/omnipod/dash/driver/comm/message/MessageIO.kt | 9 +++++++-- .../omnipod/dash/driver/comm/session/Connection.kt | 2 +- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt index 3bc367d47c..c3c38e0030 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -7,6 +7,8 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ConnectException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.CharacteristicType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.Connected +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.Connection import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.Connection.Companion.STOP_CONNECTING_CHECK_INTERVAL_MS import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.ConnectionWaitCondition import java.math.BigInteger @@ -15,7 +17,8 @@ import java.util.* class ServiceDiscoverer( private val logger: AAPSLogger, private val gatt: BluetoothGatt, - private val bleCallbacks: BleCommCallbacks + private val bleCallbacks: BleCommCallbacks, + private val connection: Connection ) { /*** @@ -33,7 +36,7 @@ class ServiceDiscoverer( } connectionWaitCond.stopConnection?.let { while (!bleCallbacks.waitForServiceDiscovery(STOP_CONNECTING_CHECK_INTERVAL_MS)) { - if (it.count == 0L) { + if (it.count == 0L || connection.connectionState() !is Connected) { throw ConnectException("stopConnecting called") } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt index dbe1c24b88..a91d645339 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt @@ -11,6 +11,7 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.WriteConfirmationError import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.WriteConfirmationSuccess +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommandRTS import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.* import java.util.concurrent.BlockingQueue import java.util.concurrent.TimeUnit @@ -84,12 +85,17 @@ open class BleIO( * Called before sending a new message. * The incoming queues should be empty, so we log when they are not. */ - fun flushIncomingQueue() { + open fun flushIncomingQueue(): Boolean { + var foundRTS = false do { val found = incomingPackets.poll()?.also { - aapsLogger.warn(LTag.PUMPBTCOMM, "BleIO: queue not empty, flushing: {${it.toHex()}") + aapsLogger.warn(LTag.PUMPBTCOMM, "BleIO: queue not empty, flushing: ${it.toHex()}") + if (it.isNotEmpty() && it[0] == BleCommandRTS.data[0]) { + foundRTS = true + } } } while (found != null) + return foundRTS } /** diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt index 8421a6f1d3..d524fa6668 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt @@ -2,7 +2,9 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic +import info.nightscout.androidaps.extensions.toHex import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommand diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt index c18c2b33f1..2394ae14e2 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt @@ -35,7 +35,12 @@ class MessageIO( @Suppress("ReturnCount") fun sendMessage(msg: MessagePacket): MessageSendResult { - cmdBleIO.flushIncomingQueue() + val foundRTS = cmdBleIO.flushIncomingQueue() + if (foundRTS) { + val msg = receiveMessage() + aapsLogger.warn(LTag.PUMPBTCOMM, "sendMessage received message=$msg") + throw IllegalStateException("Received message while trying to send") + } dataBleIO.flushIncomingQueue() val rtsSendResult = cmdBleIO.sendAndConfirmPacket(BleCommandRTS.data) @@ -219,6 +224,6 @@ class MessageIO( companion object { private const val MAX_PACKET_READ_TRIES = 4 - private const val MESSAGE_READ_TIMEOUT_MS = 2500.toLong() + private const val MESSAGE_READ_TIMEOUT_MS = 5000.toLong() } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index ea219b7b80..358e093cfb 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -89,7 +89,7 @@ class Connection( } podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED - val discoverer = ServiceDiscoverer(aapsLogger, gatt, bleCommCallbacks) + val discoverer = ServiceDiscoverer(aapsLogger, gatt, bleCommCallbacks, this) val discovered = discoverer.discoverServices(connectionWaitCond) val cmdBleIO = CmdBleIO( aapsLogger, From 21b78562e2f82a71092f659f4aa16823687648bb Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Tue, 13 Jul 2021 21:27:37 +0200 Subject: [PATCH 16/29] fix command recovery on start --- .../dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index dc582bce16..7f52c4a760 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -436,7 +436,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( override fun onStart() { when (getCommandConfirmationFromState()) { CommandConfirmationSuccess, CommandConfirmationDenied -> { - val now = System.currentTimeMillis() + val now = SystemClock.elapsedRealtime() val newCommand = podState.activeCommand?.copy( createdRealtime = now, sentRealtime = now + 1 @@ -446,7 +446,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } CommandSendingNotConfirmed -> { - val now = System.currentTimeMillis() + val now = SystemClock.elapsedRealtime() val newCommand = podState.activeCommand?.copy( createdRealtime = now, sentRealtime = now + 1 From b845c06fca67c5f6cf6326be1624b851c8857571 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 16 Jul 2021 21:34:38 +0200 Subject: [PATCH 17/29] update alerts --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 90 +++++++++++++++++-- .../omnipod/dash/driver/OmnipodDashManager.kt | 2 +- .../dash/driver/OmnipodDashManagerImpl.kt | 89 +++++++++++------- .../pod/definition/BeepRepetitionType.kt | 4 +- .../pod/state/OmnipodDashPodStateManager.kt | 3 + .../state/OmnipodDashPodStateManagerImpl.kt | 32 ++++++- .../action/DashInitializePodViewModel.kt | 17 +++- .../action/DashInsertCannulaViewModel.kt | 14 ++- .../main/res/xml/omnipod_dash_preferences.xml | 1 - 9 files changed, 206 insertions(+), 46 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 70fed1a899..13461b794f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -7,6 +7,7 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.activities.ErrorHelperActivity.Companion.runAlarm import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult +import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventProfileSwitchChanged import info.nightscout.androidaps.events.EventTempBasalChange import info.nightscout.androidaps.interfaces.* @@ -25,10 +26,7 @@ import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ActivationProgress -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodConstants +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.CommandConfirmed import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager @@ -40,13 +38,19 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.OmnipodDashOvervi import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram import info.nightscout.androidaps.queue.commands.Command import info.nightscout.androidaps.queue.commands.CustomCommand +import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.TimeChangeType import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.Completable import io.reactivex.Single +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import org.json.JSONObject +import java.time.Duration +import java.time.ZonedDateTime import java.util.* import java.util.concurrent.CountDownLatch import javax.inject.Inject @@ -65,6 +69,8 @@ class OmnipodDashPumpPlugin @Inject constructor( private val pumpSync: PumpSync, private val rxBus: RxBusWrapper, private val context: Context, + private val aapsSchedulers: AapsSchedulers, + private val fabricPrivacy: FabricPrivacy, injector: HasAndroidInjector, aapsLogger: AAPSLogger, @@ -76,6 +82,7 @@ class OmnipodDashPumpPlugin @Inject constructor( private lateinit var statusChecker: Runnable var nextPodWarningCheck: Long = 0 @Volatile var stopConnecting: CountDownLatch? = null + private var disposables: CompositeDisposable = CompositeDisposable() companion object { private const val BOLUS_RETRY_INTERVAL_MS = 2000.toLong() @@ -391,10 +398,25 @@ class OmnipodDashPumpPlugin @Inject constructor( super.onStart() podStateManager.onStart() handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS) + disposables += rxBus + .toObservable(EventPreferenceChange::class.java) + .observeOn(aapsSchedulers.main) + .subscribe( + { + if (it.isChanged(resourceHelper, + R.string.key_omnipod_common_expiration_reminder_enabled) || + it.isChanged(resourceHelper, + R.string.key_omnipod_common_expiration_reminder_hours_before_shutdown)) { + commandQueue.customCommand(CommandUpdateAlertConfiguration(), null) + } + }, + fabricPrivacy::logException + ) } override fun onStop() { super.onStop() + disposables.clear() handler.removeCallbacks(statusChecker) } @@ -451,7 +473,7 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { try { - aapsLogger.info(LTag.PUMP, "Delivering treatment: $detailedBolusInfo") + aapsLogger.info(LTag.PUMP, "Delivering treatment: $detailedBolusInfo $bolusCanceled") val beepsConfigurationKey = if (detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB) R.string.key_omnipod_common_smb_beeps_enabled else @@ -1020,8 +1042,62 @@ class OmnipodDashPumpPlugin @Inject constructor( } private fun updateAlertConfiguration(): PumpEnactResult { - // TODO - return PumpEnactResult(injector).success(false).enacted(false).comment("NOT IMPLEMENTED") + + val expirationReminderEnabled = sp.getBoolean(R.string.key_omnipod_common_expiration_reminder_enabled, true) + val expirationHours = sp.getInt(R.string.key_omnipod_common_expiration_reminder_hours_before_shutdown, 7) + val lowReservoirAlertEnabled = sp.getBoolean(R.string.key_omnipod_common_low_reservoir_alert_enabled, true) + val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units ,10) + + if (!podStateManager.differentAlertSettings( + expirationReminderEnabled, + expirationHours, + lowReservoirAlertEnabled, + lowReservoirAlertUnits + )) { + return PumpEnactResult(injector).success(true).enacted(false) + } + + val podLifeLeft = Duration.between(ZonedDateTime.now(), podStateManager.expiry) + val expiryAlertDelay = podLifeLeft.minus(Duration.ofHours(expirationHours.toLong())) + if (expiryAlertDelay.isNegative) { + aapsLogger.warn(LTag.PUMPBTCOMM, "updateAlertConfiguration negative " + + "expiryAlertDuration=$expiryAlertDelay") + PumpEnactResult(injector).success(false).enacted(false) + } + val alerts = listOf ( + AlertConfiguration( + AlertType.LOW_RESERVOIR, + enabled = lowReservoirAlertEnabled, + durationInMinutes = 0, + autoOff = false, + AlertTrigger.ReservoirVolumeTrigger((lowReservoirAlertUnits * 10).toShort()), + BeepType.FOUR_TIMES_BIP_BEEP, + BeepRepetitionType.XXX + ), + AlertConfiguration( + AlertType.USER_SET_EXPIRATION, + enabled = expirationReminderEnabled, + durationInMinutes = 0, + autoOff = false, + AlertTrigger.TimerTrigger( + expiryAlertDelay.toMinutes().toShort() + ), + BeepType.FOUR_TIMES_BIP_BEEP, + BeepRepetitionType.XXX2 + ) + ) + return executeProgrammingCommand( + historyEntry = history.createRecord(OmnipodCommandType.CONFIGURE_ALERTS), + command = omnipodManager.programAlerts(alerts).ignoreElements(), + post = podStateManager.updateExpirationAlertSettings( + expirationReminderEnabled, + expirationHours).andThen( + podStateManager.updateExpirationAlertSettings( + lowReservoirAlertEnabled, + lowReservoirAlertUnits + ) + ) + ).toPumpEnactResult() } private fun playTestBeep(): PumpEnactResult { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt index 24b09dfc79..f0c2c85947 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt @@ -15,7 +15,7 @@ interface OmnipodDashManager { fun activatePodPart1(lowReservoirAlertTrigger: AlertTrigger.ReservoirVolumeTrigger?): Observable - fun activatePodPart2(basalProgram: BasalProgram): Observable + fun activatePodPart2(basalProgram: BasalProgram, userConfiguredExpirationHours: Long?): Observable fun getStatus(type: ResponseType.StatusResponseType): Observable diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index e504f2a3b7..5e6ff425dd 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -8,12 +8,15 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEven 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.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.response.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.Observable import io.reactivex.functions.Action import io.reactivex.functions.Consumer +import java.time.Duration +import java.time.ZonedDateTime import java.util.* import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -340,11 +343,12 @@ class OmnipodDashManagerImpl @Inject constructor( return observables.reversed() } - override fun activatePodPart2(basalProgram: BasalProgram): Observable { + override fun activatePodPart2(basalProgram: BasalProgram, userConfiguredExpirationHours:Long?): + Observable { return Observable.concat( observePodReadyForActivationPart2, observeConnectToPod, - observeActivationPart2Commands(basalProgram) + observeActivationPart2Commands(basalProgram, userConfiguredExpirationHours) ).doOnComplete(ActivationProgressUpdater(ActivationProgress.COMPLETED)) // TODO these would be common for any observable returned in a public function in this class .doOnNext(PodEventInterceptor()) @@ -352,8 +356,9 @@ class OmnipodDashManagerImpl @Inject constructor( .subscribeOn(aapsSchedulers.io) } - private fun observeActivationPart2Commands(basalProgram: BasalProgram): Observable { - val observables = createActivationPart2Observables(basalProgram) + private fun observeActivationPart2Commands(basalProgram: BasalProgram, userConfiguredExpirationHours: Long?): + Observable { + val observables = createActivationPart2Observables(basalProgram, userConfiguredExpirationHours) return if (observables.isEmpty()) { Observable.empty() @@ -362,7 +367,9 @@ class OmnipodDashManagerImpl @Inject constructor( } } - private fun createActivationPart2Observables(basalProgram: BasalProgram): List> { + private fun createActivationPart2Observables(basalProgram: BasalProgram, + userConfiguredExpirationHours: Long?): + List> { val observables = ArrayList>() if (podStateManager.activationProgress.isBefore(ActivationProgress.CANNULA_INSERTED)) { @@ -388,33 +395,55 @@ class OmnipodDashManagerImpl @Inject constructor( ) } if (podStateManager.activationProgress.isBefore(ActivationProgress.UPDATED_EXPIRATION_ALERTS)) { + val podLifeLeft = Duration.between(ZonedDateTime.now(), podStateManager.expiry) + + + val alerts = mutableListOf( + AlertConfiguration( + AlertType.EXPIRATION, + enabled = true, + durationInMinutes = TimeUnit.HOURS.toMinutes(7).toShort(), + autoOff = false, + AlertTrigger.TimerTrigger( + TimeUnit.HOURS.toMinutes(72).toShort() + ), // FIXME use activation time + BeepType.FOUR_TIMES_BIP_BEEP, + BeepRepetitionType.XXX3 + ), + AlertConfiguration( + AlertType.EXPIRATION_IMMINENT, + enabled = true, + durationInMinutes = 0, + autoOff = false, + AlertTrigger.TimerTrigger( + TimeUnit.HOURS.toMinutes(79).toShort() + ), // FIXME use activation time + BeepType.FOUR_TIMES_BIP_BEEP, + BeepRepetitionType.XXX4 + ) + ) + val userExpiryAlertDelay = podLifeLeft.minus( + Duration.ofHours(userConfiguredExpirationHours ?: MAX_POD_LIFETIME.toHours() + 1)) + if (userExpiryAlertDelay.isNegative) { + logger.warn(LTag.PUMPBTCOMM, "createActivationPart2Observables negative " + + "expiryAlertDuration=$userExpiryAlertDelay") + } else { + alerts.add( AlertConfiguration( + AlertType.USER_SET_EXPIRATION, + enabled = true, + durationInMinutes = 0, + autoOff = false, + AlertTrigger.TimerTrigger( + userExpiryAlertDelay.toMinutes().toShort() + ), + BeepType.FOUR_TIMES_BIP_BEEP, + BeepRepetitionType.XXX2 + )) + } + observables.add( observeSendProgramAlertsCommand( - listOf( - // FIXME use user configured expiration alert - AlertConfiguration( - AlertType.EXPIRATION, - enabled = true, - durationInMinutes = TimeUnit.HOURS.toMinutes(7).toShort(), - autoOff = false, - AlertTrigger.TimerTrigger( - TimeUnit.HOURS.toMinutes(73).toShort() - ), // FIXME use activation time - BeepType.FOUR_TIMES_BIP_BEEP, - BeepRepetitionType.XXX3 - ), - AlertConfiguration( - AlertType.EXPIRATION_IMMINENT, - enabled = true, - durationInMinutes = TimeUnit.HOURS.toMinutes(1).toShort(), - autoOff = false, - AlertTrigger.TimerTrigger( - TimeUnit.HOURS.toMinutes(79).toShort() - ), // FIXME use activation time - BeepType.FOUR_TIMES_BIP_BEEP, - BeepRepetitionType.XXX4 - ) - ), + alerts, multiCommandFlag = true ).doOnComplete(ActivationProgressUpdater(ActivationProgress.UPDATED_EXPIRATION_ALERTS)) ) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt index 0668852456..d799b395e2 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt @@ -5,8 +5,8 @@ enum class BeepRepetitionType( val value: Byte ) { - XXX(0x01.toByte()), // Used in lump of coal alert - XXX2(0x03.toByte()), // Used in low reservoir alert + XXX(0x01.toByte()), // Used in lump of coal alert, LOW_RESERVOIR + XXX2(0x03.toByte()), // Used in USER_SET_EXPIRATION XXX3(0x05.toByte()), // Used in user pod expiration alert XXX4(0x06.toByte()), // Used in pod expiration alert XXX5(0x08.toByte()); // Used in imminent pod expiration alert diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index b8a561a8c0..cada0148c8 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -101,6 +101,9 @@ interface OmnipodDashPodStateManager { - after getPodStatus was successful(we have an up-to-date podStatus) */ fun recoverActivationFromPodStatus(): String? + fun differentAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int, lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Boolean + fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int) : Completable + fun updateLowReservoirAlertSettings(lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Completable data class ActiveCommand( val sequence: Short, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 7f52c4a760..0d57d2e976 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -205,7 +205,6 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } override val expiry: ZonedDateTime? - // TODO: Consider storing expiry datetime in pod state saving continuously recalculating to the same value get() { val podLifeInHours = podLifeInHours val minutesSinceActivation = podState.minutesSinceActivation @@ -398,6 +397,32 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } } + override fun differentAlertSettings( + expirationReminderEnabled: Boolean, + expirationHours: Int, + lowReservoirAlertEnabled: Boolean, + lowReservoirAlertUnits: Int + ): Boolean { + return podState.expirationReminderEnabled == expirationReminderEnabled && + podState.expirationHours == expirationHours && + podState.lowReservoirAlertEnabled == lowReservoirAlertEnabled && + podState.lowReservoirAlertUnits == lowReservoirAlertUnits + } + + override fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int) : + Completable = Completable.defer{ + podState.expirationReminderEnabled = expirationReminderEnabled + podState.expirationHours = expirationHours + Completable.complete() + } + + override fun updateLowReservoirAlertSettings(lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): + Completable = Completable.defer { + podState.lowReservoirAlertEnabled = lowReservoirAlertEnabled + podState.lowReservoirAlertUnits = lowReservoirAlertUnits + Completable.complete() + } + @Synchronized override fun getCommandConfirmationFromState(): CommandConfirmationFromState { return podState.activeCommand?.run { @@ -618,6 +643,11 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( var firstPrimeBolusVolume: Short? = null var secondPrimeBolusVolume: Short? = null + var expirationReminderEnabled: Boolean? = null + var expirationHours: Int? = null + var lowReservoirAlertEnabled: Boolean? = null + var lowReservoirAlertUnits: Int? = null + var pulsesDelivered: Short? = null var pulsesRemaining: Short? = null var podStatus: PodStatus? = null diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt index 1a410acd49..b39a2213be 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt @@ -9,6 +9,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activati import info.nightscout.androidaps.plugins.pump.omnipod.dash.R import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager +import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.Single import io.reactivex.rxkotlin.subscribeBy import javax.inject.Inject @@ -16,9 +18,10 @@ import javax.inject.Inject class DashInitializePodViewModel @Inject constructor( private val omnipodManager: OmnipodDashManager, injector: HasAndroidInjector, - logger: AAPSLogger + logger: AAPSLogger, + private val sp: SP, + private val podStateManager: OmnipodDashPodStateManager, ) : InitializePodViewModel(injector, logger) { - override fun isPodInAlarm(): Boolean = false // TODO override fun isPodActivationTimeExceeded(): Boolean = false // TODO @@ -28,7 +31,14 @@ class DashInitializePodViewModel @Inject constructor( override fun doExecuteAction(): Single = Single.create { source -> // TODO use configured value for low reservoir trigger - val disposable = omnipodManager.activatePodPart1(AlertTrigger.ReservoirVolumeTrigger(200)).subscribeBy( + val lowReservoirAlertEnabled = sp.getBoolean(R.string.key_omnipod_common_low_reservoir_alert_enabled, true) + val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units ,10) + val lowReservoirAlertTrigger = if (lowReservoirAlertEnabled) { + AlertTrigger.ReservoirVolumeTrigger((lowReservoirAlertUnits * 10).toShort()) + } else + null + + val disposable = omnipodManager.activatePodPart1(lowReservoirAlertTrigger).subscribeBy( onNext = { podEvent -> logger.debug( LTag.PUMP, @@ -41,6 +51,7 @@ class DashInitializePodViewModel @Inject constructor( }, onComplete = { logger.debug("Pod activation part 1 completed") + podStateManager.updateLowReservoirAlertSettings(lowReservoirAlertEnabled, lowReservoirAlertUnits) source.onSuccess(PumpEnactResult(injector).success(true)) } ) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index 2d3883d4d4..0f66c247e9 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -15,8 +15,10 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel import info.nightscout.androidaps.plugins.pump.omnipod.dash.R import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram +import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.Single import io.reactivex.rxkotlin.subscribeBy import javax.inject.Inject @@ -27,6 +29,7 @@ class DashInsertCannulaViewModel @Inject constructor( private val pumpSync: PumpSync, private val podStateManager: OmnipodDashPodStateManager, private val rxBus: RxBusWrapper, + private val sp: SP, injector: HasAndroidInjector, logger: AAPSLogger @@ -50,7 +53,15 @@ class DashInsertCannulaViewModel @Inject constructor( profile, basalProgram ) - val disposable = omnipodManager.activatePodPart2(basalProgram).subscribeBy( + val expirationReminderEnabled = sp.getBoolean(R.string.key_omnipod_common_expiration_reminder_enabled, true) + val expirationHours = sp.getInt(R.string.key_omnipod_common_expiration_reminder_hours_before_shutdown, 9) + + val expirationHoursBeforeShutdown = if (expirationReminderEnabled) + expirationHours.toLong() + else + null + + val disposable = omnipodManager.activatePodPart2(basalProgram, expirationHoursBeforeShutdown).subscribeBy( onNext = { podEvent -> logger.debug( LTag.PUMP, @@ -82,6 +93,7 @@ class DashInsertCannulaViewModel @Inject constructor( pumpType = PumpType.OMNIPOD_DASH, pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" ) + podStateManager.updateExpirationAlertSettings(expirationReminderEnabled, expirationHours) rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED)) source.onSuccess(PumpEnactResult(injector).success(true)) } diff --git a/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml b/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml index 26d400e602..633be9fc6e 100644 --- a/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml +++ b/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml @@ -70,7 +70,6 @@ android:defaultValue="false" android:key="@string/key_omnipod_common_automatically_silence_alerts_enabled" android:title="@string/omnipod_common_preferences_automatically_silence_alerts" /> - Date: Fri, 16 Jul 2021 22:14:29 +0200 Subject: [PATCH 18/29] improve isConnecting --- .../pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 13461b794f..d90c04b8f7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -181,7 +181,6 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun isInitialized(): Boolean { - // TODO return true } @@ -201,17 +200,15 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun isConnecting(): Boolean { - // TODO - return stopConnecting != null + return stopConnecting != null && podStateManager.bluetoothConnectionState == OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING } override fun isHandshakeInProgress(): Boolean { - // TODO - return false + return stopConnecting != null } override fun finishHandshaking() { - // TODO + } override fun connect(reason: String) { @@ -337,8 +334,8 @@ class OmnipodDashPumpPlugin @Inject constructor( podStateManager.createActiveCommand(historyId, basalProgram = basalProgram) }, command = omnipodManager.setBasalProgram(basalProgram, hasBasalBeepEnabled()).ignoreElements(), - post = failWhenUnconfirmed(deliverySuspended), // mark as failed even if it worked OK and try again vs. mark ok and - // deny later + post = failWhenUnconfirmed(deliverySuspended), + // mark as failed even if it worked OK and try again vs. mark ok and deny later ).toPumpEnactResult() } From 32183aff373436887ea53d061fb0b21494812f61 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 16 Jul 2021 22:25:37 +0200 Subject: [PATCH 19/29] format. remove duplication --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 31 ++-- .../dash/driver/OmnipodDashManagerImpl.kt | 132 ++++++------------ .../dash/driver/comm/ServiceDiscoverer.kt | 2 +- .../omnipod/dash/driver/comm/io/CmdBleIO.kt | 2 - .../pod/state/OmnipodDashPodStateManager.kt | 2 +- .../state/OmnipodDashPodStateManagerImpl.kt | 4 +- .../action/DashInitializePodViewModel.kt | 2 +- .../action/DashInsertCannulaViewModel.kt | 1 - 8 files changed, 71 insertions(+), 105 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index d90c04b8f7..73a6ce6ded 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -208,7 +208,6 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun finishHandshaking() { - } override fun connect(reason: String) { @@ -400,10 +399,15 @@ class OmnipodDashPumpPlugin @Inject constructor( .observeOn(aapsSchedulers.main) .subscribe( { - if (it.isChanged(resourceHelper, - R.string.key_omnipod_common_expiration_reminder_enabled) || - it.isChanged(resourceHelper, - R.string.key_omnipod_common_expiration_reminder_hours_before_shutdown)) { + if (it.isChanged( + resourceHelper, + R.string.key_omnipod_common_expiration_reminder_enabled + ) || + it.isChanged( + resourceHelper, + R.string.key_omnipod_common_expiration_reminder_hours_before_shutdown + ) + ) { commandQueue.customCommand(CommandUpdateAlertConfiguration(), null) } }, @@ -1043,25 +1047,29 @@ class OmnipodDashPumpPlugin @Inject constructor( val expirationReminderEnabled = sp.getBoolean(R.string.key_omnipod_common_expiration_reminder_enabled, true) val expirationHours = sp.getInt(R.string.key_omnipod_common_expiration_reminder_hours_before_shutdown, 7) val lowReservoirAlertEnabled = sp.getBoolean(R.string.key_omnipod_common_low_reservoir_alert_enabled, true) - val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units ,10) + val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units, 10) if (!podStateManager.differentAlertSettings( expirationReminderEnabled, expirationHours, lowReservoirAlertEnabled, lowReservoirAlertUnits - )) { + ) + ) { return PumpEnactResult(injector).success(true).enacted(false) } val podLifeLeft = Duration.between(ZonedDateTime.now(), podStateManager.expiry) val expiryAlertDelay = podLifeLeft.minus(Duration.ofHours(expirationHours.toLong())) if (expiryAlertDelay.isNegative) { - aapsLogger.warn(LTag.PUMPBTCOMM, "updateAlertConfiguration negative " + - "expiryAlertDuration=$expiryAlertDelay") + aapsLogger.warn( + LTag.PUMPBTCOMM, + "updateAlertConfiguration negative " + + "expiryAlertDuration=$expiryAlertDelay" + ) PumpEnactResult(injector).success(false).enacted(false) } - val alerts = listOf ( + val alerts = listOf( AlertConfiguration( AlertType.LOW_RESERVOIR, enabled = lowReservoirAlertEnabled, @@ -1088,7 +1096,8 @@ class OmnipodDashPumpPlugin @Inject constructor( command = omnipodManager.programAlerts(alerts).ignoreElements(), post = podStateManager.updateExpirationAlertSettings( expirationReminderEnabled, - expirationHours).andThen( + expirationHours + ).andThen( podStateManager.updateExpirationAlertSettings( lowReservoirAlertEnabled, lowReservoirAlertUnits diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index 5e6ff425dd..24004f4de6 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -84,10 +84,7 @@ class OmnipodDashManagerImpl @Inject constructor( override fun connect(stop: CountDownLatch): Observable { return observeConnectToPodWithStop(stop) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + .interceptPodEvents() } private fun observeConnectToPodWithStop(stop: CountDownLatch): Observable { @@ -244,10 +241,7 @@ class OmnipodDashManagerImpl @Inject constructor( observeConnectToPod, observeActivationPart1Commands(lowReservoirAlertTrigger) ).doOnComplete(ActivationProgressUpdater(ActivationProgress.PHASE_1_COMPLETED)) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + .interceptPodEvents() } private fun observeActivationPart1Commands(lowReservoirAlertTrigger: AlertTrigger.ReservoirVolumeTrigger?): Observable { @@ -343,17 +337,14 @@ class OmnipodDashManagerImpl @Inject constructor( return observables.reversed() } - override fun activatePodPart2(basalProgram: BasalProgram, userConfiguredExpirationHours:Long?): + override fun activatePodPart2(basalProgram: BasalProgram, userConfiguredExpirationHours: Long?): Observable { return Observable.concat( observePodReadyForActivationPart2, observeConnectToPod, observeActivationPart2Commands(basalProgram, userConfiguredExpirationHours) ).doOnComplete(ActivationProgressUpdater(ActivationProgress.COMPLETED)) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + .interceptPodEvents() } private fun observeActivationPart2Commands(basalProgram: BasalProgram, userConfiguredExpirationHours: Long?): @@ -367,8 +358,10 @@ class OmnipodDashManagerImpl @Inject constructor( } } - private fun createActivationPart2Observables(basalProgram: BasalProgram, - userConfiguredExpirationHours: Long?): + private fun createActivationPart2Observables( + basalProgram: BasalProgram, + userConfiguredExpirationHours: Long? + ): List> { val observables = ArrayList>() @@ -397,7 +390,6 @@ class OmnipodDashManagerImpl @Inject constructor( if (podStateManager.activationProgress.isBefore(ActivationProgress.UPDATED_EXPIRATION_ALERTS)) { val podLifeLeft = Duration.between(ZonedDateTime.now(), podStateManager.expiry) - val alerts = mutableListOf( AlertConfiguration( AlertType.EXPIRATION, @@ -423,27 +415,33 @@ class OmnipodDashManagerImpl @Inject constructor( ) ) val userExpiryAlertDelay = podLifeLeft.minus( - Duration.ofHours(userConfiguredExpirationHours ?: MAX_POD_LIFETIME.toHours() + 1)) + Duration.ofHours(userConfiguredExpirationHours ?: MAX_POD_LIFETIME.toHours() + 1) + ) if (userExpiryAlertDelay.isNegative) { - logger.warn(LTag.PUMPBTCOMM, "createActivationPart2Observables negative " + - "expiryAlertDuration=$userExpiryAlertDelay") + logger.warn( + LTag.PUMPBTCOMM, + "createActivationPart2Observables negative " + + "expiryAlertDuration=$userExpiryAlertDelay" + ) } else { - alerts.add( AlertConfiguration( - AlertType.USER_SET_EXPIRATION, - enabled = true, - durationInMinutes = 0, - autoOff = false, - AlertTrigger.TimerTrigger( - userExpiryAlertDelay.toMinutes().toShort() - ), - BeepType.FOUR_TIMES_BIP_BEEP, - BeepRepetitionType.XXX2 - )) + alerts.add( + AlertConfiguration( + AlertType.USER_SET_EXPIRATION, + enabled = true, + durationInMinutes = 0, + autoOff = false, + AlertTrigger.TimerTrigger( + userExpiryAlertDelay.toMinutes().toShort() + ), + BeepType.FOUR_TIMES_BIP_BEEP, + BeepRepetitionType.XXX2 + ) + ) } observables.add( observeSendProgramAlertsCommand( - alerts, + alerts, multiCommandFlag = true ).doOnComplete(ActivationProgressUpdater(ActivationProgress.UPDATED_EXPIRATION_ALERTS)) ) @@ -463,11 +461,7 @@ class OmnipodDashManagerImpl @Inject constructor( observeUniqueIdSet, observeConnectToPod, observeSendGetPodStatusCommand(type) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } override fun setBasalProgram(basalProgram: BasalProgram, hasBasalBeepEnabled: Boolean): Observable { @@ -475,11 +469,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendProgramBasalCommand(basalProgram, hasBasalBeepEnabled) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } private fun observeSendStopDeliveryCommand( @@ -510,11 +500,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendStopDeliveryCommand(StopDeliveryCommand.DeliveryType.ALL, hasBasalBeepEnabled) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } override fun setTime(): Observable { @@ -544,11 +530,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendProgramTempBasalCommand(rate, durationInMinutes, tempBasalBeeps) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } override fun stopTempBasal(hasTempBasalBeepEnabled: Boolean): Observable { @@ -556,11 +538,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendStopDeliveryCommand(StopDeliveryCommand.DeliveryType.TEMP_BASAL, hasTempBasalBeepEnabled) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } override fun bolus(units: Double, confirmationBeeps: Boolean, completionBeeps: Boolean): Observable { @@ -573,11 +551,7 @@ class OmnipodDashManagerImpl @Inject constructor( confirmationBeeps, completionBeeps ) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } override fun stopBolus(beep: Boolean): Observable { @@ -585,11 +559,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendStopDeliveryCommand(StopDeliveryCommand.DeliveryType.BOLUS, beep) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } private fun observeSendConfigureBeepsCommand( @@ -618,11 +588,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendConfigureBeepsCommand(immediateBeepType = beepType) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } override fun programAlerts(alertConfigurations: List): Observable { @@ -630,11 +596,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendProgramAlertsCommand(alertConfigurations) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } private fun observeSendSilenceAlertsCommand(alertTypes: EnumSet): Observable { @@ -656,11 +618,7 @@ class OmnipodDashManagerImpl @Inject constructor( observePodRunning, observeConnectToPod, observeSendSilenceAlertsCommand(alertTypes) - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() } private val observeSendDeactivateCommand: Observable @@ -679,11 +637,7 @@ class OmnipodDashManagerImpl @Inject constructor( return Observable.concat( observeConnectToPod, observeSendDeactivateCommand - ) - // TODO these would be common for any observable returned in a public function in this class - .doOnNext(PodEventInterceptor()) - .doOnError(ErrorInterceptor()) - .subscribeOn(aapsSchedulers.io) + ).interceptPodEvents() // .doOnComplete(podStateManager::reset) } @@ -760,6 +714,12 @@ class OmnipodDashManagerImpl @Inject constructor( } } + private fun Observable.interceptPodEvents(): Observable { + return this.doOnNext(PodEventInterceptor()) + .doOnError(ErrorInterceptor()) + .subscribeOn(aapsSchedulers.io) + } + inner class ErrorInterceptor : Consumer { override fun accept(throwable: Throwable) { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt index c3c38e0030..2fc1c42704 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -36,7 +36,7 @@ class ServiceDiscoverer( } connectionWaitCond.stopConnection?.let { while (!bleCallbacks.waitForServiceDiscovery(STOP_CONNECTING_CHECK_INTERVAL_MS)) { - if (it.count == 0L || connection.connectionState() !is Connected) { + if (it.count == 0L || connection.connectionState() !is Connected) { throw ConnectException("stopConnecting called") } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt index d524fa6668..8421a6f1d3 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/CmdBleIO.kt @@ -2,9 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic -import info.nightscout.androidaps.extensions.toHex import info.nightscout.androidaps.logging.AAPSLogger -import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommand diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index cada0148c8..af833c4552 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -102,7 +102,7 @@ interface OmnipodDashPodStateManager { */ fun recoverActivationFromPodStatus(): String? fun differentAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int, lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Boolean - fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int) : Completable + fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int): Completable fun updateLowReservoirAlertSettings(lowReservoirAlertEnabled: Boolean, lowReservoirAlertUnits: Int): Completable data class ActiveCommand( diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 0d57d2e976..f71aa63bcc 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -409,8 +409,8 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( podState.lowReservoirAlertUnits == lowReservoirAlertUnits } - override fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int) : - Completable = Completable.defer{ + override fun updateExpirationAlertSettings(expirationReminderEnabled: Boolean, expirationHours: Int): + Completable = Completable.defer { podState.expirationReminderEnabled = expirationReminderEnabled podState.expirationHours = expirationHours Completable.complete() diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt index b39a2213be..cbdce8ab5a 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt @@ -32,7 +32,7 @@ class DashInitializePodViewModel @Inject constructor( Single.create { source -> // TODO use configured value for low reservoir trigger val lowReservoirAlertEnabled = sp.getBoolean(R.string.key_omnipod_common_low_reservoir_alert_enabled, true) - val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units ,10) + val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units, 10) val lowReservoirAlertTrigger = if (lowReservoirAlertEnabled) { AlertTrigger.ReservoirVolumeTrigger((lowReservoirAlertUnits * 10).toShort()) } else diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index 0f66c247e9..4f5f2f06c9 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -15,7 +15,6 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel import info.nightscout.androidaps.plugins.pump.omnipod.dash.R import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram import info.nightscout.androidaps.utils.sharedPreferences.SP From f9aa967b462c7d294be84455f6d82f93fcf6ae8f Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 16 Jul 2021 23:17:37 +0200 Subject: [PATCH 20/29] set initial basalProgram. fix handshaking state --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 8 +++++--- .../driver/pod/state/OmnipodDashPodStateManagerImpl.kt | 2 ++ .../viewmodel/action/DashInsertCannulaViewModel.kt | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 73a6ce6ded..c7f5d821e2 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -200,11 +200,12 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun isConnecting(): Boolean { - return stopConnecting != null && podStateManager.bluetoothConnectionState == OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING + return stopConnecting != null } override fun isHandshakeInProgress(): Boolean { - return stopConnecting != null + return stopConnecting != null && + podStateManager.bluetoothConnectionState == OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTED } override fun finishHandshaking() { @@ -212,6 +213,7 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun connect(reason: String) { aapsLogger.info(LTag.PUMP, "connect reason=$reason") + podStateManager.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING thread( start = true, name = "ConnectionThread", @@ -437,7 +439,7 @@ class OmnipodDashPumpPlugin @Inject constructor( // TODO: what do we have to answer here if delivery is suspended? val running = podStateManager.basalProgram val equal = (mapProfileToBasalProgram(profile) == running) - aapsLogger.info(LTag.PUMP, "isThisProfileSet: $equal") + aapsLogger.info(LTag.PUMP, "set: $equal. profile=$profile, running=$running") return equal } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index f71aa63bcc..ad9d789467 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -218,7 +218,9 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } override var bluetoothConnectionState: OmnipodDashPodStateManager.BluetoothConnectionState + @Synchronized get() = podState.bluetoothConnectionState + @Synchronized set(bluetoothConnectionState) { podState.bluetoothConnectionState = bluetoothConnectionState rxBus.send(EventOmnipodDashPumpValuesChanged()) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index 4f5f2f06c9..4173fcd4c7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -73,6 +73,7 @@ class DashInsertCannulaViewModel @Inject constructor( }, onComplete = { logger.debug("Pod activation part 2 completed") + podStateManager.basalProgram = basalProgram pumpSync.connectNewPump() pumpSync.insertTherapyEventIfNewWithTimestamp( timestamp = System.currentTimeMillis(), From bf7ad8e697c03ec5b87b33548ecaea0c4d93c9f0 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 17 Jul 2021 10:35:44 +0200 Subject: [PATCH 21/29] fixes: - closeGatt on stopConnecting - fix stopBolus --- .../pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 11 +++++++++-- .../omnipod/dash/driver/OmnipodDashManager.kt | 2 +- .../dash/driver/OmnipodDashManagerImpl.kt | 4 ++-- .../dash/driver/comm/OmnipodDashBleManager.kt | 2 +- .../driver/comm/OmnipodDashBleManagerImpl.kt | 10 +++++----- .../driver/comm/callbacks/BleCommCallbacks.kt | 15 ++++++++++----- .../dash/driver/comm/session/Connection.kt | 16 ++++++++++------ 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index c7f5d821e2..b73e730e5b 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -78,6 +78,8 @@ class OmnipodDashPumpPlugin @Inject constructor( commandQueue: CommandQueueProvider ) : PumpPluginBase(pluginDescription, injector, aapsLogger, resourceHelper, commandQueue), Pump { @Volatile var bolusCanceled = false + @Volatile var bolusDeliveryInProgress = false + private val handler: Handler = Handler(Looper.getMainLooper()) private lateinit var statusChecker: Runnable var nextPodWarningCheck: Long = 0 @@ -232,12 +234,13 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun disconnect(reason: String) { aapsLogger.info(LTag.PUMP, "disconnect reason=$reason") stopConnecting?.let { it.countDown() } - omnipodManager.disconnect() + omnipodManager.disconnect(false) } override fun stopConnecting() { aapsLogger.info(LTag.PUMP, "stopConnecting") stopConnecting?.let { it.countDown() } + omnipodManager.disconnect(true) } override fun getPumpStatus(reason: String) { @@ -476,6 +479,7 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { try { + bolusDeliveryInProgress = true aapsLogger.info(LTag.PUMP, "Delivering treatment: $detailedBolusInfo $bolusCanceled") val beepsConfigurationKey = if (detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB) R.string.key_omnipod_common_smb_beeps_enabled @@ -563,6 +567,7 @@ class OmnipodDashPumpPlugin @Inject constructor( return ret } finally { bolusCanceled = false + bolusDeliveryInProgress = false } } @@ -697,7 +702,9 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun stopBolusDelivering() { aapsLogger.info(LTag.PUMP, "stopBolusDelivering called") - bolusCanceled = true + if (bolusDeliveryInProgress) { + bolusCanceled = true + } } override fun setTempBasalAbsolute( diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt index f0c2c85947..e9d4c68fba 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt @@ -41,7 +41,7 @@ interface OmnipodDashManager { fun deactivatePod(): Observable - fun disconnect() + fun disconnect(closeGatt: Boolean=false) fun connect(stop: CountDownLatch): Observable } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index 24004f4de6..e504e93e62 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -78,8 +78,8 @@ class OmnipodDashManagerImpl @Inject constructor( } } - override fun disconnect() { - bleManager.disconnect() + override fun disconnect(closeGatt: Boolean) { + bleManager.disconnect(closeGatt) } override fun connect(stop: CountDownLatch): Observable { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt index d0aa9013f2..bdfc1c4e5d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt @@ -23,5 +23,5 @@ interface OmnipodDashBleManager { fun pairNewPod(): Observable - fun disconnect() + fun disconnect(closeGatt: Boolean=false) } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt index 4a13d50585..60b9363238 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt @@ -84,7 +84,7 @@ class OmnipodDashBleManagerImpl @Inject constructor( } emitter.onComplete() } catch (ex: Exception) { - disconnect() + disconnect(false) emitter.tryOnError(ex) } finally { busy.set(false) @@ -142,7 +142,7 @@ class OmnipodDashBleManagerImpl @Inject constructor( emitter.onComplete() } catch (ex: Exception) { - disconnect() + disconnect(false) emitter.tryOnError(ex) } finally { busy.set(false) @@ -226,15 +226,15 @@ class OmnipodDashBleManagerImpl @Inject constructor( emitter.onNext(PodEvent.Connected) emitter.onComplete() } catch (ex: Exception) { - disconnect() + disconnect(false) emitter.tryOnError(ex) } finally { busy.set(false) } } - override fun disconnect() { - connection?.disconnect() + override fun disconnect(closeGatt: Boolean) { + connection?.disconnect(closeGatt) ?: aapsLogger.info(LTag.PUMPBTCOMM, "Trying to disconnect a null connection") } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index 7f8b907ec8..966eb35836 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -40,7 +40,8 @@ class BleCommCallbacks( if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) { connected.countDown() } - if (newState == BluetoothProfile.STATE_DISCONNECTED) { + if (newState == BluetoothProfile.STATE_DISCONNECTED && status != BluetoothGatt.GATT_SUCCESS ) { + // If status == SUCCESS, it means that we initiated the disconnect. disconnectHandler.onConnectionLost(status) } } @@ -54,12 +55,13 @@ class BleCommCallbacks( } fun waitForConnection(timeoutMs: Long): Boolean { + val latch = connected try { - connected.await(timeoutMs, TimeUnit.MILLISECONDS) + latch.await(timeoutMs, TimeUnit.MILLISECONDS) } catch (e: InterruptedException) { aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while waiting for Connection") } - return connected.count == 0L + return latch.count == 0L } fun startServiceDiscovery() { @@ -67,12 +69,13 @@ class BleCommCallbacks( } fun waitForServiceDiscovery(timeoutMs: Long): Boolean { + val latch = serviceDiscoveryComplete try { - serviceDiscoveryComplete.await(timeoutMs, TimeUnit.MILLISECONDS) + latch.await(timeoutMs, TimeUnit.MILLISECONDS) } catch (e: InterruptedException) { aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while waiting for ServiceDiscovery") } - return serviceDiscoveryComplete.count == 0L + return latch.count == 0L } fun confirmWrite(expectedPayload: ByteArray, expectedUUID: String, timeoutMs: Long): WriteConfirmation { @@ -208,6 +211,8 @@ class BleCommCallbacks( fun resetConnection() { aapsLogger.debug(LTag.PUMPBTCOMM, "Reset connection") + connected?.countDown() + serviceDiscoveryComplete?.countDown() connected = CountDownLatch(1) serviceDiscoveryComplete = CountDownLatch(1) flushConfirmationQueue() diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index 358e093cfb..261f42e0ea 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -63,7 +63,7 @@ class Connection( var msgIO: MessageIO? = null fun connect(connectionWaitCond: ConnectionWaitCondition) { - aapsLogger.debug("Connecting") + aapsLogger.debug("Connecting connectionWaitCond=$connectionWaitCond") podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING val autoConnect = false @@ -115,11 +115,15 @@ class Connection( dataBleIO.readyToRead() } - fun disconnect() { - aapsLogger.debug(LTag.PUMPBTCOMM, "Disconnecting") + fun disconnect(closeGatt: Boolean) { + aapsLogger.debug(LTag.PUMPBTCOMM, "Disconnecting closeGatt=$closeGatt") podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED - - gattConnection?.disconnect() + if (closeGatt) { + gattConnection?.close() + gattConnection = null + } else { + gattConnection?.disconnect() + } bleCommCallbacks.resetConnection() session = null msgIO = null @@ -186,7 +190,7 @@ class Connection( // This will be called from a different thread !!! override fun onConnectionLost(status: Int) { aapsLogger.info(LTag.PUMPBTCOMM, "Lost connection with status: $status") - disconnect() + disconnect(false) } companion object { From 5283295eda2f05c92d41617f4c8930a2772297b8 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 17 Jul 2021 11:33:49 +0200 Subject: [PATCH 22/29] notification sounds --- .../src/main/res/values/strings.xml | 11 +++++++- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 27 +++++++++++++++---- .../main/res/xml/omnipod_dash_preferences.xml | 27 +++++++++++++++++-- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/omnipod-common/src/main/res/values/strings.xml b/omnipod-common/src/main/res/values/strings.xml index eb3ae323c6..040757704d 100644 --- a/omnipod-common/src/main/res/values/strings.xml +++ b/omnipod-common/src/main/res/values/strings.xml @@ -13,7 +13,11 @@ AAPS.Omnipod.low_reservoir_alert_units AAPS.Omnipod.automatically_acknowledge_alerts_enabled common_preferences_category_alerts - + common_preferences_category_notifications_settings + AAPS.Omnipod.notification_uncertain_tbr_sound_enabled + AAPS.Omnipod.notification_uncertain_smb_sound_enabled + AAPS.Omnipod.notification_uncertain_bolus_sound_enabled Pod Management Actions @@ -132,6 +136,11 @@ Other Alerts Confirmation Beeps + Notifications + Sound for uncertain TBR notifications enabled + Sound for + uncertain SMB notifications enabled + Sound for uncertain bolus notifications enabled No Active Pod diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index b73e730e5b..22fbb357ec 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -364,6 +364,8 @@ class OmnipodDashPumpPlugin @Inject constructor( } Completable.error(java.lang.IllegalStateException("Command not confirmed")) } else { + showNotification(Notification.PROFILE_SET_OK, "Profile set OK", Notification.INFO, null); + Completable.complete() } } @@ -549,9 +551,16 @@ class OmnipodDashPumpPlugin @Inject constructor( ) } else { if (podStateManager.activeCommand != null) { + val sound = if (sp.getBoolean(R.string + .key_omnipod_common_notification_uncertain_tbr_sound_enabled, + true)) + R.raw.boluserror + else + 0 + showErrorDialog( "Bolus delivery status uncertain. Refresh pod status to confirm or deny.", - R.raw.boluserror + sound ) } } @@ -1330,14 +1339,22 @@ class OmnipodDashPumpPlugin @Inject constructor( message, urgency ) - // TODO add back sound when we have options to disable it - /* - if (sound != null) { + if (sound != null && soundEnabledForNotificationType(id)) { notification.soundId = sound - }*/ + } rxBus.send(EventNewNotification(notification)) } + private fun soundEnabledForNotificationType(notificationType: Int): Boolean{ + return when(notificationType) { + Notification.OMNIPOD_TBR_ALERTS -> + sp.getBoolean(R.string.key_omnipod_common_notification_uncertain_tbr_sound_enabled, true) + Notification.OMNIPOD_UNCERTAIN_SMB -> + sp.getBoolean(R.string.key_omnipod_common_notification_uncertain_smb_sound_enabled, true) + else -> true + } + } + private fun dismissNotification(id: Int) { rxBus.send(EventDismissNotification(id)) } diff --git a/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml b/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml index 633be9fc6e..0e1d2dd11a 100644 --- a/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml +++ b/omnipod-dash/src/main/res/xml/omnipod_dash_preferences.xml @@ -65,11 +65,34 @@ validate:maxNumber="50" validate:minNumber="5" validate:testType="numericRange" /> + + + + + android:key="@string/key_omnipod_common_notification_uncertain_tbr_sound_enabled" + android:title="@string/omnipod_common_preferences_notification_uncertain_tbr_sound_enabled" /> + + + + + Date: Sat, 17 Jul 2021 11:36:12 +0200 Subject: [PATCH 23/29] fix option key --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 22fbb357ec..a2ac4e4e43 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -552,7 +552,7 @@ class OmnipodDashPumpPlugin @Inject constructor( } else { if (podStateManager.activeCommand != null) { val sound = if (sp.getBoolean(R.string - .key_omnipod_common_notification_uncertain_tbr_sound_enabled, + .key_omnipod_common_notification_uncertain_bolus_sound_enabled, true)) R.raw.boluserror else From b9af0c3f6fe50f620a2a9a098081b099c809d744 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 17 Jul 2021 11:45:28 +0200 Subject: [PATCH 24/29] format --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 23 ++++++++++++++----- .../omnipod/dash/driver/OmnipodDashManager.kt | 2 +- .../dash/driver/comm/OmnipodDashBleManager.kt | 2 +- .../driver/comm/callbacks/BleCommCallbacks.kt | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index a2ac4e4e43..0304e2be93 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -364,7 +364,7 @@ class OmnipodDashPumpPlugin @Inject constructor( } Completable.error(java.lang.IllegalStateException("Command not confirmed")) } else { - showNotification(Notification.PROFILE_SET_OK, "Profile set OK", Notification.INFO, null); + showNotification(Notification.PROFILE_SET_OK, "Profile set OK", Notification.INFO, null) Completable.complete() } @@ -413,6 +413,14 @@ class OmnipodDashPumpPlugin @Inject constructor( it.isChanged( resourceHelper, R.string.key_omnipod_common_expiration_reminder_hours_before_shutdown + ) || + it.isChanged( + resourceHelper, + R.string.key_omnipod_common_low_reservoir_alert_enabled + ) || + it.isChanged( + resourceHelper, + R.string.key_omnipod_common_low_reservoir_alert_units ) ) { commandQueue.customCommand(CommandUpdateAlertConfiguration(), null) @@ -551,9 +559,12 @@ class OmnipodDashPumpPlugin @Inject constructor( ) } else { if (podStateManager.activeCommand != null) { - val sound = if (sp.getBoolean(R.string - .key_omnipod_common_notification_uncertain_bolus_sound_enabled, - true)) + val sound = if (sp.getBoolean( + R.string + .key_omnipod_common_notification_uncertain_bolus_sound_enabled, + true + ) + ) R.raw.boluserror else 0 @@ -1345,8 +1356,8 @@ class OmnipodDashPumpPlugin @Inject constructor( rxBus.send(EventNewNotification(notification)) } - private fun soundEnabledForNotificationType(notificationType: Int): Boolean{ - return when(notificationType) { + private fun soundEnabledForNotificationType(notificationType: Int): Boolean { + return when (notificationType) { Notification.OMNIPOD_TBR_ALERTS -> sp.getBoolean(R.string.key_omnipod_common_notification_uncertain_tbr_sound_enabled, true) Notification.OMNIPOD_UNCERTAIN_SMB -> diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt index e9d4c68fba..718df1597b 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt @@ -41,7 +41,7 @@ interface OmnipodDashManager { fun deactivatePod(): Observable - fun disconnect(closeGatt: Boolean=false) + fun disconnect(closeGatt: Boolean = false) fun connect(stop: CountDownLatch): Observable } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt index bdfc1c4e5d..7a98a61b19 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManager.kt @@ -23,5 +23,5 @@ interface OmnipodDashBleManager { fun pairNewPod(): Observable - fun disconnect(closeGatt: Boolean=false) + fun disconnect(closeGatt: Boolean = false) } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index 966eb35836..6e193193b3 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -40,7 +40,7 @@ class BleCommCallbacks( if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) { connected.countDown() } - if (newState == BluetoothProfile.STATE_DISCONNECTED && status != BluetoothGatt.GATT_SUCCESS ) { + if (newState == BluetoothProfile.STATE_DISCONNECTED && status != BluetoothGatt.GATT_SUCCESS) { // If status == SUCCESS, it means that we initiated the disconnect. disconnectHandler.onConnectionLost(status) } From eb33e89ea75ed0fc95a9e9936f18210eb917019b Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 17 Jul 2021 12:09:15 +0200 Subject: [PATCH 25/29] fixes: - read(and log) message on connect if there is RTS waiting - show yellow pod status on unconfirmed commands --- .../omnipod/dash/driver/comm/message/MessageIO.kt | 14 ++++++++------ .../omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 10 ++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt index 2394ae14e2..0aa3033894 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessageIO.kt @@ -37,7 +37,7 @@ class MessageIO( fun sendMessage(msg: MessagePacket): MessageSendResult { val foundRTS = cmdBleIO.flushIncomingQueue() if (foundRTS) { - val msg = receiveMessage() + val msg = receiveMessage(false) aapsLogger.warn(LTag.PUMPBTCOMM, "sendMessage received message=$msg") throw IllegalStateException("Received message while trying to send") } @@ -90,11 +90,13 @@ class MessageIO( } @Suppress("ReturnCount") - fun receiveMessage(): MessagePacket? { - val expectRTS = cmdBleIO.expectCommandType(BleCommandRTS, MESSAGE_READ_TIMEOUT_MS) - if (expectRTS !is BleConfirmSuccess) { - aapsLogger.warn(LTag.PUMPBTCOMM, "Error reading RTS: $expectRTS") - return null + fun receiveMessage(readRTS: Boolean = true): MessagePacket? { + if (readRTS) { + val expectRTS = cmdBleIO.expectCommandType(BleCommandRTS, MESSAGE_READ_TIMEOUT_MS) + if (expectRTS !is BleConfirmSuccess) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Error reading RTS: $expectRTS") + return null + } } val sendResult = cmdBleIO.sendAndConfirmPacket(BleCommandCTS.data) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index ea37bf5aeb..97f70338a5 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -432,12 +432,14 @@ class OmnipodDashOverviewFragment : DaggerFragment() { } } - val podStatusColor = - if (!podStateManager.isActivationCompleted || podStateManager.isPodKaput || podStateManager.isSuspended) { + val podStatusColor = when { + !podStateManager.isActivationCompleted || podStateManager.isPodKaput || podStateManager.isSuspended -> Color.RED - } else { + podStateManager.activeCommand != null -> + Color.YELLOW + else -> Color.WHITE - } + } podInfoBinding.podStatus.setTextColor(podStatusColor) } From ba5529e86893b469d11fc111a2f8d7dedef934ed Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 23 Jul 2021 19:30:25 +0200 Subject: [PATCH 26/29] fix race --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 0304e2be93..4856f351b9 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -216,17 +216,29 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun connect(reason: String) { aapsLogger.info(LTag.PUMP, "connect reason=$reason") podStateManager.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING + + synchronized(this) { + stopConnecting?.let { + aapsLogger.warn(LTag.PUMP, "Already connecting: $stopConnecting") + return + } + val stop = CountDownLatch(1) + stopConnecting = stop + } + thread( start = true, name = "ConnectionThread", ) { try { - val stop = CountDownLatch(1) - stopConnecting = stop - val error = omnipodManager.connect(stop).ignoreElements().blockingGet() - aapsLogger.info(LTag.PUMPCOMM, "connect error=$error") + stopConnecting?.let{ + val error = omnipodManager.connect(it).ignoreElements().blockingGet() + aapsLogger.info(LTag.PUMPCOMM, "connect error=${error}") + } } finally { - stopConnecting = null + synchronized(this) { + stopConnecting = null + } } } } From 2e8a81f38de1e01ff782fea3fb8d07badae16b49 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 25 Jul 2021 15:18:59 +0200 Subject: [PATCH 27/29] format. refresh Overview --- .../pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 4856f351b9..8ab1e04845 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventProfileSwitchChanged +import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.events.EventTempBasalChange import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger @@ -231,9 +232,9 @@ class OmnipodDashPumpPlugin @Inject constructor( name = "ConnectionThread", ) { try { - stopConnecting?.let{ + stopConnecting?.let { val error = omnipodManager.connect(it).ignoreElements().blockingGet() - aapsLogger.info(LTag.PUMPCOMM, "connect error=${error}") + aapsLogger.info(LTag.PUMPCOMM, "connect error=$error") } } finally { synchronized(this) { @@ -1203,11 +1204,17 @@ class OmnipodDashPumpPlugin @Inject constructor( .map { handleCommandConfirmation(it) } .ignoreElement(), checkPodKaput(), + refreshOverview(), post, ) ) } + private fun refreshOverview(): Completable = Completable.defer { + rxBus.send(EventRefreshOverview("Dash command", false)) + Completable.complete() + } + private fun handleCommandConfirmation(confirmation: CommandConfirmed) { val command = confirmation.command val historyEntry = history.getById(command.historyId) From ec22bec5a664c02f4157a7e7a078ecee28bcdcf6 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Wed, 28 Jul 2021 19:05:52 +0200 Subject: [PATCH 28/29] remove todo --- .../activation/viewmodel/action/DashInitializePodViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt index cbdce8ab5a..4862dc6a46 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInitializePodViewModel.kt @@ -30,7 +30,6 @@ class DashInitializePodViewModel @Inject constructor( override fun doExecuteAction(): Single = Single.create { source -> - // TODO use configured value for low reservoir trigger val lowReservoirAlertEnabled = sp.getBoolean(R.string.key_omnipod_common_low_reservoir_alert_enabled, true) val lowReservoirAlertUnits = sp.getInt(R.string.key_omnipod_common_low_reservoir_alert_units, 10) val lowReservoirAlertTrigger = if (lowReservoirAlertEnabled) { From e2b419c7cdcf4b47889821331024b11241776fb6 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Wed, 28 Jul 2021 19:20:29 +0200 Subject: [PATCH 29/29] update comments --- .../dash/driver/pod/definition/BeepRepetitionType.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt index d799b395e2..d7a1a8f761 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/BeepRepetitionType.kt @@ -7,7 +7,7 @@ enum class BeepRepetitionType( XXX(0x01.toByte()), // Used in lump of coal alert, LOW_RESERVOIR XXX2(0x03.toByte()), // Used in USER_SET_EXPIRATION - XXX3(0x05.toByte()), // Used in user pod expiration alert - XXX4(0x06.toByte()), // Used in pod expiration alert - XXX5(0x08.toByte()); // Used in imminent pod expiration alert + XXX3(0x05.toByte()), // published system expiration alert + XXX4(0x06.toByte()), // Used in imminent pod expiration alert + XXX5(0x08.toByte()); // Lump of coal alert }