From bf26f7293ac97bcd22eb353c81bb3e904672d28b Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 23 Jan 2020 23:05:15 -0800 Subject: [PATCH] my now fixed nice bluetooth api works well --- app/build.gradle | 3 +- .../geeksville/mesh/SoftwareUpdateService.kt | 8 +--- .../geeksville/mesh/SyncBluetoothDevice.kt | 39 +++++++++---------- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d1084b97..92fa3ff6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -88,7 +88,8 @@ dependencies { // Add the Firebase SDK for Crashlytics. implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta01' - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3" + // alas implementation bug deep in the bowels when I tried it for my SyncBluetoothDevice class + // implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3" // add SDKs for any other desired Firebase products // https://firebase.google.com/docs/android/setup#available-libraries diff --git a/app/src/main/java/com/geeksville/mesh/SoftwareUpdateService.kt b/app/src/main/java/com/geeksville/mesh/SoftwareUpdateService.kt index d1c1e6a6..338224c1 100644 --- a/app/src/main/java/com/geeksville/mesh/SoftwareUpdateService.kt +++ b/app/src/main/java/com/geeksville/mesh/SoftwareUpdateService.kt @@ -10,12 +10,10 @@ import android.os.SystemClock import android.widget.Toast import androidx.core.app.JobIntentService import com.geeksville.android.Logging -import kotlinx.coroutines.* import java.io.IOException import java.io.InputStream import java.util.* import java.util.zip.CRC32 -import kotlin.coroutines.* /** * typical flow @@ -29,7 +27,7 @@ import kotlin.coroutines.* * FIXME - broadcast when we found devices, made progress sending blocks or when the update is complete * FIXME - make the user decide to start an update on a particular device */ -class SoftwareUpdateService : JobIntentService(), Logging, CoroutineScope by MainScope() { +class SoftwareUpdateService : JobIntentService(), Logging { private val bluetoothAdapter: BluetoothAdapter by lazy(LazyThreadSafetyMode.NONE) { val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager @@ -41,8 +39,6 @@ class SoftwareUpdateService : JobIntentService(), Logging, CoroutineScope by Mai fun startUpdate() { info("starting update") - // FIXME, is this the right scope to use? I want it to block in the job queue - launch { val sync = SyncBluetoothDevice(this@SoftwareUpdateService, device) val firmwareStream = assets.open("firmware.bin") @@ -110,7 +106,6 @@ class SoftwareUpdateService : JobIntentService(), Logging, CoroutineScope by Mai logAssert(updateResult == 0) // FIXME - handle this case // FIXME perhaps ask device to reboot - } } @@ -192,7 +187,6 @@ class SoftwareUpdateService : JobIntentService(), Logging, CoroutineScope by Mai } override fun onDestroy() { - cancel() // Stop the CoroutineScope super.onDestroy() // toast("All work complete") } diff --git a/app/src/main/java/com/geeksville/mesh/SyncBluetoothDevice.kt b/app/src/main/java/com/geeksville/mesh/SyncBluetoothDevice.kt index d3d7edc6..68012181 100644 --- a/app/src/main/java/com/geeksville/mesh/SyncBluetoothDevice.kt +++ b/app/src/main/java/com/geeksville/mesh/SyncBluetoothDevice.kt @@ -4,10 +4,8 @@ import android.bluetooth.* import android.content.Context import com.geeksville.android.Logging import java.io.IOException -import kotlin.coroutines.Continuation -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException -import kotlin.coroutines.suspendCoroutine +import com.geeksville.concurrent.SyncContinuation +import com.geeksville.concurrent.suspend /** @@ -19,13 +17,14 @@ import kotlin.coroutines.suspendCoroutine * * This class fixes the API by using coroutines to let you safely do a series of BTLE operations. */ -class SyncBluetoothDevice(private val context: Context, private val device: BluetoothDevice) : Logging { +class SyncBluetoothDevice(private val context: Context, private val device: BluetoothDevice) : + Logging { - private var pendingServiceDesc: Continuation? = null - private var pendingMtu: Continuation? = null - private var pendingWriteC: Continuation? = null - private var pendingReadC: Continuation? = null - private var pendingConnect: Continuation? = null + private var pendingServiceDesc: SyncContinuation? = null + private var pendingMtu: SyncContinuation? = null + private var pendingWriteC: SyncContinuation? = null + private var pendingReadC: SyncContinuation? = null + private var pendingConnect: SyncContinuation? = null private val gattCallback = object : BluetoothGattCallback() { @@ -37,7 +36,7 @@ class SyncBluetoothDevice(private val context: Context, private val device: Blue info("new bluetooth connection state $newState") when (newState) { BluetoothProfile.STATE_CONNECTED -> { - if(pendingConnect != null) { // If someone was waiting to connect unblock them + if (pendingConnect != null) { // If someone was waiting to connect unblock them pendingConnect!!.resume(Unit) pendingConnect = null } @@ -91,32 +90,32 @@ class SyncBluetoothDevice(private val context: Context, private val device: Blue /// Users can access the GATT directly as needed lateinit var gatt: BluetoothGatt - suspend fun connect() = - suspendCoroutine { cont -> + fun connect() = + suspend { cont -> pendingConnect = cont gatt = device.connectGatt(context, false, gattCallback)!! } - suspend fun discoverServices() = - suspendCoroutine { cont -> + fun discoverServices() = + suspend { cont -> pendingServiceDesc = cont logAssert(gatt.discoverServices()) } /// Returns the actual MTU size used - suspend fun requestMtu(len: Int): kotlin.Int = suspendCoroutine { cont -> + fun requestMtu(len: Int) = suspend { cont -> pendingMtu = cont logAssert(gatt.requestMtu(len)) } - suspend fun writeCharacteristic(c: BluetoothGattCharacteristic) = - suspendCoroutine { cont -> + fun writeCharacteristic(c: BluetoothGattCharacteristic) = + suspend { cont -> pendingWriteC = cont logAssert(gatt.writeCharacteristic(c)) } - suspend fun readCharacteristic(c: BluetoothGattCharacteristic) = - suspendCoroutine { cont -> + fun readCharacteristic(c: BluetoothGattCharacteristic) = + suspend { cont -> pendingReadC = cont logAssert(gatt.readCharacteristic(c)) }