Implement more suggestions after the switch to Kotlin

This commit is contained in:
Andrei Vereha 2021-02-25 09:31:50 +01:00
parent 2a14d60bee
commit f2fed8adc4
11 changed files with 54 additions and 41 deletions

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.*
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO
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 java.util.*
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
@ -26,7 +25,7 @@ class BleManager @Inject constructor(private val context: Context, private val a
private val bluetoothManager: BluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager private val bluetoothManager: BluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
private val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter private val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter
@Throws(InterruptedException::class, ScanFailException::class, FailedToConnectException::class, CouldNotSendBleException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::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)
fun activateNewPod() { fun activateNewPod() {
aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation") aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation")
val podScanner = PodScanner(aapsLogger, bluetoothAdapter) val podScanner = PodScanner(aapsLogger, bluetoothAdapter)
@ -35,7 +34,7 @@ class BleManager @Inject constructor(private val context: Context, private val a
connect(podAddress) connect(podAddress)
} }
@Throws(FailedToConnectException::class, CouldNotSendBleException::class, InterruptedException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) @Throws(FailedToConnectException::class, CouldNotSendBleException::class, InterruptedException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWriteException::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class)
private fun connect(podAddress: String) { private fun connect(podAddress: String) {
// TODO: locking? // TODO: locking?
val podDevice = bluetoothAdapter.getRemoteDevice(podAddress) val podDevice = bluetoothAdapter.getRemoteDevice(podAddress)
@ -61,7 +60,7 @@ class BleManager @Inject constructor(private val context: Context, private val a
val chars = discoverer.discoverServices() val chars = discoverer.discoverServices()
val bleIO = BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks) val bleIO = BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks)
aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod") aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod")
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).asByteArray()) bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).data)
bleIO.readyToRead() bleIO.readyToRead()
} }

View file

