Move all BLE code into BLE service

This commit is contained in:
geeksville
2020-06-05 21:22:56 -07:00
parent 3d4be477a2
commit e99e8695fe
2 changed files with 8 additions and 87 deletions

View File

@@ -98,6 +98,13 @@ class BluetoothInterfaceService : InterfaceService() {
/// this service UUID is publically visible for scanning
val BTM_SERVICE_UUID = UUID.fromString("6ba1b218-15a8-461f-9fa8-5dcae273eafd")
val BTM_FROMRADIO_CHARACTER =
UUID.fromString("8ba2bcc2-ee02-4a55-a531-c525c5e454d5")
val BTM_TORADIO_CHARACTER =
UUID.fromString("f75c76d2-129e-4dad-a1dd-7866124401e7")
val BTM_FROMNUM_CHARACTER =
UUID.fromString("ed9da18c-a800-4f66-a670-aa7547e34453")
/// If our service is currently running, this pointer can be used to reach it (in case setBondedDeviceAddress is called)
private var runningService: BluetoothInterfaceService? = null
@@ -479,7 +486,7 @@ class BluetoothInterfaceService : InterfaceService() {
/**
* do a synchronous write operation
*/
override fun doWrite(uuid: UUID, a: ByteArray) = toRemoteExceptions {
private fun doWrite(uuid: UUID, a: ByteArray) = toRemoteExceptions {
if (!isConnected)
throw RadioNotConnectedException()
else {
@@ -501,46 +508,4 @@ class BluetoothInterfaceService : InterfaceService() {
private fun getCharacteristic(uuid: UUID) =
service.getCharacteristic(uuid) ?: throw BLEException("Can't get characteristic $uuid")
/**
* do an asynchronous write operation
* Any error responses will be ignored (other than log messages)
*/
override fun doAsyncWrite(uuid: UUID, a: ByteArray) = toRemoteExceptions {
if (!isConnected)
throw RadioNotConnectedException()
else {
debug("queuing ${a.size} bytes to $uuid")
// Note: we generate a new characteristic each time, because we are about to
// change the data and we want the data stored in the closure
val toRadio = getCharacteristic(uuid)
toRadio.value = a
safe!!.asyncWriteCharacteristic(toRadio) {
debug("asyncwrite of ${a.size} bytes completed")
}
}
}
/**
* do a synchronous read operation
*/
override fun doRead(uuid: UUID): ByteArray? = toRemoteExceptions {
if (!isConnected)
throw RadioNotConnectedException()
else {
// Note: we generate a new characteristic each time, because we are about to
// change the data and we want the data stored in the closure
val toRadio = getCharacteristic(uuid)
var a = safe!!.readCharacteristic(toRadio)
.value.clone() // we copy the bluetooth array because it might still be in use
debug("Read of $uuid got ${a.size} bytes")
if (a.isEmpty()) // An empty bluetooth response is converted to a null response for our clients
null
else
a
}
}
}

View File

@@ -6,14 +6,12 @@ import android.content.Intent
import android.os.IBinder
import com.geeksville.android.BinaryLogFile
import com.geeksville.android.Logging
import com.geeksville.concurrent.DeferredExecution
import com.geeksville.concurrent.handledLaunch
import com.geeksville.mesh.IRadioInterfaceService
import com.geeksville.util.toRemoteExceptions
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import java.util.*
class RadioNotConnectedException(message: String = "Not connected to radio") :
@@ -45,13 +43,6 @@ abstract class InterfaceService : Service(), Logging {
const val DEVADDR_KEY = "devAddr"
val BTM_FROMRADIO_CHARACTER =
UUID.fromString("8ba2bcc2-ee02-4a55-a531-c525c5e454d5")
val BTM_TORADIO_CHARACTER =
UUID.fromString("f75c76d2-129e-4dad-a1dd-7866124401e7")
val BTM_FROMNUM_CHARACTER =
UUID.fromString("ed9da18c-a800-4f66-a670-aa7547e34453")
/// This is public only so that SimRadio can bootstrap our message flow
fun broadcastReceivedFromRadio(context: Context, payload: ByteArray) {
val intent = Intent(RECEIVE_FROMRADIO_ACTION)
@@ -61,8 +52,6 @@ abstract class InterfaceService : Service(), Logging {
fun getPrefs(context: Context) =
context.getSharedPreferences("radio-prefs", Context.MODE_PRIVATE)
}
protected val logSends = false
@@ -75,10 +64,6 @@ abstract class InterfaceService : Service(), Logging {
private val serviceJob = Job()
protected val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
/// Work that users of our service want done, which might get deferred until after
/// we have completed our initial connection
private val clientOperations = DeferredExecution()
protected fun broadcastConnectionChanged(isConnected: Boolean, isPermanent: Boolean) {
debug("Broadcasting connection=$isConnected")
val intent = Intent(RADIO_CONNECTED_ACTION)
@@ -87,12 +72,6 @@ abstract class InterfaceService : Service(), Logging {
sendBroadcast(intent)
}
/**
* With the new rev2 api, our first send is to start the configure readbacks. In that case,
* rather than waiting for FromNum notifies - we try to just aggressively read all of the responses.
*/
private var isFirstSend = true
/// Send a packet/command out the radio link, this routine can block if it needs to
protected abstract fun handleSendToRadio(p: ByteArray)
@@ -109,7 +88,6 @@ abstract class InterfaceService : Service(), Logging {
)
}
protected fun onDisconnect(isPermanent: Boolean) {
broadcastConnectionChanged(false, isPermanent)
isConnected = false
@@ -149,32 +127,10 @@ abstract class InterfaceService : Service(), Logging {
}
}
/**
* do a synchronous write operation
*/
protected open fun doWrite(uuid: UUID, a: ByteArray) {
throw NotImplementedError("Only implemented temporarily until rev1 api is removed")
}
/**
* do an asynchronous write operation
* Any error responses will be ignored (other than log messages)
*/
protected open fun doAsyncWrite(uuid: UUID, a: ByteArray) {
throw NotImplementedError("Only implemented temporarily until rev1 api is removed")
}
protected open fun setBondedDeviceAddress(addr: String?) {
TODO()
}
/**
* do a synchronous read operation
*/
protected open fun doRead(uuid: UUID): ByteArray? {
throw NotImplementedError("Only implemented temporarily until rev1 api is removed")
}
private val binder = object : IRadioInterfaceService.Stub() {
override fun setDeviceAddress(deviceAddr: String?) = toRemoteExceptions {