Merge pull request #81 from geeksville/dev

Dev
pull/85/head
Kevin Hester 2020-07-02 10:43:14 -07:00 zatwierdzone przez GitHub
commit cfc7dc8355
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
10 zmienionych plików z 88 dodań i 44 usunięć

Wyświetl plik

@ -1,7 +1,7 @@
# Remaining tasks before declaring 1.0 # Remaining tasks before declaring 1.0
- add faq entry about range and antennas and rain
- first message sent is still doubled for some people - first message sent is still doubled for some people
- disable software update button after update finishes
- let users set arbitrary params in android - let users set arbitrary params in android
- add a low level settings screen (let user change any of the RadioConfig parameters) - add a low level settings screen (let user change any of the RadioConfig parameters)

Wyświetl plik

@ -17,8 +17,8 @@ android {
applicationId "com.geeksville.mesh" applicationId "com.geeksville.mesh"
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works) minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
targetSdkVersion 29 targetSdkVersion 29
versionCode 10785 // format is Mmmss (where M is 1+the numeric major number versionCode 10787 // format is Mmmss (where M is 1+the numeric major number
versionName "0.7.85" versionName "0.7.87"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {

Wyświetl plik

@ -0,0 +1 @@
../../../../../meshtastic-esp32/release/latest/bins

Wyświetl plik

@ -772,7 +772,12 @@ class MainActivity : AppCompatActivity(), Logging,
if (model.meshService != null) if (model.meshService != null)
Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)") Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)")
try {
MeshService.startService(this) // Start the service so it stays running even after we unbind MeshService.startService(this) // Start the service so it stays running even after we unbind
} catch (ex: Exception) {
// Old samsung phones have a race condition andthis might rarely fail. Which is probably find because the bind will be sufficient most of the time
errormsg("Failed to start service from activity - but ignoring because bind will work ${ex.message}")
}
// ALSO bind so we can use the api // ALSO bind so we can use the api
mesh.connect(this, MeshService.intent, Context.BIND_AUTO_CREATE + Context.BIND_ABOVE_CLIENT) mesh.connect(this, MeshService.intent, Context.BIND_AUTO_CREATE + Context.BIND_ABOVE_CLIENT)

Wyświetl plik

@ -354,9 +354,9 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String
private var isFirstTime = true private var isFirstTime = true
private fun doDiscoverServicesAndInit() { private fun doDiscoverServicesAndInit() {
// FIXME - no need to discover services more than once - instead use lazy() to use them in future attempts
safe!!.asyncDiscoverServices { discRes -> safe!!.asyncDiscoverServices { discRes ->
discRes.getOrThrow() // FIXME, instead just try to reconnect? try {
discRes.getOrThrow()
service.serviceScope.handledLaunch { service.serviceScope.handledLaunch {
try { try {
@ -384,6 +384,11 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String
) )
} }
} }
} catch (ex: BLEException) {
scheduleReconnect(
"Unexpected error discovering services, forcing disconnect $ex"
)
}
} }
} }

Wyświetl plik