@ -10,7 +10,7 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType.Companion.byValue import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType.Companion.byValue
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWriteException
import java.util.concurrent.BlockingQueue import java.util.concurrent.BlockingQueue
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.LinkedBlockingQueue
@ -50,23 +50,21 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
serviceDiscoveryComplete.await(timeout_ms.toLong(), TimeUnit.MILLISECONDS) serviceDiscoveryComplete.await(timeout_ms.toLong(), TimeUnit.MILLISECONDS)
} }
@Throws(InterruptedException::class, TimeoutException::class, CouldNotConfirmWrite::class) @Throws(InterruptedException::class, TimeoutException::class, CouldNotConfirmWriteException::class)
fun confirmWrite(expectedPayload: ByteArray, timeout_ms: Int) { fun confirmWrite(expectedPayload: ByteArray, timeout_ms: Int) {
val received: CharacteristicWriteConfirmation = writeQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS) val received: CharacteristicWriteConfirmation = writeQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS)
?: throw TimeoutException() ?: throw TimeoutException()
when (received) { when (received) {
is CharacteristicWriteConfirmationPayload -> confirmWritePayload(expectedPayload, received) is CharacteristicWriteConfirmationPayload -> confirmWritePayload(expectedPayload, received)
is CharacteristicWriteConfirmationError -> is CharacteristicWriteConfirmationError -> throw CouldNotConfirmWriteException(received.status)
aapsLogger.debug(LTag.PUMPBTCOMM, "Could not confirm write: status was ${received.status}")
} }
} }
private fun confirmWritePayload(expectedPayload: ByteArray, received: CharacteristicWriteConfirmationPayload) { private fun confirmWritePayload(expectedPayload: ByteArray, received: CharacteristicWriteConfirmationPayload) {
if (!expectedPayload.contentEquals(received.payload)) { if (!expectedPayload.contentEquals(received.payload)) {
aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload + ". Status: " + received.status) aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload)
throw CouldNotConfirmWrite(expectedPayload, received.payload) throw CouldNotConfirmWriteException(expectedPayload, received.payload)
} }
aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed write with value: " + received.payload) aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed write with value: " + received.payload)
} }
@ -74,8 +72,7 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
super.onCharacteristicWrite(gatt, characteristic, status) super.onCharacteristicWrite(gatt, characteristic, status)
val writeConfirmation = if (status == BluetoothGatt.GATT_SUCCESS) { val writeConfirmation = if (status == BluetoothGatt.GATT_SUCCESS) {
aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite value " + characteristic.getStringValue(0)) CharacteristicWriteConfirmationPayload(characteristic.value)
CharacteristicWriteConfirmationPayload(characteristic.value, status)
} else { } else {
CharacteristicWriteConfirmationError(status) CharacteristicWriteConfirmationError(status)
} }
@ -107,26 +104,33 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
@Throws(InterruptedException::class, CouldNotConfirmDescriptorWriteException::class) @Throws(InterruptedException::class, CouldNotConfirmDescriptorWriteException::class)
fun confirmWriteDescriptor(descriptorUUID: String, timeout_ms: Int) { fun confirmWriteDescriptor(descriptorUUID: String, timeout_ms: Int) {
val confirmed = descriptorWriteQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS) val confirmed: DescriptorWriteConfirmation = descriptorWriteQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS)
if (descriptorUUID != confirmed.uuid) { ?: throw TimeoutException()
aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got " + confirmed.uuid + ".Expected: " + descriptorUUID + ". Status: " + confirmed.status) when (confirmed) {
throw CouldNotConfirmDescriptorWriteException(confirmed.uuid!!, descriptorUUID) is DescriptorWriteConfirmationError -> throw CouldNotConfirmWriteException(confirmed.status)
is DescriptorWriteConfirmationUUID -> if (confirmed.uuid != descriptorUUID) {
aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got ${confirmed.uuid}. Expected: ${descriptorUUID}")
throw CouldNotConfirmDescriptorWriteException(descriptorUUID, confirmed.uuid)
} else {
aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed descriptor write : " + confirmed.uuid)
}
} }
} }
override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) { override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
super.onDescriptorWrite(gatt, descriptor, status) super.onDescriptorWrite(gatt, descriptor, status)
var uuid: String? = null val writeConfirmation = if (status == BluetoothGatt.GATT_SUCCESS) {
if (status == BluetoothGatt.GATT_SUCCESS) { aapsLogger.debug(LTag.PUMPBTCOMM, "OnDescriptor value " + descriptor.value)
uuid = descriptor.uuid.toString() DescriptorWriteConfirmationUUID(descriptor.uuid.toString())
} else {
DescriptorWriteConfirmationError(status)
} }
val confirmation = DescriptorWriteConfirmation(status, uuid)
try { try {
if (descriptorWriteQueue.size > 0) { if (descriptorWriteQueue.size > 0) {
aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: " + descriptorWriteQueue.size) aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: " + descriptorWriteQueue.size)
descriptorWriteQueue.clear() descriptorWriteQueue.clear()
} }
val offered = descriptorWriteQueue.offer(confirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) val offered = descriptorWriteQueue.offer(writeConfirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS)
if (!offered) { if (!offered) {
aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed descriptor write confirmation") aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed descriptor write confirmation")
} }
@ -136,7 +140,6 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
} }
companion object { companion object {
private const val WRITE_CONFIRM_TIMEOUT_MS = 10 // the confirmation queue should be empty anyway
private const val WRITE_CONFIRM_TIMEOUT_MS = 10 // the other thread should be waiting for the exchange
} }
} }

View file

@ -2,6 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbac
sealed class CharacteristicWriteConfirmation sealed class CharacteristicWriteConfirmation
class CharacteristicWriteConfirmationPayload(val payload: ByteArray, val status: Int) : CharacteristicWriteConfirmation() data class CharacteristicWriteConfirmationPayload(val payload: ByteArray) : CharacteristicWriteConfirmation()
class CharacteristicWriteConfirmationError(val status: Int) : CharacteristicWriteConfirmation() data class CharacteristicWriteConfirmationError(val status: Int) : CharacteristicWriteConfirmation()

View file

@ -1,3 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks
class DescriptorWriteConfirmation(var status: Int, var uuid: String?) sealed class DescriptorWriteConfirmation
data class DescriptorWriteConfirmationUUID(val uuid: String): DescriptorWriteConfirmation()
data class DescriptorWriteConfirmationError(val status: Int): DescriptorWriteConfirmation()

View file

