Skip to content

Commit

Permalink
Add maximumWriteValueLength to Peripheral (#809)
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikHellman authored Dec 6, 2024
1 parent 64f054e commit 1fce4e2
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 0 deletions.
1 change: 1 addition & 0 deletions kable-core/api/android/kable-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ public abstract interface class com/juul/kable/Peripheral : kotlinx/coroutines/C
public abstract fun getName ()Ljava/lang/String;
public abstract fun getServices ()Lkotlinx/coroutines/flow/StateFlow;
public abstract fun getState ()Lkotlinx/coroutines/flow/StateFlow;
public abstract fun maximumWriteValueLengthForType (Lcom/juul/kable/WriteType;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
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
1 change: 1 addition & 0 deletions kable-core/api/jvm/kable-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ public abstract interface class com/juul/kable/Peripheral : kotlinx/coroutines/C
public abstract fun getName ()Ljava/lang/String;
public abstract fun getServices ()Lkotlinx/coroutines/flow/StateFlow;
public abstract fun getState ()Lkotlinx/coroutines/flow/StateFlow;
public abstract fun maximumWriteValueLengthForType (Lcom/juul/kable/WriteType;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
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
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ import kotlin.time.Duration
// https://github.com/JuulLabs/kable/issues/295
private const val DISCOVER_SERVICES_RETRIES = 5

private const val DEFAULT_ATT_MTU = 23
private const val ATT_MTU_HEADER_SIZE = 3

internal class BluetoothDeviceAndroidPeripheral(
private val bluetoothDevice: BluetoothDevice,
private val autoConnectPredicate: () -> Boolean,
Expand Down Expand Up @@ -163,6 +166,9 @@ internal class BluetoothDeviceAndroidPeripheral(
.requestConnectionPriority(priority.intValue)
}

override suspend fun maximumWriteValueLengthForType(writeType: WriteType): Int =
(mtu.value ?: DEFAULT_ATT_MTU) - ATT_MTU_HEADER_SIZE

@ExperimentalApi // Experimental until Web Bluetooth advertisements APIs are stable.
override suspend fun rssi(): Int =
connectionOrThrow().execute<OnReadRemoteRssi> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import kotlinx.coroutines.flow.onSubscription
import kotlinx.coroutines.flow.updateAndGet
import kotlinx.coroutines.sync.withLock
import kotlinx.io.IOException
import platform.CoreBluetooth.CBCharacteristicWriteWithResponse
import platform.CoreBluetooth.CBCharacteristicWriteWithoutResponse
import platform.CoreBluetooth.CBDescriptor
import platform.CoreBluetooth.CBManagerState
import platform.CoreBluetooth.CBManagerStatePoweredOn
Expand Down Expand Up @@ -144,6 +146,14 @@ internal class CBPeripheralCoreBluetoothPeripheral(
)
}

override suspend fun maximumWriteValueLengthForType(writeType: WriteType): Int {
val type = when (writeType) {
WithResponse -> CBCharacteristicWriteWithResponse
WithoutResponse -> CBCharacteristicWriteWithoutResponse
}
return cbPeripheral.maximumWriteValueLengthForType(type).toInt()
}

@ExperimentalApi // Experimental until Web Bluetooth advertisements APIs are stable.
@Throws(CancellationException::class, IOException::class)
override suspend fun rssi(): Int = connectionOrThrow().execute<DidReadRssi> {
Expand Down
9 changes: 9 additions & 0 deletions kable-core/src/commonMain/kotlin/Peripheral.kt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ public interface Peripheral : CoroutineScope {
*/
public val services: StateFlow<List<DiscoveredService>?>

/**
* Return the current ATT MTU size, minus the size of the ATT headers (3 bytes).
*
* On Android, this will be the default (23 - 3) unless you called [requestMtu] when connecting.
* For iOS, this is automatically negotiated, and can also vary depending on the writeType.
* On JavaScript, this will return the default (23 - 3) every time as there is no ATT MTU property available.
*/
public suspend fun maximumWriteValueLengthForType(writeType: WriteType): Int

/**
* On JavaScript, requires Chrome 79+ with the
* `chrome://flags/#enable-experimental-web-platform-features` flag enabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import kotlin.coroutines.resumeWithException
import kotlin.time.Duration

private const val ADVERTISEMENT_RECEIVED = "advertisementreceived"
private const val DEFAULT_ATT_MTU = 23
private const val ATT_MTU_HEADER_SIZE = 3

internal class BluetoothDeviceWebBluetoothPeripheral(
private val bluetoothDevice: BluetoothDevice,
Expand Down Expand Up @@ -114,6 +116,9 @@ internal class BluetoothDeviceWebBluetoothPeripheral(
)
}

override suspend fun maximumWriteValueLengthForType(writeType: WriteType): Int =
DEFAULT_ATT_MTU - ATT_MTU_HEADER_SIZE

/**
* Per [Web Bluetooth / Scanning Sample][https://googlechrome.github.io/samples/web-bluetooth/scan.html]:
*
Expand Down

0 comments on commit 1fce4e2

Please sign in to comment.