kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
if phone ble stack is hosed restart it
rodzic
dac3610f7d
commit
2c8c7ac8d6
4
TODO.md
4
TODO.md
|
@ -80,7 +80,6 @@ rules at the BluetoothDevice level. Either make SafeBluetooth lock at the devic
|
|||
* register app link for our URLs https://developer.android.com/studio/write/app-link-indexing.html
|
||||
* let user change radio params and share radio join info via QR code or text message (use an encoded app specific URL - to autoprompt for app installation as needed)
|
||||
* test with an oldish android release using real hardware
|
||||
* if necessary restart entire BT adapter with this tip from Michael https://stackoverflow.com/questions/35103701/ble-android-onconnectionstatechange-not-being-called
|
||||
* stop using a foreground service
|
||||
* change info() log strings to debug()
|
||||
* use platform theme (dark or light)
|
||||
|
@ -152,4 +151,5 @@ Don't leave device discoverable. Don't let unpaired users do things with device
|
|||
* tell Compose geeks
|
||||
* call crashlytics from exceptionReporter!!! currently not logging failures caught there
|
||||
* do setOwner every time we connect to the radio, use our settings, radio should ignore if unchanged
|
||||
* send location data for devices that don't have a GPS - https://developer.android.com/training/location/change-location-settings
|
||||
* send location data for devices that don't have a GPS - https://developer.android.com/training/location/change-location-settings
|
||||
* if necessary restart entire BT adapter with this tip from Michael https://stackoverflow.com/questions/35103701/ble-android-onconnectionstatechange-not-being-called
|
||||
|
|
|
@ -16,6 +16,8 @@ import android.os.RemoteException
|
|||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.PRIORITY_MIN
|
||||
import com.geeksville.analytics.DataPair
|
||||
import com.geeksville.android.GeeksvilleApplication
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.android.ServiceClient
|
||||
import com.geeksville.mesh.*
|
||||
|
@ -163,6 +165,8 @@ class MeshService : Service(), Logging {
|
|||
@SuppressLint("MissingPermission")
|
||||
private fun startLocationRequests() {
|
||||
if (fusedLocationClient == null) {
|
||||
GeeksvilleApplication.analytics.track("location_start") // Figure out how many users needed to use the phone GPS
|
||||
|
||||
val request = LocationRequest.create().apply {
|
||||
interval =
|
||||
5 * 60 * 1000 // FIXME, do more like once every 5 mins while we are connected to our radio _and_ someone else is in the mesh
|
||||
|
@ -209,6 +213,7 @@ class MeshService : Service(), Logging {
|
|||
private fun stopLocationRequests() {
|
||||
if (fusedLocationClient != null) {
|
||||
debug("Stopping location requests")
|
||||
GeeksvilleApplication.analytics.track("location_stop")
|
||||
fusedLocationClient?.removeLocationUpdates(locationCallback)
|
||||
fusedLocationClient = null
|
||||
}
|
||||
|
@ -231,7 +236,7 @@ class MeshService : Service(), Logging {
|
|||
private fun broadcastNodeChange(info: NodeInfo) {
|
||||
debug("Broadcasting node change $info")
|
||||
val intent = Intent(ACTION_NODE_CHANGE)
|
||||
|
||||
|
||||
intent.putExtra(EXTRA_NODEINFO, info)
|
||||
explicitBroadcast(intent)
|
||||
}
|
||||
|
@ -388,6 +393,8 @@ class MeshService : Service(), Logging {
|
|||
)
|
||||
|
||||
|
||||
private val numNodes get() = nodeDBbyNodeNum.size
|
||||
|
||||
/**
|
||||
* How many nodes are currently online (including our local node)
|
||||
*/
|
||||
|
@ -623,6 +630,12 @@ class MeshService : Service(), Logging {
|
|||
// Do our startup init
|
||||
try {
|
||||
reinitFromRadio()
|
||||
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"mesh_connect",
|
||||
DataPair("num_nodes", numNodes),
|
||||
DataPair("num_online", numOnlineNodes)
|
||||
)
|
||||
} catch (ex: RemoteException) {
|
||||
// It seems that when the ESP32 goes offline it can briefly come back for a 100ms ish which
|
||||
// causes the phone to try and reconnect. If we fail downloading our initial radio state we don't want to
|
||||
|
@ -633,6 +646,12 @@ class MeshService : Service(), Logging {
|
|||
} else {
|
||||
// lost radio connection, therefore no need to keep listening to GPS
|
||||
stopLocationRequests()
|
||||
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"mesh_disconnect",
|
||||
DataPair("num_nodes", numNodes),
|
||||
DataPair("num_online", numOnlineNodes)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,8 @@ class RadioInterfaceService : Service(), Logging {
|
|||
else {
|
||||
val fromRadio = service.getCharacteristic(BTM_FROMRADIO_CHARACTER)
|
||||
safe!!.asyncReadCharacteristic(fromRadio) {
|
||||
val b = it.getOrThrow().value
|
||||
val b = it.getOrThrow()
|
||||
.value.clone() // We clone the array just in case, I'm not sure if they keep reusing the array
|
||||
|
||||
if (b.isNotEmpty()) {
|
||||
debug("Received ${b.size} bytes from radio")
|
||||
|
@ -380,13 +381,14 @@ class RadioInterfaceService : Service(), Logging {
|
|||
// 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 = service.getCharacteristic(uuid)
|
||||
var a = safe!!.readCharacteristic(toRadio).value
|
||||
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
|
||||
a = null
|
||||
|
||||
a
|
||||
null
|
||||
else
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ import android.content.BroadcastReceiver
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Handler
|
||||
import com.geeksville.android.GeeksvilleApplication
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.concurrent.CallbackContinuation
|
||||
import com.geeksville.concurrent.Continuation
|
||||
|
@ -65,7 +67,8 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
debug("We were not connected, so ignoring bluetooth shutdown")
|
||||
}
|
||||
BluetoothAdapter.STATE_ON -> {
|
||||
warn("FIXME - requeue a connect anytime bluetooth is reenabled?")
|
||||
warn("requeue a connect anytime bluetooth is reenabled")
|
||||
reconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +103,35 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* skanky hack to restart BLE if it says it is hosed
|
||||
* https://stackoverflow.com/questions/35103701/ble-android-onconnectionstatechange-not-being-called
|
||||
*/
|
||||
var mHandler: Handler = Handler()
|
||||
|
||||
fun restartBle() {
|
||||
GeeksvilleApplication.analytics.track("ble_restart") // record # of times we needed to use this nasty hack
|
||||
error("Doing emergency BLE restart")
|
||||
val mgr =
|
||||
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
val adp = mgr.adapter
|
||||
if (null != adp) {
|
||||
if (adp.isEnabled) {
|
||||
adp.disable()
|
||||
// TODO: display some kind of UI about restarting BLE
|
||||
mHandler.postDelayed(object : Runnable {
|
||||
override fun run() {
|
||||
if (!adp.isEnabled) {
|
||||
adp.enable()
|
||||
} else {
|
||||
mHandler.postDelayed(this, 2500)
|
||||
}
|
||||
}
|
||||
}, 2500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val gattCallback = object : BluetoothGattCallback() {
|
||||
|
||||
override fun onConnectionStateChange(
|
||||
|
@ -153,6 +185,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
debug("No connectionCallback registered")
|
||||
}
|
||||
}
|
||||
|
||||
if (status == 257) { // mystery error code when phone is hung
|
||||
//throw Exception("Mystery bluetooth failure - debug me")
|
||||
restartBle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -350,6 +387,13 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
queueConnect(autoConnect, CallbackContinuation(cb))
|
||||
}
|
||||
|
||||
/// Restart any previous connect attempts
|
||||
private fun reconnect() {
|
||||
connectionCallback?.let { cb ->
|
||||
queueConnect(true, CallbackContinuation(cb))
|
||||
}
|
||||
}
|
||||
|
||||
fun connect(autoConnect: Boolean = false) = makeSync<Unit> { queueConnect(autoConnect, it) }
|
||||
|
||||
private fun queueReadCharacteristic(
|
||||
|
|
|
@ -43,8 +43,7 @@ object ScanState : Logging {
|
|||
debug("stopping scan")
|
||||
scanner!!.stopScan(callback)
|
||||
callback = null
|
||||
} else
|
||||
debug("not stopping bt scanner")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue