kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
0.5.5 only try to set max MTU once, if it fails consider phone buggy
rodzic
3e89510f52
commit
e302848607
|
@ -17,8 +17,8 @@ android {
|
|||
applicationId "com.geeksville.mesh"
|
||||
minSdkVersion 22 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||
targetSdkVersion 29
|
||||
versionCode 154
|
||||
versionName "0.5.4"
|
||||
versionCode 155
|
||||
versionName "0.5.5"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
|
|
@ -387,6 +387,73 @@ class RadioInterfaceService : Service(), Logging {
|
|||
|
||||
// private var isFirstTime = true
|
||||
|
||||
/**
|
||||
* Some buggy BLE stacks can fail on initial connect, with either missing services or missing characteristics. If that happens we
|
||||
* disconnect and try again when the device reenumerates.
|
||||
*/
|
||||
private suspend fun retryDueToException() {
|
||||
// Track how often in the field we need this hack
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"ble_reconnect_hack",
|
||||
DataPair(1)
|
||||
)
|
||||
|
||||
warn("Forcing disconnect and hopefully device will comeback (disabling forced refresh)")
|
||||
hasForcedRefresh = true
|
||||
ignoreException {
|
||||
safe!!.closeConnection()
|
||||
}
|
||||
delay(1000) // Give some nasty time for buggy BLE stacks to shutdown (500ms was not enough)
|
||||
warn("Attempting reconnect")
|
||||
startConnect()
|
||||
}
|
||||
|
||||
/// We only try to set MTU once, because some buggy implementations fail
|
||||
private var shouldSetMtu = true
|
||||
|
||||
private fun doDiscoverServicesAndInit() {
|
||||
// FIXME - no need to discover services more than once - instead use lazy() to use them in future attempts
|
||||
safe!!.asyncDiscoverServices { discRes ->
|
||||
discRes.getOrThrow() // FIXME, instead just try to reconnect?
|
||||
|
||||
serviceScope.handledLaunch {
|
||||
try {
|
||||
debug("Discovered services!")
|
||||
delay(500) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null
|
||||
|
||||
// service could be null, test this by throwing BLEException and testing it on my machine
|
||||
isOldApi = service.getCharacteristic(BTM_RADIO_CHARACTER) != null
|
||||
warn("Use oldAPI = $isOldApi")
|
||||
|
||||
/* if (isFirstTime) {
|
||||
isFirstTime = false
|
||||
throw BLEException("Faking a BLE failure")
|
||||
} */
|
||||
|
||||
fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER)
|
||||
|
||||
// We must set this to true before broadcasting connectionChanged
|
||||
isConnected = true
|
||||
|
||||
// We treat the first send by a client as special
|
||||
isFirstSend = true
|
||||
|
||||
// Now tell clients they can (finally use the api)
|
||||
broadcastConnectionChanged(true, isPermanent = false)
|
||||
|
||||
// Immediately broadcast any queued packets sitting on the device
|
||||
doReadFromRadio(true)
|
||||
} catch (ex: BLEException) {
|
||||
errormsg(
|
||||
"Unexpected error in initial device enumeration, forcing disconnect",
|
||||
ex
|
||||
)
|
||||
retryDueToException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onConnect(connRes: Result<Unit>) {
|
||||
// This callback is invoked after we are connected
|
||||
|
||||
|
@ -399,65 +466,27 @@ class RadioInterfaceService : Service(), Logging {
|
|||
forceServiceRefresh()
|
||||
}
|
||||
|
||||
// we begin by setting our MTU size as high as it can go
|
||||
safe!!.asyncRequestMtu(512) { mtuRes ->
|
||||
mtuRes.getOrThrow() // FIXME - why sometimes is the result Unit!?!
|
||||
debug("MTU change attempted")
|
||||
// we begin by setting our MTU size as high as it can go (if we can)
|
||||
if (shouldSetMtu)
|
||||
safe!!.asyncRequestMtu(512) { mtuRes ->
|
||||
try {
|
||||
mtuRes.getOrThrow() // FIXME - why sometimes is the result Unit!?!
|
||||
debug("MTU change attempted")
|
||||
|
||||
// FIXME - no need to discover services more than once - instead use lazy() to use them in future attempts
|
||||
safe!!.asyncDiscoverServices { discRes ->
|
||||
discRes.getOrThrow() // FIXME, instead just try to reconnect?
|
||||
// throw BLEException("Test MTU set failed")
|
||||
|
||||
serviceScope.handledLaunch {
|
||||
try {
|
||||
debug("Discovered services!")
|
||||
delay(500) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null
|
||||
|
||||
// service could be null, test this by throwing BLEException and testing it on my machine
|
||||
isOldApi = service.getCharacteristic(BTM_RADIO_CHARACTER) != null
|
||||
warn("Use oldAPI = $isOldApi")
|
||||
|
||||
/* if (isFirstTime) {
|
||||
isFirstTime = false
|
||||
throw BLEException("Faking a BLE failure")
|
||||
} */
|
||||
|
||||
fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER)
|
||||
|
||||
// We must set this to true before broadcasting connectionChanged
|
||||
isConnected = true
|
||||
|
||||
// We treat the first send by a client as special
|
||||
isFirstSend = true
|
||||
|
||||
// Now tell clients they can (finally use the api)
|
||||
broadcastConnectionChanged(true, isPermanent = false)
|
||||
|
||||
// Immediately broadcast any queued packets sitting on the device
|
||||
doReadFromRadio(true)
|
||||
} catch (ex: BLEException) {
|
||||
// Track how often in the field we need this hack
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"ble_reconnect_hack",
|
||||
DataPair(1)
|
||||
)
|
||||
|
||||
errormsg(
|
||||
"Unexpected error in initial device enumeration, forcing disconnect",
|
||||
ex
|
||||
)
|
||||
warn("Forcing disconnect and hopefully device will comeback (disabling forced refresh)")
|
||||
hasForcedRefresh = true
|
||||
ignoreException {
|
||||
safe!!.closeConnection()
|
||||
}
|
||||
delay(500) // Give some nasty time for buggy BLE stacks to shutdown
|
||||
warn("Attempting reconnect")
|
||||
startConnect()
|
||||
}
|
||||
doDiscoverServicesAndInit()
|
||||
} catch (ex: BLEException) {
|
||||
errormsg(
|
||||
"Giving up on setting MTUs, forcing disconnect",
|
||||
ex
|
||||
)
|
||||
shouldSetMtu = false
|
||||
serviceScope.handledLaunch { retryDueToException() }
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
doDiscoverServicesAndInit()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,6 +84,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A BLE status code based error
|
||||
*/
|
||||
class BLEStatusException(val status: Int, msg: String) : BLEException(msg)
|
||||
|
||||
// 0x2902 org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
||||
private val configurationDescriptorUUID =
|
||||
longBLEUUID("2902")
|
||||
|
@ -339,7 +344,8 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
debug("work ${work.tag} is completed, resuming status=$status, res=$res")
|
||||
if (status != 0)
|
||||
work.completion.resumeWithException(
|
||||
BLEException(
|
||||
BLEStatusException(
|
||||
status,
|
||||
"Bluetooth status=$status while doing ${work.tag}"
|
||||
)
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@ buildscript {
|
|||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.0-beta04'
|
||||
classpath 'com.android.tools.build:gradle:4.0.0-beta05'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue