Skip to content

Commit

Permalink
Optimize observation handling (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
twyatt authored Jan 18, 2022
1 parent 1584c60 commit 3597853
Show file tree
Hide file tree
Showing 19 changed files with 774 additions and 460 deletions.
12 changes: 8 additions & 4 deletions core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public final class com/juul/kable/AndroidPeripheral : com/juul/kable/Peripheral
public fun disconnect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getMtu ()Lkotlinx/coroutines/flow/StateFlow;
public fun getServices ()Ljava/util/List;
public fun getState ()Lkotlinx/coroutines/flow/Flow;
public fun getState ()Lkotlinx/coroutines/flow/StateFlow;
public fun observe (Lcom/juul/kable/Characteristic;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow;
public fun read (Lcom/juul/kable/Characteristic;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun read (Lcom/juul/kable/Descriptor;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down Expand Up @@ -58,7 +58,7 @@ public final class com/juul/kable/CharacteristicKt {
public static final fun characteristicOf (Ljava/lang/String;Ljava/lang/String;)Lcom/juul/kable/Characteristic;
}

public final class com/juul/kable/ConnectionLostException : java/io/IOException {
public final class com/juul/kable/ConnectionLostException : com/juul/kable/NotConnectedException {
public fun <init> ()V
}

Expand Down Expand Up @@ -169,7 +169,11 @@ public final class com/juul/kable/ManufacturerData {
public final fun getData ()[B
}

public final class com/juul/kable/NotReadyException : java/io/IOException {
public class com/juul/kable/NotConnectedException : java/io/IOException {
public fun <init> ()V
}

public final class com/juul/kable/NotReadyException : com/juul/kable/NotConnectedException {
public fun <init> ()V
}

Expand All @@ -183,7 +187,7 @@ public abstract interface class com/juul/kable/Peripheral {
public abstract fun connect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun disconnect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getServices ()Ljava/util/List;
public abstract fun getState ()Lkotlinx/coroutines/flow/Flow;
public abstract fun getState ()Lkotlinx/coroutines/flow/StateFlow;
public abstract fun observe (Lcom/juul/kable/Characteristic;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow;
public abstract fun read (Lcom/juul/kable/Characteristic;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun read (Lcom/juul/kable/Descriptor;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down
7 changes: 4 additions & 3 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ kotlin {
dependencies {
api(libs.kotlinx.coroutines.core)
api(libs.uuid)
implementation(libs.tuulbox.collections)
implementation(libs.stately.collections)
}
}

val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(libs.tuulbox.logging)
implementation(libs.kotlinx.coroutines.test)
}
}

Expand Down Expand Up @@ -72,9 +76,6 @@ kotlin {

val appleMain by creating {
dependsOn(commonMain)
dependencies {
implementation(libs.stately)
}
}

val appleTest by creating
Expand Down
2 changes: 1 addition & 1 deletion core/src/androidMain/kotlin/Connection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.juul.kable

import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGatt.GATT_SUCCESS
import com.juul.kable.AndroidObservationEvent.CharacteristicChange
import com.juul.kable.ObservationEvent.CharacteristicChange
import com.juul.kable.gatt.Callback
import com.juul.kable.gatt.GattStatus
import kotlinx.coroutines.CoroutineDispatcher
Expand Down
11 changes: 11 additions & 0 deletions core/src/androidMain/kotlin/Observations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.juul.kable

internal actual fun Peripheral.observationHandler(): Observation.Handler = object : Observation.Handler {
override suspend fun startObservation(characteristic: Characteristic) {
(this@observationHandler as AndroidPeripheral).startObservation(characteristic)
}

override suspend fun stopObservation(characteristic: Characteristic) {
(this@observationHandler as AndroidPeripheral).stopObservation(characteristic)
}
}
153 changes: 0 additions & 153 deletions core/src/androidMain/kotlin/Observers.kt

This file was deleted.

33 changes: 18 additions & 15 deletions core/src/androidMain/kotlin/Peripheral.kt
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public enum class Priority { Low, Balanced, High }

public class AndroidPeripheral internal constructor(
parentCoroutineContext: CoroutineContext,
internal val bluetoothDevice: BluetoothDevice,
private val bluetoothDevice: BluetoothDevice,
private val transport: Transport,
private val phy: Phy,
private val onServicesDiscovered: ServicesDiscoveredAction,
Expand All @@ -136,8 +136,10 @@ public class AndroidPeripheral internal constructor(

private val logger = Logger(logging, tag = "Kable/Peripheral", identifier = bluetoothDevice.address)

internal val platformIdentifier = bluetoothDevice.address

private val _state = MutableStateFlow<State>(State.Disconnected())
public override val state: Flow<State> = _state.asStateFlow()
public override val state: StateFlow<State> = _state.asStateFlow()

private val receiver = registerBluetoothStateBroadcastReceiver { state ->
if (state == STATE_OFF) {
Expand Down Expand Up @@ -166,7 +168,7 @@ public class AndroidPeripheral internal constructor(
*/
public val mtu: StateFlow<Int?> = _mtu.asStateFlow()

private val observers = Observers(this, logging)
private val observers = Observers<ByteArray>(this, logging)

@Volatile
private var _platformServices: List<PlatformService>? = null
Expand Down Expand Up @@ -212,7 +214,7 @@ public class AndroidPeripheral internal constructor(
onServicesDiscovered(ServicesDiscoveredPeripheral(this@AndroidPeripheral))
_state.value = State.Connecting.Observes
logger.verbose { message = "Configuring characteristic observations" }
observers.rewire()
observers.onConnected()
} catch (t: Throwable) {
closeConnection()
logger.error(t) { message = "Failed to connect" }
Expand All @@ -226,6 +228,7 @@ public class AndroidPeripheral internal constructor(
private fun closeConnection() {
_connection?.close()
_connection = null

// Avoid trampling existing `Disconnected` state (and its properties) by only updating if not already `Disconnected`.
_state.update { previous -> previous as? State.Disconnected ?: State.Disconnected() }
}
Expand Down Expand Up @@ -381,19 +384,16 @@ public class AndroidPeripheral internal constructor(

internal suspend fun stopObservation(characteristic: Characteristic) {
val platformCharacteristic = platformServices.findCharacteristic(characteristic)
setConfigDescriptor(platformCharacteristic, enable = false)

try {
setConfigDescriptor(platformCharacteristic, enable = false)
} finally {
logger.debug {
message = "setCharacteristicNotification"
detail(characteristic)
detail("value", "false")
}
connection
.bluetoothGatt
.setCharacteristicNotification(platformCharacteristic, false)
logger.debug {
message = "setCharacteristicNotification"
detail(characteristic)
detail("value", "false")
}
connection
.bluetoothGatt
.setCharacteristicNotification(platformCharacteristic, false)
}

private suspend fun setConfigDescriptor(
Expand Down Expand Up @@ -506,3 +506,6 @@ private fun checkBluetoothAdapterState(
throw BluetoothDisabledException("Bluetooth adapter state is $actualName ($actual), but $expectedName ($expected) was required.")
}
}

internal actual val Peripheral.identifier: String
get() = (this as AndroidPeripheral).platformIdentifier
11 changes: 11 additions & 0 deletions core/src/appleMain/kotlin/Observations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.juul.kable

internal actual fun Peripheral.observationHandler(): Observation.Handler = object : Observation.Handler {
override suspend fun startObservation(characteristic: Characteristic) {
(this@observationHandler as ApplePeripheral).startNotifications(characteristic)
}

override suspend fun stopObservation(characteristic: Characteristic) {
(this@observationHandler as ApplePeripheral).stopNotifications(characteristic)
}
}
Loading

0 comments on commit 3597853

Please sign in to comment.