mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
treat disabiling bluetooth as loss of connection
This commit is contained in:
parent
9e83bfd790
commit
8ce5a13cf8
4 changed files with 59 additions and 16 deletions
4
TODO.md
4
TODO.md
|
|
@ -1,9 +1,8 @@
|
||||||
# High priority
|
# High priority
|
||||||
|
|
||||||
* fix startup race conditions in services, allow reads to block as needed
|
|
||||||
* if radio disconnects, we need to requeue a new connect attempt in RadioService
|
* if radio disconnects, we need to requeue a new connect attempt in RadioService
|
||||||
* when notified phone should download messages
|
* when notified phone should download messages
|
||||||
* have phone use our local node number as its node number (instead of hardwired)
|
* fix startup race conditions in services, allow reads to block as needed
|
||||||
* investigate the Signal SMS message flow path, see if I could just make Mesh a third peer to signal & sms?
|
* investigate the Signal SMS message flow path, see if I could just make Mesh a third peer to signal & sms?
|
||||||
* make signal work when there is no internet up
|
* make signal work when there is no internet up
|
||||||
* make Signal rx path work
|
* make Signal rx path work
|
||||||
|
|
@ -69,3 +68,4 @@ Don't leave device discoverable. Don't let unpaired users do things with device
|
||||||
* investigate a 16 bit node number. If possible it would make collisions super rare. Much easier to just pick a nodenum and go.
|
* investigate a 16 bit node number. If possible it would make collisions super rare. Much easier to just pick a nodenum and go.
|
||||||
* remove example code boilerplate from the service
|
* remove example code boilerplate from the service
|
||||||
* switch from protobuf-java to protobuf-javalite - much faster and smaller, just no JSON debug printing
|
* switch from protobuf-java to protobuf-javalite - much faster and smaller, just no JSON debug printing
|
||||||
|
* have phone use our local node number as its node number (instead of hardwired)
|
||||||
|
|
@ -132,11 +132,12 @@ class RadioInterfaceService : Service(), Logging {
|
||||||
private lateinit var device: BluetoothDevice
|
private lateinit var device: BluetoothDevice
|
||||||
private lateinit var safe: SafeBluetooth
|
private lateinit var safe: SafeBluetooth
|
||||||
|
|
||||||
val service get() = safe.gatt.services.find { it.uuid == BTM_SERVICE_UUID }!!
|
val service get() = safe.gatt!!.services.find { it.uuid == BTM_SERVICE_UUID }!!
|
||||||
|
|
||||||
private lateinit var fromRadio: BluetoothGattCharacteristic
|
private lateinit var fromRadio: BluetoothGattCharacteristic
|
||||||
private lateinit var fromNum: BluetoothGattCharacteristic
|
private lateinit var fromNum: BluetoothGattCharacteristic
|
||||||
|
|
||||||
|
private val logSends = false
|
||||||
lateinit var sentPacketsLog: BinaryLogFile // inited in onCreate
|
lateinit var sentPacketsLog: BinaryLogFile // inited in onCreate
|
||||||
|
|
||||||
private var isConnected = false
|
private var isConnected = false
|
||||||
|
|
@ -160,8 +161,10 @@ class RadioInterfaceService : Service(), Logging {
|
||||||
|
|
||||||
debug("sending to radio")
|
debug("sending to radio")
|
||||||
doWrite(BTM_TORADIO_CHARACTER, p)
|
doWrite(BTM_TORADIO_CHARACTER, p)
|
||||||
sentPacketsLog.write(p)
|
if (logSends) {
|
||||||
sentPacketsLog.flush()
|
sentPacketsLog.write(p)
|
||||||
|
sentPacketsLog.flush()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle an incoming packet from the radio, broadcasts it as an android intent
|
// Handle an incoming packet from the radio, broadcasts it as an android intent
|
||||||
|
|
@ -239,12 +242,14 @@ class RadioInterfaceService : Service(), Logging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sentPacketsLog = BinaryLogFile(this, "sent_log.pb")
|
if (logSends)
|
||||||
|
sentPacketsLog = BinaryLogFile(this, "sent_log.pb")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
info("Destroying radio interface service")
|
info("Destroying radio interface service")
|
||||||
sentPacketsLog.close()
|
if (logSends)
|
||||||
|
sentPacketsLog.close()
|
||||||
safe.disconnect()
|
safe.disconnect()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
package com.geeksville.mesh
|
package com.geeksville.mesh
|
||||||
|
|
||||||
import android.bluetooth.*
|
import android.bluetooth.*
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
import com.geeksville.android.Logging
|
import com.geeksville.android.Logging
|
||||||
import com.geeksville.concurrent.CallbackContinuation
|
import com.geeksville.concurrent.CallbackContinuation
|
||||||
import com.geeksville.concurrent.Continuation
|
import com.geeksville.concurrent.Continuation
|
||||||
import com.geeksville.concurrent.SyncContinuation
|
import com.geeksville.concurrent.SyncContinuation
|
||||||
|
import com.geeksville.util.exceptionReporter
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -25,12 +29,39 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
var timeoutMsec = 5 * 1000L
|
var timeoutMsec = 5 * 1000L
|
||||||
|
|
||||||
/// Users can access the GATT directly as needed
|
/// Users can access the GATT directly as needed
|
||||||
lateinit var gatt: BluetoothGatt
|
var gatt: BluetoothGatt? = null
|
||||||
|
|
||||||
var state = BluetoothProfile.STATE_DISCONNECTED
|
var state = BluetoothProfile.STATE_DISCONNECTED
|
||||||
private var currentWork: BluetoothContinuation? = null
|
private var currentWork: BluetoothContinuation? = null
|
||||||
private val workQueue = mutableListOf<BluetoothContinuation>()
|
private val workQueue = mutableListOf<BluetoothContinuation>()
|
||||||
|
|
||||||
|
/// When we see the BT stack getting disabled/renabled we handle that as a connect/disconnect event
|
||||||
|
private val btStateReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) = exceptionReporter {
|
||||||
|
if (intent.action == BluetoothAdapter.ACTION_STATE_CHANGED) {
|
||||||
|
val newstate = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
|
||||||
|
when (newstate) {
|
||||||
|
// Simulate a disconnection if the user disables bluetooth entirely
|
||||||
|
BluetoothAdapter.STATE_OFF -> if (gatt != null) gattCallback.onConnectionStateChange(
|
||||||
|
gatt!!,
|
||||||
|
0,
|
||||||
|
BluetoothProfile.STATE_DISCONNECTED
|
||||||
|
)
|
||||||
|
BluetoothAdapter.STATE_ON -> {
|
||||||
|
warn("FIXME - requeue a connect anytime bluetooth is reenabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
context.registerReceiver(
|
||||||
|
btStateReceiver,
|
||||||
|
IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a schedulable bit of bluetooth work, includes both the closure to call to start the operation
|
* 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
|
* and the completion (either async or sync) to call when it completes
|
||||||
|
|
@ -48,10 +79,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val gattCallback = object : BluetoothGattCallback() {
|
private val gattCallback = object : BluetoothGattCallback() {
|
||||||
|
|
||||||
override fun onConnectionStateChange(
|
override fun onConnectionStateChange(
|
||||||
gatt: BluetoothGatt,
|
g: BluetoothGatt,
|
||||||
status: Int,
|
status: Int,
|
||||||
newState: Int
|
newState: Int
|
||||||
) {
|
) {
|
||||||
|
|
@ -66,6 +98,8 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
BluetoothProfile.STATE_DISCONNECTED -> {
|
BluetoothProfile.STATE_DISCONNECTED -> {
|
||||||
// cancel any queued ops? for now I think it is best to keep them around
|
// cancel any queued ops? for now I think it is best to keep them around
|
||||||
// failAllWork(IOException("Lost connection"))
|
// failAllWork(IOException("Lost connection"))
|
||||||
|
|
||||||
|
gatt = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,6 +201,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
// more info.
|
// more info.
|
||||||
// Otherwise if you pass in false, it will try to connect now and will timeout and fail in 30 seconds.
|
// 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<Unit>) {
|
private fun queueConnect(autoConnect: Boolean = false, cont: Continuation<Unit>) {
|
||||||
|
assert(gatt == null);
|
||||||
queueWork("connect", cont) {
|
queueWork("connect", cont) {
|
||||||
val g = device.connectGatt(context, autoConnect, gattCallback)
|
val g = device.connectGatt(context, autoConnect, gattCallback)
|
||||||
if (g != null)
|
if (g != null)
|
||||||
|
|
@ -185,7 +220,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
private fun queueReadCharacteristic(
|
private fun queueReadCharacteristic(
|
||||||
c: BluetoothGattCharacteristic,
|
c: BluetoothGattCharacteristic,
|
||||||
cont: Continuation<BluetoothGattCharacteristic>
|
cont: Continuation<BluetoothGattCharacteristic>
|
||||||
) = queueWork("readc", cont) { gatt.readCharacteristic(c) }
|
) = queueWork("readc", cont) { gatt!!.readCharacteristic(c) }
|
||||||
|
|
||||||
fun asyncReadCharacteristic(
|
fun asyncReadCharacteristic(
|
||||||
c: BluetoothGattCharacteristic,
|
c: BluetoothGattCharacteristic,
|
||||||
|
|
@ -197,7 +232,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
|
|
||||||
private fun queueDiscoverServices(cont: Continuation<Unit>) {
|
private fun queueDiscoverServices(cont: Continuation<Unit>) {
|
||||||
queueWork("discover", cont) {
|
queueWork("discover", cont) {
|
||||||
gatt.discoverServices()
|
gatt!!.discoverServices()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,7 +246,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
private fun queueRequestMtu(
|
private fun queueRequestMtu(
|
||||||
len: Int,
|
len: Int,
|
||||||
cont: Continuation<Int>
|
cont: Continuation<Int>
|
||||||
) = queueWork("reqMtu", cont) { gatt.requestMtu(len) }
|
) = queueWork("reqMtu", cont) { gatt!!.requestMtu(len) }
|
||||||
|
|
||||||
fun asyncRequestMtu(
|
fun asyncRequestMtu(
|
||||||
len: Int,
|
len: Int,
|
||||||
|
|
@ -227,7 +262,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
private fun queueWriteCharacteristic(
|
private fun queueWriteCharacteristic(
|
||||||
c: BluetoothGattCharacteristic,
|
c: BluetoothGattCharacteristic,
|
||||||
cont: Continuation<BluetoothGattCharacteristic>
|
cont: Continuation<BluetoothGattCharacteristic>
|
||||||
) = queueWork("writec", cont) { gatt.writeCharacteristic(c) }
|
) = queueWork("writec", cont) { gatt!!.writeCharacteristic(c) }
|
||||||
|
|
||||||
fun asyncWriteCharacteristic(
|
fun asyncWriteCharacteristic(
|
||||||
c: BluetoothGattCharacteristic,
|
c: BluetoothGattCharacteristic,
|
||||||
|
|
@ -238,7 +273,10 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
||||||
makeSync { queueWriteCharacteristic(c, it) }
|
makeSync { queueWriteCharacteristic(c, it) }
|
||||||
|
|
||||||
fun disconnect() {
|
fun disconnect() {
|
||||||
gatt.disconnect()
|
if (gatt != null)
|
||||||
|
gatt!!.disconnect()
|
||||||
|
|
||||||
|
context.unregisterReceiver(btStateReceiver)
|
||||||
failAllWork(Exception("SafeBluetooth disconnected"))
|
failAllWork(Exception("SafeBluetooth disconnected"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,8 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
||||||
|
|
||||||
// we begin by setting our MTU size as high as it can go
|
// we begin by setting our MTU size as high as it can go
|
||||||
sync.requestMtu(512)
|
sync.requestMtu(512)
|
||||||
|
|
||||||
val service = sync.gatt.services.find { it.uuid == SW_UPDATE_UUID }!!
|
val service = sync.gatt!!.services.find { it.uuid == SW_UPDATE_UUID }!!
|
||||||
|
|
||||||
val totalSizeDesc = service.getCharacteristic(SW_UPDATE_TOTALSIZE_CHARACTER)
|
val totalSizeDesc = service.getCharacteristic(SW_UPDATE_TOTALSIZE_CHARACTER)
|
||||||
val dataDesc = service.getCharacteristic(SW_UPDATE_DATA_CHARACTER)
|
val dataDesc = service.getCharacteristic(SW_UPDATE_DATA_CHARACTER)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue