Merge branch 'fix/espflasher-cancellable': cancellable flasher + dialog fixes + key exchange reliability

This commit is contained in:
eddy 2026-07-26 17:24:40 +02:00
commit a80abc5c0c
2 changed files with 27 additions and 7 deletions

View file

@ -25,7 +25,15 @@ class EspFlasher(private val context: Context) {
private val handler = Handler(Looper.getMainLooper())
@Volatile
private var cancelled = false
fun cancel() {
cancelled = true
}
fun flashDevice(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
cancelled = false
Thread {
try {
doFlash(usbManager, device, callback)
@ -47,6 +55,7 @@ class EspFlasher(private val context: Context) {
private fun doFlash(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
Thread.sleep(500)
if (cancelled) return
val connection = usbManager.openDevice(device)
?: throw IOException("Kan USB-apparaat niet openen")
@ -67,6 +76,7 @@ class EspFlasher(private val context: Context) {
postProgress(callback, 0, "Verbinden met ESP bootloader...")
val transport = UsbSerialTransport(connection, epOut, epIn)
if (cancelled) return
val assets = context.assets
val bootloader = assets.open("firmware/bootloader.bin").readBytes()
@ -107,6 +117,7 @@ class EspFlasher(private val context: Context) {
stub.eraseFlash()
for (step in steps) {
if (cancelled) return
val sizeStr = if (step.data.size > 1024) "${step.data.size / 1024}KB" else "${step.data.size} bytes"
postProgress(callback, step.baseProgress, "${step.name} schrijven ($sizeStr)...")

View file

@ -43,6 +43,7 @@ class SettingsActivity : AppCompatActivity() {
private var currentAction = UsbAction.NONE
private var progressDialog: AlertDialog? = null
private var dialog: AlertDialog? = null
private var flasher: EspFlasher? = null
private val handler = Handler(Looper.getMainLooper())
private val usbAttachedReceiver = object : BroadcastReceiver() {
@ -120,6 +121,8 @@ class SettingsActivity : AppCompatActivity() {
override fun onDestroy() {
super.onDestroy()
currentAction = UsbAction.NONE
flasher?.cancel()
flasher = null
try { unregisterReceiver(usbAttachedReceiver) } catch (e: Exception) {}
try { unregisterReceiver(usbPermissionReceiver) } catch (e: Exception) {}
try { unregisterReceiver(usbDetachedReceiver) } catch (e: Exception) {}
@ -166,11 +169,11 @@ class SettingsActivity : AppCompatActivity() {
finish()
}
is KeyResult.Error -> {
Toast.makeText(this, result.message, Toast.LENGTH_LONG).show()
Toast.makeText(this, "Sleutel uitwisselen mislukt - probeer opnieuw", Toast.LENGTH_LONG).show()
cleanupAction()
}
null -> {
Toast.makeText(this, "Sleutel niet gevonden", Toast.LENGTH_SHORT).show()
Toast.makeText(this, "Sleutel uitwisselen mislukt - probeer opnieuw", Toast.LENGTH_SHORT).show()
cleanupAction()
}
}
@ -201,10 +204,12 @@ class SettingsActivity : AppCompatActivity() {
}
private fun doFlashing(usbManager: UsbManager, device: UsbDevice) {
dialog?.dismiss()
dialog = null
showProgressDialog("Firmware Flashen", "Initialiseren...", STYLE_HORIZONTAL)
val flasher = EspFlasher(this)
flasher.flashDevice(usbManager, device, object : EspFlasher.FlashCallback {
flasher = EspFlasher(this)
flasher?.flashDevice(usbManager, device, object : EspFlasher.FlashCallback {
override fun onProgress(percent: Int, message: String) {
runOnUiThread {
val d = progressDialog ?: return@runOnUiThread
@ -282,6 +287,10 @@ class SettingsActivity : AppCompatActivity() {
progressDialog = AlertDialog.Builder(this)
.setTitle(title)
.setView(view)
.setNegativeButton("Annuleren") { _, _ ->
flasher?.cancel()
cleanupAction()
}
.setCancelable(false)
.show()
}
@ -335,8 +344,8 @@ class SettingsActivity : AppCompatActivity() {
try {
setupCdcControl(connection, device)
for (attempt in 1..3) {
Thread.sleep(500)
for (attempt in 1..5) {
Thread.sleep(1000L)
flushReadBuffer(connection, epIn)
@ -389,7 +398,7 @@ class SettingsActivity : AppCompatActivity() {
Log.w(TAG, "Attempt $attempt: no KEY response, retrying")
}
return KeyResult.Error("Geen sleutel gevonden na 3 pogingen")
return KeyResult.Error("Geen sleutel gevonden na 5 pogingen")
} catch (e: Exception) {
Log.e(TAG, "Key exchange error", e)
return KeyResult.Error("Fout: ${e.message}")