@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command
abstract class BleCommand { abstract class BleCommand {
private val data: ByteArray val data: ByteArray
constructor(type: BleCommandType) { constructor(type: BleCommandType) {
data = byteArrayOf(type.value) data = byteArrayOf(type.value)
@ -14,8 +14,4 @@ abstract class BleCommand {
data[0] = type.value data[0] = type.value
System.arraycopy(payload, 0, data, 1, payload.size) System.arraycopy(payload, 0, data, 1, payload.size)
} }
fun asByteArray(): ByteArray {
return data
}
} }

View file

@ -1,3 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
class CouldNotConfirmDescriptorWriteException(private val received: String, private val expected: String) : Exception() class CouldNotConfirmDescriptorWriteException(override val message: String?) : Exception(message) {
constructor(sent: String, confirmed: String): this("Could not confirm write. Sent: {$sent} .Received: ${confirmed}")
constructor(status: Int): this("Could not confirm write. Write status: ${status}")
}

View file

@ -1,3 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
class CouldNotConfirmWrite(private val sent: ByteArray, private val confirmed: ByteArray?) : Exception()

View file

@ -0,0 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
class CouldNotConfirmWriteException(override val message: String?) : Exception(message) {
constructor(sent: ByteArray, confirmed: ByteArray): this("Could not confirm write. Sent: {$sent} .Received: ${confirmed}")
constructor(status: Int): this("Could not confirm write. Write status: ${status}")
}

View file

@ -2,4 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.excepti
import android.os.ParcelUuid import android.os.ParcelUuid
class DiscoveredInvalidPodException(message: String, serviceUUIds: List<ParcelUuid?>) : Exception("$message service UUIDs: $serviceUUIds") class DiscoveredInvalidPodException: Exception {
constructor(message: String) : super(message) {}
constructor(message: String, serviceUUIds: List<ParcelUuid?>) : super("$message service UUIDs: $serviceUUIds"){}
}

View file

@ -41,7 +41,7 @@ class BleIO(private val aapsLogger: AAPSLogger, private val chars: Map<Character
* @param payload the data to send * @param payload the data to send
* @throws CouldNotSendBleException * @throws CouldNotSendBleException
*/ */
@Throws(CouldNotSendBleException::class, BleIOBusyException::class, InterruptedException::class, CouldNotConfirmWrite::class, TimeoutException::class) @Throws(CouldNotSendBleException::class, BleIOBusyException::class, InterruptedException::class, CouldNotConfirmWriteException::class, TimeoutException::class)
fun sendAndConfirmPacket(characteristic: CharacteristicType, payload: ByteArray) { fun sendAndConfirmPacket(characteristic: CharacteristicType, payload: ByteArray) {
synchronized(state) { synchronized(state) {
if (state != IOState.IDLE) { if (state != IOState.IDLE) {

View file

@ -8,9 +8,10 @@ class BleDiscoveredDevice(val scanResult: ScanResult, private val podID: Long) {
private val sequenceNo: Int private val sequenceNo: Int
private val lotNo: Long private val lotNo: Long
@Throws(DiscoveredInvalidPodException::class) private fun validateServiceUUIDs() { @Throws(DiscoveredInvalidPodException::class)
private fun validateServiceUUIDs() {
val scanRecord = scanResult.scanRecord val scanRecord = scanResult.scanRecord
?: throw DiscoveredInvalidPodException("Scan record is null") ?: throw DiscoveredInvalidPodException("Scan record is null");
val serviceUUIDs = scanRecord.serviceUuids val serviceUUIDs = scanRecord.serviceUuids
if (serviceUUIDs.size != 9) { if (serviceUUIDs.size != 9) {
throw DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUUIDs.size, serviceUUIDs) throw DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUUIDs.size, serviceUUIDs)
@ -26,7 +27,8 @@ class BleDiscoveredDevice(val scanResult: ScanResult, private val podID: Long) {
} }
} }
@Throws(DiscoveredInvalidPodException::class) private fun validatePodID() { @Throws(DiscoveredInvalidPodException::class)
private fun validatePodID() {
val scanRecord = scanResult.scanRecord val scanRecord = scanResult.scanRecord
val serviceUUIDs = scanRecord.serviceUuids val serviceUUIDs = scanRecord.serviceUuids
val hexPodID = extractUUID16(serviceUUIDs[3]) + extractUUID16(serviceUUIDs[4]) val hexPodID = extractUUID16(serviceUUIDs[3]) + extractUUID16(serviceUUIDs[4])