kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
treat disabiling bluetooth as loss of connection
rodzic
9e83bfd790
commit
8ce5a13cf8
4
TODO.md
4
TODO.md
|
@ -1,9 +1,8 @@
|
|||
# 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
|
||||
* 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?
|
||||
* make signal work when there is no internet up
|
||||
* 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.
|
||||
* remove example code boilerplate from the service
|
||||
* 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 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 fromNum: BluetoothGattCharacteristic
|
||||
|
||||
private val logSends = false
|
||||
lateinit var sentPacketsLog: BinaryLogFile // inited in onCreate
|
||||
|
||||
private var isConnected = false
|
||||
|
@ -160,8 +161,10 @@ class RadioInterfaceService : Service(), Logging {
|
|||
|
||||
debug("sending to radio")
|
||||
doWrite(BTM_TORADIO_CHARACTER, p)
|
||||
sentPacketsLog.write(p)
|
||||
sentPacketsLog.flush()
|
||||
if (logSends) {
|
||||
sentPacketsLog.write(p)
|
||||
sentPacketsLog.flush()
|
||||
}
|
||||
}
|
||||
|
||||
// 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() {
|
||||
info("Destroying radio interface service")
|
||||
sentPacketsLog.close()
|
||||
if (logSends)
|
||||
sentPacketsLog.close()
|
||||
safe.disconnect()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package com.geeksville.mesh
|
||||
|
||||
import android.bluetooth.*
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.concurrent.CallbackContinuation
|
||||
import com.geeksville.concurrent.Continuation
|
||||
import com.geeksville.concurrent.SyncContinuation
|
||||
import com.geeksville.util.exceptionReporter
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
|
@ -25,12 +29,39 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
var timeoutMsec = 5 * 1000L
|
||||
|
||||
/// Users can access the GATT directly as needed
|
||||
lateinit var gatt: BluetoothGatt
|
||||
var gatt: BluetoothGatt? = null
|
||||
|
||||
var state = BluetoothProfile.STATE_DISCONNECTED
|
||||
private var currentWork: BluetoothContinuation? = null
|
||||
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
|
||||
* 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() {
|
||||
|
||||
override fun onConnectionStateChange(
|
||||
gatt: BluetoothGatt,
|
||||
g: BluetoothGatt,
|
||||
status: Int,
|
||||
newState: Int
|
||||
) {
|
||||
|
@ -66,6 +98,8 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
BluetoothProfile.STATE_DISCONNECTED -> {
|
||||
// cancel any queued ops? for now I think it is best to keep them around
|
||||
// failAllWork(IOException("Lost connection"))
|
||||
|
||||
gatt = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,6 +201,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<Unit>) {
|
||||
assert(gatt == null);
|
||||
queueWork("connect", cont) {
|
||||
val g = device.connectGatt(context, autoConnect, gattCallback)
|
||||
if (g != null)
|
||||
|
@ -185,7 +220,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
private fun queueReadCharacteristic(
|
||||
c: BluetoothGattCharacteristic,
|
||||
cont: Continuation<BluetoothGattCharacteristic>
|
||||
) = queueWork("readc", cont) { gatt.readCharacteristic(c) }
|
||||
) = queueWork("readc", cont) { gatt!!.readCharacteristic(c) }
|
||||
|
||||
fun asyncReadCharacteristic(
|
||||
c: BluetoothGattCharacteristic,
|
||||
|
@ -197,7 +232,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
|
||||
private fun queueDiscoverServices(cont: Continuation<Unit>) {
|
||||
queueWork("discover", cont) {
|
||||
gatt.discoverServices()
|
||||
gatt!!.discoverServices()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,7 +246,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
private fun queueRequestMtu(
|
||||
len: Int,
|
||||
cont: Continuation<Int>
|
||||
) = queueWork("reqMtu", cont) { gatt.requestMtu(len) }
|
||||
) = queueWork("reqMtu", cont) { gatt!!.requestMtu(len) }
|
||||
|
||||
fun asyncRequestMtu(
|
||||
len: Int,
|
||||
|
@ -227,7 +262,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
private fun queueWriteCharacteristic(
|
||||
c: BluetoothGattCharacteristic,
|
||||
cont: Continuation<BluetoothGattCharacteristic>
|
||||
) = queueWork("writec", cont) { gatt.writeCharacteristic(c) }
|
||||
) = queueWork("writec", cont) { gatt!!.writeCharacteristic(c) }
|
||||
|
||||
fun asyncWriteCharacteristic(
|
||||
c: BluetoothGattCharacteristic,
|
||||
|
@ -238,7 +273,10 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
makeSync { queueWriteCharacteristic(c, it) }
|
||||
|
||||
fun disconnect() {
|
||||
gatt.disconnect()
|
||||
if (gatt != null)
|
||||
gatt!!.disconnect()
|
||||
|
||||
context.unregisterReceiver(btStateReceiver)
|
||||
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
|
||||
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 dataDesc = service.getCharacteristic(SW_UPDATE_DATA_CHARACTER)
|
||||
|
|
Ładowanie…
Reference in New Issue