@ -1461,6 +1461,8 @@ class MeshService : Service(), Logging {
errormsg("Unable to update", ex) errormsg("Unable to update", ex)
null null
} }
debug("setFirmwareUpdateFilename $firmwareUpdateFilename")
} }
private fun doFirmwareUpdate() { private fun doFirmwareUpdate() {

Wyświetl plik

@ -85,8 +85,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
} }
override fun toString(): String { override fun toString(): String {
return super.toString() return "Work:$tag"
} }
/// Connection work items are treated specially
fun isConnect() = tag == "connect" || tag == "reconnect"
} }
/** /**
@ -122,6 +125,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
private val STATUS_RELIABLE_WRITE_FAILED = 4403 private val STATUS_RELIABLE_WRITE_FAILED = 4403
private val STATUS_TIMEOUT = 4404 private val STATUS_TIMEOUT = 4404
private val STATUS_NOSTART = 4405 private val STATUS_NOSTART = 4405
private val STATUS_SIMFAILURE = 4406
private val gattCallback = object : BluetoothGattCallback() { private val gattCallback = object : BluetoothGattCallback() {
@ -157,7 +161,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
if (oldstate == BluetoothProfile.STATE_CONNECTED) { if (oldstate == BluetoothProfile.STATE_CONNECTED) {
info("Lost connection - aborting current work: $currentWork") info("Lost connection - aborting current work: $currentWork")
// If we get a disconnect, just try again otherwise fail all current operations
if (currentWork?.isConnect() == true)
dropAndReconnect() dropAndReconnect()
else
lostConnection("lost connection")
} else if (status == 133) { } else if (status == 133) {
// We were not previously connected and we just failed with our non-auto connection attempt. Therefore we now need // We were not previously connected and we just failed with our non-auto connection attempt. Therefore we now need
// to do an autoconnection attempt. When that attempt succeeds/fails the normal callbacks will be called // to do an autoconnection attempt. When that attempt succeeds/fails the normal callbacks will be called
@ -285,6 +293,12 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
} }
} }
// To test loss of BLE faults we can randomly fail a certain % of all work items. We
// skip this for "connect" items because the handling for connection failure is special
var simFailures = false
var failPercent =
10 // 15% failure is unusably high because of constant reconnects, 7% somewhat usable, 10% pretty bad
private val failRandom = Random()
private var activeTimeout: Job? = null private var activeTimeout: Job? = null
@ -311,6 +325,14 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
isSettingMtu = isSettingMtu =
false // Most work is not doing MTU stuff, the work that is will re set this flag false // Most work is not doing MTU stuff, the work that is will re set this flag
val failThis =
simFailures && !newWork.isConnect() && failRandom.nextInt(100) < failPercent
if (failThis) {
errormsg("Simulating random work failure!")
completeWork(STATUS_SIMFAILURE, Unit)
} else {
val started = newWork.startWork() val started = newWork.startWork()
if (!started) { if (!started) {
errormsg("Failed to start work, returned error status") errormsg("Failed to start work, returned error status")
@ -321,6 +343,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
} }
} }
} }
}
private fun <T> queueWork( private fun <T> queueWork(
tag: String, tag: String,
@ -499,8 +522,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
} }
} }
/// Drop our current connection and then requeue a connect as needed private fun lostConnection(reason: String) {
private fun dropAndReconnect() {
/* /*
Supposedly this reconnect attempt happens automatically Supposedly this reconnect attempt happens automatically
"If the connection was established through an auto connect, Android will "If the connection was established through an auto connect, Android will
@ -511,7 +533,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
closeConnection() closeConnection()
*/ */
failAllWork(BLEException("Lost connection")) failAllWork(BLEException(reason))
// Cancel any notifications - because when the device comes back it might have forgotten about us // Cancel any notifications - because when the device comes back it might have forgotten about us
notifyHandlers.clear() notifyHandlers.clear()
@ -520,6 +542,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
debug("calling lostConnect handler") debug("calling lostConnect handler")
it.invoke() it.invoke()
} }
}
/// Drop our current connection and then requeue a connect as needed
private fun dropAndReconnect() {
lostConnection("lost connection, reconnecting")
// Queue a new connection attempt // Queue a new connection attempt
val cb = connectionCallback val cb = connectionCallback

Wyświetl plik

@ -230,10 +230,12 @@ class SoftwareUpdateService : JobIntentService(), Logging {
val (region) = regionRegex.find(hwVer)?.destructured val (region) = regionRegex.find(hwVer)?.destructured
?: throw Exception("Malformed hw version") ?: throw Exception("Malformed hw version")
val name = "firmware/firmware-$mfg-$region-$curver.bin" val base = "firmware-$mfg-$region-$curver.bin"
// Check to see if the file exists (some builds might not include update files for size reasons) // Check to see if the file exists (some builds might not include update files for size reasons)
return if (!context.assets.list(name).isNullOrEmpty()) val firmwareFiles = context.assets.list("firmware") ?: arrayOf()
name return if (firmwareFiles.contains(base))
"firmware/$base"
else else
null null
} }

Wyświetl plik

@ -484,10 +484,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
updateProgressBar.progress = service.updateStatus updateProgressBar.progress = service.updateStatus
delay(2000) // Only check occasionally delay(2000) // Only check occasionally
} }
val isSuccess = (service.updateStatus == -1)
scanStatusText.text = scanStatusText.text =
if (service.updateStatus == -1) "Update successful" else "Update failed" if (isSuccess) "Update successful" else "Update failed"
updateProgressBar.isEnabled = false updateProgressBar.isEnabled = false
updateFirmwareButton.isEnabled = true updateFirmwareButton.isEnabled = !isSuccess
} }
} }
} }
@ -504,7 +506,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
// If actively connected possibly let the user update firmware // If actively connected possibly let the user update firmware
val info = model.myNodeInfo.value val info = model.myNodeInfo.value
if (connected == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate) { if (connected == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate && info.couldUpdate) {
updateFirmwareButton.visibility = View.VISIBLE updateFirmwareButton.visibility = View.VISIBLE
updateFirmwareButton.text = updateFirmwareButton.text =
getString(R.string.update_to).format(getString(R.string.cur_firmware_version)) getString(R.string.update_to).format(getString(R.string.cur_firmware_version))

@ -1 +1 @@
Subproject commit 10d3b2e62b26d41b9b2568eefb3c207442c1cc5c Subproject commit 95c5a9aa950f917857a3cc0c7cd84a4a56993032