refactor(transport): complete transport architecture overhaul — extract callback, wire BleReconnectPolicy, fix safety issues (#5080)

This commit is contained in:
James Rich 2026-04-11 23:22:18 -05:00 committed by GitHub
parent 962c619c4c
commit e85300531e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
64 changed files with 1184 additions and 1018 deletions

View file

@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
@ -86,7 +87,7 @@ class AndroidBluetoothRepository(
return
}
kotlinx.coroutines.suspendCancellableCoroutine<Unit> { cont ->
suspendCancellableCoroutine<Unit> { cont ->
val receiver =
object : android.content.BroadcastReceiver() {
@SuppressLint("MissingPermission")

View file

@ -87,7 +87,7 @@ class KableBleService(private val peripheral: Peripheral, private val serviceUui
*
* Connection attempts follow Kable's recommended pattern from the SensorTag sample: try a direct connect first, then
* fall back to `autoConnect = true` on failure. Only two attempts are made per [connect] call the caller
* ([BleRadioInterface]) owns the macro-level retry/backoff loop.
* ([BleRadioTransport]) owns the macro-level retry/backoff loop.
*/
class KableBleConnection(private val scope: CoroutineScope) : BleConnection {

View file

@ -17,6 +17,7 @@
package org.meshtastic.core.ble
import com.juul.kable.Advertisement
import com.juul.kable.ExperimentalApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@ -47,7 +48,7 @@ class MeshtasticBleDevice(
override val isConnected: Boolean
get() = _state.value is BleConnectionState.Connected || ActiveBleConnection.active?.address == address
@OptIn(com.juul.kable.ExperimentalApi::class)
@OptIn(ExperimentalApi::class)
override suspend fun readRssi(): Int {
val active = ActiveBleConnection.active
return if (active != null && active.address == address) {

View file

@ -18,6 +18,7 @@ package org.meshtastic.core.ble
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.advanceUntilIdle
@ -118,8 +119,8 @@ class KableMeshtasticRadioProfileTest {
fun `MeshtasticRadioProfile default awaitSubscriptionReady returns immediately`() = runTest {
val profile =
object : MeshtasticRadioProfile {
override val fromRadio = kotlinx.coroutines.flow.emptyFlow<ByteArray>()
override val logRadio = kotlinx.coroutines.flow.emptyFlow<ByteArray>()
override val fromRadio = emptyFlow<ByteArray>()
override val logRadio = emptyFlow<ByteArray>()
override suspend fun sendToRadio(packet: ByteArray) {}
}