Merge pull request #11 from 0pen-dash/bart/observable-connect

Make OmnipodDashBleManager.connect() return an Observable of PodEvents
This commit is contained in:
Andrei Vereha 2021-02-28 18:30:06 +01:00 committed by GitHub
commit 11633995f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 280 additions and 104 deletions

View file

@ -1,3 +1,9 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action
abstract class InitializePodViewModel : PodActivationActionViewModelBase() import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
abstract class InitializePodViewModel(
injector: HasAndroidInjector,
logger: AAPSLogger
) : PodActivationActionViewModelBase(injector, logger)

View file

@ -1,3 +1,9 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action
abstract class InsertCannulaViewModel : PodActivationActionViewModelBase() import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
abstract class InsertCannulaViewModel(
injector: HasAndroidInjector,
logger: AAPSLogger
) : PodActivationActionViewModelBase(injector, logger)

View file

@ -1,8 +1,13 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase
abstract class PodActivationActionViewModelBase : ActionViewModelBase() { abstract class PodActivationActionViewModelBase(
injector: HasAndroidInjector,
logger: AAPSLogger
) : ActionViewModelBase(injector, logger) {
abstract fun isPodInAlarm(): Boolean abstract fun isPodInAlarm(): Boolean

View file

@ -2,11 +2,17 @@ package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import io.reactivex.schedulers.Schedulers import info.nightscout.androidaps.logging.AAPSLogger
import io.reactivex.subjects.SingleSubject import info.nightscout.androidaps.logging.LTag
import io.reactivex.Single
import io.reactivex.rxkotlin.subscribeBy
abstract class ActionViewModelBase : ViewModelBase() { abstract class ActionViewModelBase(
protected val injector: HasAndroidInjector,
protected val logger: AAPSLogger
) : ViewModelBase() {
private val _isActionExecutingLiveData = MutableLiveData(false) private val _isActionExecutingLiveData = MutableLiveData(false)
val isActionExecutingLiveData: LiveData<Boolean> = _isActionExecutingLiveData val isActionExecutingLiveData: LiveData<Boolean> = _isActionExecutingLiveData
@ -16,14 +22,17 @@ abstract class ActionViewModelBase : ViewModelBase() {
fun executeAction() { fun executeAction() {
_isActionExecutingLiveData.postValue(true) _isActionExecutingLiveData.postValue(true)
SingleSubject.fromCallable(this::doExecuteAction) val disposable = doExecuteAction().subscribeBy(
.subscribeOn(Schedulers.io()) onSuccess = { result ->
.doOnSuccess { result ->
_isActionExecutingLiveData.postValue(false) _isActionExecutingLiveData.postValue(false)
_actionResultLiveData.postValue(result) _actionResultLiveData.postValue(result)
} },
.subscribe() onError = { throwable ->
logger.error(LTag.PUMP, "Caught exception in while executing action in ActionViewModelBase", throwable)
_isActionExecutingLiveData.postValue(false)
_actionResultLiveData.postValue(PumpEnactResult(injector).success(false).comment(throwable.message))
})
} }
protected abstract fun doExecuteAction(): PumpEnactResult protected abstract fun doExecuteAction(): Single<PumpEnactResult>
} }

View file

@ -1,8 +1,13 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.action package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.action
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase
abstract class DeactivatePodViewModel : ActionViewModelBase() { abstract class DeactivatePodViewModel(
injector: HasAndroidInjector,
logger: AAPSLogger
) : ActionViewModelBase(injector, logger) {
abstract fun discardPod() abstract fun discardPod()
} }

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver
import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManager
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.GetVersionCommand import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.GetVersionCommand
@ -9,50 +10,58 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.AlarmStatusResponse
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.DefaultStatusResponse
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.SetUniqueIdResponse
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.VersionResponse
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.functions.Consumer
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class OmnipodDashManagerImpl @Inject constructor( class OmnipodDashManagerImpl @Inject constructor(
private val aapsLogger: AAPSLogger, private val logger: AAPSLogger,
private val podStateManager: OmnipodDashPodStateManager, private val podStateManager: OmnipodDashPodStateManager,
private val bleManager: OmnipodDashBleManager private val bleManager: OmnipodDashBleManager,
private val aapsSchedulers: AapsSchedulers
) : OmnipodDashManager { ) : OmnipodDashManager {
private val observePodReadyForActivationPart1: Observable<PodEvent> private val observePodReadyForActivationPart1: Observable<PodEvent>
get() { get() = Observable.defer {
if (podStateManager.activationProgress.isBefore(ActivationProgress.PHASE_1_COMPLETED)) { if (podStateManager.activationProgress.isBefore(ActivationProgress.PHASE_1_COMPLETED)) {
return Observable.empty() Observable.empty()
} else {
Observable.error(IllegalStateException("Pod is in an incorrect state"))
} }
return Observable.error(IllegalStateException("Pod is in an incorrect state"))
} }
private val observeConnectToPod: Observable<PodEvent> private val observeConnectToPod: Observable<PodEvent>
get() { get() = Observable.defer { bleManager.connect() }
return Observable.defer {
bleManager.connect() private val observeSendGetVersionCommand: Observable<PodEvent>
Observable.just(PodEvent.Connected(0)) // TODO should be returned in BleManager get() = Observable.defer {
} bleManager.sendCommand(GetVersionCommand.Builder() //
.setSequenceNumber(podStateManager.messageSequenceNumber) //
.setUniqueId(DEFAULT_UNIQUE_ID) //
.build()) //
} }
override fun activatePodPart1(): Observable<PodEvent> { override fun activatePodPart1(): Observable<PodEvent> {
val command = GetVersionCommand.Builder() //
.setSequenceNumber(podStateManager.messageSequenceNumber) //
.setUniqueId(DEFAULT_UNIQUE_ID) //
.build()
return Observable.concat( return Observable.concat(
observePodReadyForActivationPart1, observePodReadyForActivationPart1,
observeConnectToPod, observeConnectToPod,
Observable.defer { observeSendGetVersionCommand
bleManager.sendCommand(command)
Observable.just(PodEvent.CommandSent(command)) // TODO should be returned in BleManager
}
// ... Send more commands // ... Send more commands
) ) //
// TODO these would be common for any observable returned in a public function in this class
.doOnNext(PodEventInterceptor()) //
.doOnError(ErrorInterceptor())
.subscribeOn(aapsSchedulers.io)
} }
override fun activatePodPart2(): Observable<PodEvent> { override fun activatePodPart2(): Observable<PodEvent> {
@ -119,4 +128,63 @@ class OmnipodDashManagerImpl @Inject constructor(
// TODO // TODO
return Observable.empty() return Observable.empty()
} }
inner class PodEventInterceptor : Consumer<PodEvent> {
override fun accept(event: PodEvent) {
logger.debug(LTag.PUMP, "Intercepted PodEvent in OmnipodDashManagerImpl: ${event.javaClass.simpleName}")
when (event) {
is PodEvent.AlreadyConnected -> {
podStateManager.bluetoothAddress = event.bluetoothAddress
podStateManager.uniqueId = event.uniqueId
}
is PodEvent.BluetoothConnected -> {
podStateManager.bluetoothAddress = event.address
}
is PodEvent.Connected -> {
podStateManager.uniqueId = event.uniqueId
}
is PodEvent.ResponseReceived -> {
podStateManager.increaseMessageSequenceNumber()
handleResponse(event.response)
}
else -> {
// Do nothing
}
}
}
private fun handleResponse(response: Response) {
when (response) {
is VersionResponse -> {
podStateManager.updateFromVersionResponse(response)
}
is SetUniqueIdResponse -> {
podStateManager.updateFromSetUniqueIdResponse(response)
}
is DefaultStatusResponse -> {
podStateManager.updateFromDefaultStatusResponse(response)
}
is AlarmStatusResponse -> {
podStateManager.updateFromAlarmStatusResponse(response)
}
}
}
}
inner class ErrorInterceptor : Consumer<Throwable> {
override fun accept(throwable: Throwable) {
logger.debug(LTag.PUMP, "Intercepted error in OmnipodDashManagerImpl: ${throwable.javaClass.simpleName}")
}
}
} }

View file

@ -1,18 +1,17 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.status.ConnectionStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.status.ConnectionStatus
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.command.base.Command
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response import io.reactivex.Observable
interface OmnipodDashBleManager { interface OmnipodDashBleManager {
fun sendCommand(cmd: Command): Response fun sendCommand(cmd: Command): Observable<PodEvent>
fun getStatus(): ConnectionStatus fun getStatus(): ConnectionStatus
fun connect() fun connect(): Observable<PodEvent>
fun disconnect() fun disconnect()
fun getPodId(): Id
} }

View file

@ -17,8 +17,10 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ltk.LTKE
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageIO import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageIO
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.status.ConnectionStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.status.ConnectionStatus
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.command.base.Command
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response import io.reactivex.Observable
import org.apache.commons.lang3.NotImplementedException
import java.util.concurrent.BlockingQueue import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingDeque import java.util.concurrent.LinkedBlockingDeque
import java.util.concurrent.TimeoutException import java.util.concurrent.TimeoutException
@ -62,8 +64,9 @@ class OmnipodDashBleManagerImpl @Inject constructor(private val context: Context
return bleIO return bleIO
} }
override fun sendCommand(cmd: Command): Response { override fun sendCommand(cmd: Command): Observable<PodEvent> {
TODO("not implemented") // TODO
return Observable.error(NotImplementedException("sendCommand is not yet implemented"))
} }
override fun getStatus(): ConnectionStatus { override fun getStatus(): ConnectionStatus {
@ -71,30 +74,42 @@ class OmnipodDashBleManagerImpl @Inject constructor(private val context: Context
} }
@Throws(InterruptedException::class, ScanFailException::class, FailedToConnectException::class, CouldNotSendBleException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWriteException::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) @Throws(InterruptedException::class, ScanFailException::class, FailedToConnectException::class, CouldNotSendBleException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWriteException::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class)
override fun connect() { override fun connect(): Observable<PodEvent> = Observable.create { emitter ->
// TODO: this is wrong and I know it // TODO: when we are already connected,
aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation") // emit PodEvent.AlreadyConnected, complete the observable and return from this method
val podScanner = PodScanner(aapsLogger, bluetoothAdapter)
val podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).scanResult.device.address
// For tests: this.podAddress = "B8:27:EB:1D:7E:BB";
val bleIO = connect(podAddress)
val msgIO = MessageIO(aapsLogger, bleIO)
val ltkExchanger = LTKExchanger(aapsLogger, msgIO)
val ltk = ltkExchanger.negociateLTKAndNonce()
aapsLogger.info(LTag.PUMPCOMM, "Got LTK and Nonce Prefix: ${ltk}") try {
// TODO: this is wrong and I know it
aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation")
val podScanner = PodScanner(aapsLogger, bluetoothAdapter)
emitter.onNext(PodEvent.Scanning)
val podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).scanResult.device.address
// For tests: this.podAddress = "B8:27:EB:1D:7E:BB";
emitter.onNext(PodEvent.BluetoothConnecting)
val bleIO = connect(podAddress)
emitter.onNext(PodEvent.BluetoothConnected(podAddress))
val msgIO = MessageIO(aapsLogger, bleIO)
val ltkExchanger = LTKExchanger(aapsLogger, msgIO)
emitter.onNext(PodEvent.Pairing)
val ltk = ltkExchanger.negotiateLTKAndNonce()
aapsLogger.info(LTag.PUMPCOMM, "Got LTK and Nonce Prefix: ${ltk}")
emitter.onNext(PodEvent.Connected(PodScanner.POD_ID_NOT_ACTIVATED)) // TODO supply actual pod id
emitter.onComplete()
} catch (ex: Exception) {
emitter.tryOnError(ex)
}
} }
override fun disconnect() { override fun disconnect() {
TODO("not implemented") TODO("not implemented")
} }
override fun getPodId(): Id {
// TODO: return something meaningful here
return Id.fromInt(4243);
}
companion object { companion object {
private const val CONNECT_TIMEOUT_MS = 5000 private const val CONNECT_TIMEOUT_MS = 5000

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
open class ScanFailException : Exception { open class ScanFailException : Exception {
constructor() constructor(message: String) : super(message)
constructor(errorCode: Int) : super("errorCode$errorCode") constructor(errorCode: Int) : super("errorCode$errorCode")
} }

View file

@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.excepti
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.BleDiscoveredDevice import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.BleDiscoveredDevice
import java.util.* import java.util.*
class ScanFailFoundTooManyException(devices: List<BleDiscoveredDevice>) : ScanFailException() { class ScanFailFoundTooManyException(devices: List<BleDiscoveredDevice>) : ScanFailException("Found more than one Pod") {
private val devices: List<BleDiscoveredDevice> = ArrayList(devices) private val devices: List<BleDiscoveredDevice> = ArrayList(devices)
val discoveredDevices: List<BleDiscoveredDevice> val discoveredDevices: List<BleDiscoveredDevice>

View file

@ -1,3 +1,3 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
class ScanFailNotFoundException : ScanFailException() class ScanFailNotFoundException : ScanFailException("No Pod found")

View file

@ -9,7 +9,7 @@ import info.nightscout.androidaps.utils.extensions.hexStringToByteArray
internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO) { internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO) {
fun negociateLTKAndNonce(): LTK? { fun negotiateLTKAndNonce(): LTK? {
// send SP1, SP2 // send SP1, SP2
// TODO: get this from somewhere(preferences?) // TODO: get this from somewhere(preferences?)
var seq: Byte = 1 var seq: Byte = 1

View file

@ -42,7 +42,7 @@ class PodScanner(private val logger: AAPSLogger, private val bluetoothAdapter: B
companion object { companion object {
const val SCAN_FOR_SERVICE_UUID = "00004024-0000-1000-8000-00805F9B34FB" const val SCAN_FOR_SERVICE_UUID = "00004024-0000-1000-8000-00805F9B34FB"
const val POD_ID_NOT_ACTIVATED = 4294967294L const val POD_ID_NOT_ACTIVATED = 0xFFFFFFFFL
private const val SCAN_DURATION_MS = 5000 private const val SCAN_DURATION_MS = 5000
} }
} }

View file

@ -34,7 +34,7 @@ class ScanCollector(private val logger: AAPSLogger, private val podID: Long) : S
for (result in found.values) { for (result in found.values) {
try { try {
result.scanRecord?.let { result.scanRecord?.let {
val device = BleDiscoveredDevice(result, result.scanRecord, podID) val device = BleDiscoveredDevice(result, it, podID)
ret.add(device) ret.add(device)
logger.debug(LTag.PUMPBTCOMM, "ScanCollector found: " + result.toString() + "Pod ID: " + podID) logger.debug(LTag.PUMPBTCOMM, "ScanCollector found: " + result.toString() + "Pod ID: " + podID)
} }

View file

@ -5,10 +5,17 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.
sealed class PodEvent { sealed class PodEvent {
/* BT connection events */
class AlreadyConnected(val bluetoothAddress: String, val uniqueId: Long) : PodEvent()
object Scanning : PodEvent() object Scanning : PodEvent()
object BluetoothConnecting : PodEvent()
class BluetoothConnected(val address: String) : PodEvent()
object Pairing : PodEvent() object Pairing : PodEvent()
object Connecting : PodEvent() object Paired : PodEvent()
class Connected(val uniqueId: Int) : PodEvent() object EstablishingSession : PodEvent()
class Connected(val uniqueId: Long) : PodEvent()
/* Message exchange events */
class CommandSending(val command: Command) : PodEvent() class CommandSending(val command: Command) : PodEvent()
class CommandSent(val command: Command) : PodEvent() class CommandSent(val command: Command) : PodEvent()
class ResponseReceived(val response: Response) : PodEvent() class ResponseReceived(val response: Response) : PodEvent()

View file

@ -21,8 +21,8 @@ interface OmnipodDashPodStateManager {
val messageSequenceNumber: Short val messageSequenceNumber: Short
val sequenceNumberOfLastProgrammingCommand: Short? val sequenceNumberOfLastProgrammingCommand: Short?
val activationTime: Long? val activationTime: Long?
val uniqueId: Long? var uniqueId: Long?
val bluetoothAddress: String? var bluetoothAddress: String?
val bluetoothVersion: SoftwareVersion? val bluetoothVersion: SoftwareVersion?
val firmwareVersion: SoftwareVersion? val firmwareVersion: SoftwareVersion?

View file

@ -34,8 +34,6 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
store() store()
} }
// TODO: dynamic get() fun instead of assignment
override val isUniqueIdSet: Boolean override val isUniqueIdSet: Boolean
get() = activationProgress.isAtLeast(ActivationProgress.SET_UNIQUE_ID) get() = activationProgress.isAtLeast(ActivationProgress.SET_UNIQUE_ID)
@ -68,11 +66,27 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
override val activationTime: Long? override val activationTime: Long?
get() = podState.activationTime get() = podState.activationTime
override val uniqueId: Long? override var uniqueId: Long?
get() = podState.uniqueId get() = podState.uniqueId
set(uniqueId) {
if (podState.uniqueId == null) {
podState.uniqueId = uniqueId
store()
} else if (uniqueId != podState.uniqueId) {
throw IllegalStateException("Trying to set Unique ID to $uniqueId, but it is already set to ${podState.uniqueId}")
}
}
override val bluetoothAddress: String? override var bluetoothAddress: String?
get() = podState.bluetoothAddress get() = podState.bluetoothAddress
set(bluetoothAddress) {
if (podState.bluetoothAddress == null) {
podState.bluetoothAddress = bluetoothAddress
store()
} else if (bluetoothAddress != podState.bluetoothAddress) {
throw IllegalStateException("Trying to set Bluetooth Address to $bluetoothAddress, but it is already set to ${podState.bluetoothAddress}")
}
}
override val bluetoothVersion: SoftwareVersion? override val bluetoothVersion: SoftwareVersion?
get() = podState.bleVersion get() = podState.bleVersion

View file

@ -8,11 +8,15 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel
import info.nightscout.androidaps.plugins.pump.omnipod.dash.R 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.OmnipodDashManager
import io.reactivex.Single
import io.reactivex.rxkotlin.subscribeBy
import javax.inject.Inject import javax.inject.Inject
class DashInitializePodViewModel @Inject constructor(private val aapsLogger: AAPSLogger, class DashInitializePodViewModel @Inject constructor(
private val injector: HasAndroidInjector, private val omnipodManager: OmnipodDashManager,
private val omnipodManager: OmnipodDashManager) : InitializePodViewModel() { injector: HasAndroidInjector,
logger: AAPSLogger
) : InitializePodViewModel(injector, logger) {
override fun isPodInAlarm(): Boolean = false // TODO override fun isPodInAlarm(): Boolean = false // TODO
@ -20,16 +24,20 @@ class DashInitializePodViewModel @Inject constructor(private val aapsLogger: AAP
override fun isPodDeactivatable(): Boolean = true // TODO override fun isPodDeactivatable(): Boolean = true // TODO
override fun doExecuteAction(): PumpEnactResult { override fun doExecuteAction(): Single<PumpEnactResult> =
// TODO FIRST STEP OF ACTIVATION Single.create { source ->
val disposable = omnipodManager.activatePodPart1().subscribe( val disposable = omnipodManager.activatePodPart1().subscribeBy(
{ podEvent -> aapsLogger.debug(LTag.PUMP, "Received PodEvent in Pod activation part 1: $podEvent") }, onNext = { podEvent -> logger.debug(LTag.PUMP, "Received PodEvent in Pod activation part 1: $podEvent") },
{ throwable -> aapsLogger.error(LTag.PUMP, "Error in Pod activation part 1: $throwable") }, onError = { throwable ->
{ aapsLogger.debug("Pod activation part 1 completed") } logger.error(LTag.PUMP, "Error in Pod activation part 1", throwable)
) source.onSuccess(PumpEnactResult(injector).success(false).comment(throwable.message))
},
return PumpEnactResult(injector).success(false).comment("not implemented") onComplete = {
} logger.debug("Pod activation part 1 completed")
source.onSuccess(PumpEnactResult(injector).success(true))
}
)
}
@StringRes @StringRes
override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_initialize_pod_title override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_initialize_pod_title

View file

@ -4,11 +4,17 @@ import androidx.annotation.StringRes
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel 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.R
import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
class DashInsertCannulaViewModel @Inject constructor(private val injector: HasAndroidInjector, private val profileFunction: ProfileFunction) : InsertCannulaViewModel() { class DashInsertCannulaViewModel @Inject constructor(
private val profileFunction: ProfileFunction,
injector: HasAndroidInjector,
logger: AAPSLogger
) : InsertCannulaViewModel(injector, logger) {
override fun isPodInAlarm(): Boolean = false // TODO override fun isPodInAlarm(): Boolean = false // TODO
@ -16,7 +22,7 @@ class DashInsertCannulaViewModel @Inject constructor(private val injector: HasAn
override fun isPodDeactivatable(): Boolean = true // TODO override fun isPodDeactivatable(): Boolean = true // TODO
override fun doExecuteAction(): PumpEnactResult = PumpEnactResult(injector) // TODO override fun doExecuteAction(): Single<PumpEnactResult> = Single.just(PumpEnactResult(injector).success(false).comment("TODO")) // TODO
@StringRes @StringRes
override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_insert_cannula_title override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_insert_cannula_title

View file

@ -3,13 +3,18 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.deactivat
import androidx.annotation.StringRes import androidx.annotation.StringRes
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.common.R import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.action.DeactivatePodViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.action.DeactivatePodViewModel
import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
class DashDeactivatePodViewModel @Inject constructor(private val injector: HasAndroidInjector) : DeactivatePodViewModel() { class DashDeactivatePodViewModel @Inject constructor(
injector: HasAndroidInjector,
logger: AAPSLogger
) : DeactivatePodViewModel(injector, logger) {
override fun doExecuteAction(): PumpEnactResult = PumpEnactResult(injector) // TODO override fun doExecuteAction(): Single<PumpEnactResult> = Single.just(PumpEnactResult(injector).success(false).comment("TODO")) // TODO
override fun discardPod() { override fun discardPod() {
// TODO // TODO

View file

@ -1,15 +1,23 @@
package info.nightscout.androidaps.plugins.pump.omnipod.eros.ui.wizard.activation.viewmodel.action package info.nightscout.androidaps.plugins.pump.omnipod.eros.ui.wizard.activation.viewmodel.action
import androidx.annotation.StringRes import androidx.annotation.StringRes
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel
import info.nightscout.androidaps.plugins.pump.omnipod.eros.R import info.nightscout.androidaps.plugins.pump.omnipod.eros.R
import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.ActivationProgress
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsErosPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsErosPodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodErosManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodErosManager
import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
class ErosInitializePodViewModel @Inject constructor(private val aapsOmnipodManager: AapsOmnipodErosManager, private val podStateManager: AapsErosPodStateManager) : InitializePodViewModel() { class ErosInitializePodViewModel @Inject constructor(
private val aapsOmnipodManager: AapsOmnipodErosManager,
private val podStateManager: AapsErosPodStateManager,
injector: HasAndroidInjector,
logger: AAPSLogger
) : InitializePodViewModel(injector, logger) {
override fun isPodInAlarm(): Boolean = podStateManager.isPodFaulted override fun isPodInAlarm(): Boolean = podStateManager.isPodFaulted
@ -17,7 +25,7 @@ class ErosInitializePodViewModel @Inject constructor(private val aapsOmnipodMana
override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED) override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED)
override fun doExecuteAction(): PumpEnactResult = aapsOmnipodManager.initializePod() override fun doExecuteAction(): Single<PumpEnactResult> = Single.just(aapsOmnipodManager.initializePod())
@StringRes @StringRes
override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_initialize_pod_title override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_initialize_pod_title

View file

@ -1,16 +1,25 @@
package info.nightscout.androidaps.plugins.pump.omnipod.eros.ui.wizard.activation.viewmodel.action package info.nightscout.androidaps.plugins.pump.omnipod.eros.ui.wizard.activation.viewmodel.action
import androidx.annotation.StringRes import androidx.annotation.StringRes
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel
import info.nightscout.androidaps.plugins.pump.omnipod.eros.R import info.nightscout.androidaps.plugins.pump.omnipod.eros.R
import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.ActivationProgress
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsErosPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsErosPodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodErosManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodErosManager
import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
class ErosInsertCannulaViewModel @Inject constructor(private val aapsOmnipodManager: AapsOmnipodErosManager, private val podStateManager: AapsErosPodStateManager, private val profileFunction: ProfileFunction) : InsertCannulaViewModel() { class ErosInsertCannulaViewModel @Inject constructor(
private val aapsOmnipodManager: AapsOmnipodErosManager,
private val podStateManager: AapsErosPodStateManager,
private val profileFunction: ProfileFunction,
injector: HasAndroidInjector,
logger: AAPSLogger
) : InsertCannulaViewModel(injector, logger) {
override fun isPodInAlarm(): Boolean = podStateManager.isPodFaulted override fun isPodInAlarm(): Boolean = podStateManager.isPodFaulted
@ -18,7 +27,7 @@ class ErosInsertCannulaViewModel @Inject constructor(private val aapsOmnipodMana
override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED) override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED)
override fun doExecuteAction(): PumpEnactResult = aapsOmnipodManager.insertCannula(profileFunction.getProfile()) override fun doExecuteAction(): Single<PumpEnactResult> = Single.just(aapsOmnipodManager.insertCannula(profileFunction.getProfile()))
@StringRes @StringRes
override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_insert_cannula_title override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_insert_cannula_title

View file

@ -1,27 +1,33 @@
package info.nightscout.androidaps.plugins.pump.omnipod.eros.ui.wizard.deactivation.viewmodel.action package info.nightscout.androidaps.plugins.pump.omnipod.eros.ui.wizard.deactivation.viewmodel.action
import androidx.annotation.StringRes import androidx.annotation.StringRes
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.common.R import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandDeactivatePod import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandDeactivatePod
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.action.DeactivatePodViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.action.DeactivatePodViewModel
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodErosManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodErosManager
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import io.reactivex.subjects.SingleSubject import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
class ErosDeactivatePodViewModel @Inject constructor(private val aapsOmnipodManager: AapsOmnipodErosManager, private val commandQueueProvider: CommandQueueProvider) : DeactivatePodViewModel() { class ErosDeactivatePodViewModel @Inject constructor(
private val aapsOmnipodManager: AapsOmnipodErosManager,
private val commandQueueProvider: CommandQueueProvider,
injector: HasAndroidInjector,
logger: AAPSLogger
) : DeactivatePodViewModel(injector, logger) {
override fun doExecuteAction(): PumpEnactResult { override fun doExecuteAction(): Single<PumpEnactResult> =
val singleSubject = SingleSubject.create<PumpEnactResult>() Single.create { source ->
commandQueueProvider.customCommand(CommandDeactivatePod(), object : Callback() { commandQueueProvider.customCommand(CommandDeactivatePod(), object : Callback() {
override fun run() { override fun run() {
singleSubject.onSuccess(result) source.onSuccess(result)
} }
}) })
return singleSubject.blockingGet() }
}
override fun discardPod() { override fun discardPod() {
aapsOmnipodManager.discardPodState() aapsOmnipodManager.discardPodState()