diff --git a/app/src/main/java/com/geeksville/mesh/RadioInterfaceService.kt b/app/src/main/java/com/geeksville/mesh/RadioInterfaceService.kt index 4e84fc92d..908a91845 100644 --- a/app/src/main/java/com/geeksville/mesh/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/RadioInterfaceService.kt @@ -178,11 +178,13 @@ class RadioInterfaceService : Service(), Logging { // FIXME - no need to discover services, instead just hardwire the characteristics (like we do for toRadio) safe.asyncDiscoverServices { discRes -> discRes.getOrThrow() // FIXME, instead just try to reconnect? + debug("Discovered services!") // we begin by setting our MTU size as high as it can go safe.asyncRequestMtu(512) { mtuRes -> + debug("requested MTU result=$mtuRes") mtuRes.getOrThrow() - + fromRadio = service.getCharacteristic(BTM_FROMRADIO_CHARACTER) fromNum = service.getCharacteristic(BTM_FROMNUM_CHARACTER) @@ -197,6 +199,7 @@ class RadioInterfaceService : Service(), Logging { override fun onDestroy() { info("Destroying radio interface service") sentPacketsLog.close() + safe.disconnect() super.onDestroy() } @@ -217,9 +220,12 @@ class RadioInterfaceService : Service(), Logging { ) toRadio.value = a - safe.asyncWriteCharacteristic(toRadio) { - it.getOrThrow() // FIXME, handle the error better - } + if (true) + safe.asyncWriteCharacteristic(toRadio) { + it.getOrThrow() // FIXME, handle the error better + } + else + error("FIXME ignoring writes for now - because they slide in before discovery - bad bad") } } } \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/SafeBluetooth.kt b/app/src/main/java/com/geeksville/mesh/SafeBluetooth.kt index fff232e55..aeb8fe766 100644 --- a/app/src/main/java/com/geeksville/mesh/SafeBluetooth.kt +++ b/app/src/main/java/com/geeksville/mesh/SafeBluetooth.kt @@ -35,13 +35,17 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD * a schedulable bit of bluetooth work, includes both the closure to call to start the operation * and the completion (either async or sync) to call when it completes */ - class BluetoothContinuation( + private class BluetoothContinuation( + val tag: String, val completion: com.geeksville.concurrent.Continuation<*>, - private val startWorkFn: () -> Boolean - ) { + val startWorkFn: () -> Boolean + ) : Logging { /// Start running a queued bit of work, return true for success or false for fatal bluetooth error - fun startWork() = startWorkFn() + fun startWork(): Boolean { + debug("Starting work: $tag") + return startWorkFn() + } } private val gattCallback = object : BluetoothGattCallback() { @@ -99,14 +103,15 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD if (workQueue.isNotEmpty()) { val newWork = workQueue.removeAt(0) currentWork = newWork - newWork.startWork() + logAssert(newWork.startWork()) } } - private fun queueWork(cont: Continuation, initFn: () -> Boolean) { - val btCont = BluetoothContinuation(cont, initFn) + private fun queueWork(tag: String, cont: Continuation, initFn: () -> Boolean) { + val btCont = BluetoothContinuation(tag, cont, initFn) synchronized(workQueue) { + debug("Enqueuing work: ${btCont.tag}") workQueue.add(btCont) // if we don't have any outstanding operations, run first item in queue @@ -161,7 +166,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD // more info. // Otherwise if you pass in false, it will try to connect now and will timeout and fail in 30 seconds. private fun queueConnect(autoConnect: Boolean = false, cont: Continuation) { - queueWork(cont) { + queueWork("connect", cont) { val g = device.connectGatt(context, autoConnect, gattCallback) if (g != null) gatt = g @@ -170,6 +175,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD } fun asyncConnect(autoConnect: Boolean = false, cb: (Result) -> Unit) { + logAssert(workQueue.isEmpty() && currentWork == null) // I don't think anything should be able to sneak in front queueConnect(autoConnect, CallbackContinuation(cb)) } @@ -178,7 +184,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD private fun queueReadCharacteristic( c: BluetoothGattCharacteristic, cont: Continuation - ) = queueWork(cont) { gatt.readCharacteristic(c) } + ) = queueWork("readc", cont) { gatt.readCharacteristic(c) } fun asyncReadCharacteristic( c: BluetoothGattCharacteristic, @@ -189,12 +195,13 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD makeSync { queueReadCharacteristic(c, it) } private fun queueDiscoverServices(cont: Continuation) { - queueWork(cont) { + queueWork("discover", cont) { gatt.discoverServices() } } fun asyncDiscoverServices(cb: (Result) -> Unit) { + logAssert(workQueue.isEmpty() && currentWork == null) // I don't think anything should be able to sneak in front queueDiscoverServices(CallbackContinuation(cb)) } @@ -203,12 +210,15 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD private fun queueRequestMtu( len: Int, cont: Continuation - ) = queueWork(cont) { gatt.requestMtu(len) } + ) = queueWork("reqMtu", cont) { gatt.requestMtu(len) } fun asyncRequestMtu( len: Int, cb: (Result) -> Unit - ) = queueRequestMtu(len, CallbackContinuation(cb)) + ) { + logAssert(workQueue.isEmpty() && currentWork == null) // I don't think anything should be able to sneak in front + queueRequestMtu(len, CallbackContinuation(cb)) + } fun requestMtu(len: Int): Int = makeSync { queueRequestMtu(len, it) } @@ -216,7 +226,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD private fun queueWriteCharacteristic( c: BluetoothGattCharacteristic, cont: Continuation - ) = queueWork(cont) { gatt.writeCharacteristic(c) } + ) = queueWork("writec", cont) { gatt.writeCharacteristic(c) } fun asyncWriteCharacteristic( c: BluetoothGattCharacteristic, @@ -228,5 +238,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD fun disconnect() { gatt.disconnect() + failAllWork(Exception("SafeBluetooth disconnected")) } } +