From 0513e7777df4e5caf1ecd3e23a57054ee1a77a19 Mon Sep 17 00:00:00 2001 From: eddy Date: Thu, 30 Jul 2026 18:59:08 +0200 Subject: [PATCH] fix: USB/OTA update flow - version check, chunk size, UX improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MainActivity: suppress toast when activity not resumed, auto-navigate to Settings on new firmware - SettingsActivity: unified BLE/USB radio buttons + single update button, version check before OTA, show dialog before loadFirmware, spinner timeout - BleRelayManager: expose getEspVersion() - OtaManager: reduce chunk size 500→248 to fit BLE MTU 255 - ESP: WRITE→WRITE_NR on OTA characteristic (was silently dropping data) - Layout/strings: remove intro text, add method radio buttons - Bump all firmware versions to v5 --- .../app/src/main/assets/firmware/firmware.bin | Bin 538800 -> 538800 bytes .../nl/eddydevink/sylda/BleRelayManager.kt | 2 + .../java/nl/eddydevink/sylda/MainActivity.kt | 6 ++- .../java/nl/eddydevink/sylda/OtaManager.kt | 2 +- .../nl/eddydevink/sylda/SettingsActivity.kt | 45 +++++++++++++----- .../src/main/res/layout/activity_settings.xml | 37 +++++++++----- android/app/src/main/res/values/strings.xml | 9 ++-- src/main.cpp | 4 +- 8 files changed, 70 insertions(+), 35 deletions(-) diff --git a/android/app/src/main/assets/firmware/firmware.bin b/android/app/src/main/assets/firmware/firmware.bin index e743106da1ebc175f4ab9d588e2572f98c152be7..5d7e202d54edf0c3808eafcb8495638891fcb9d5 100644 GIT binary patch delta 129 zcmV-{0Dk|l@gT7AAds*i(!)aB26#!hA3+Pd7$#aNCR!?fG)h}TB?7Q}0c!qsSJ?2&}OViuQ=M_yE>{?Ipu delta 128 zcmV-`0Du3m@gT7AAds*hv0ne$FF0YmP^@htipd+vnXfU*kJ^p095|M>?bc diff --git a/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt b/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt index fa9a970..9ce1a47 100644 --- a/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt +++ b/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt @@ -217,6 +217,8 @@ class BleRelayManager( appVersion = version } + fun getEspVersion(): String? = espVersion + @SuppressLint("MissingPermission") private fun connectToDevice(device: android.bluetooth.BluetoothDevice) { handler.post { callbacks.onStatusChanged(BleStatus.Connecting) } diff --git a/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt b/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt index b21a04b..da135a9 100644 --- a/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt +++ b/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt @@ -22,7 +22,7 @@ class MainActivity : AppCompatActivity(), BleCallbacks { private const val REQUEST_SETTINGS = 1 private const val POST_SETTINGS_RESCAN_MS = 500L private const val ON_RESUME_SCAN_DELAY_MS = 300L - private const val BUNDLED_FIRMWARE_VERSION = "2" + private const val BUNDLED_FIRMWARE_VERSION = "5" } private lateinit var manager: BleRelayManager @@ -222,8 +222,10 @@ class MainActivity : AppCompatActivity(), BleCallbacks { override fun onFirmwareVersion(espVersion: String, appVersion: String) { runOnUiThread { + if (isFinishing || isDestroyed || !lifecycle.currentState.isAtLeast(androidx.lifecycle.Lifecycle.State.RESUMED)) return@runOnUiThread if (espVersion.isEmpty() || espVersion != appVersion) { - Toast.makeText(this, getString(R.string.ota_update_available), Toast.LENGTH_LONG).show() + Toast.makeText(this, getString(R.string.ota_update_available), Toast.LENGTH_SHORT).show() + startActivityForResult(Intent(this, SettingsActivity::class.java), REQUEST_SETTINGS) } else { Toast.makeText(this, getString(R.string.ota_up_to_date), Toast.LENGTH_SHORT).show() } diff --git a/android/app/src/main/java/nl/eddydevink/sylda/OtaManager.kt b/android/app/src/main/java/nl/eddydevink/sylda/OtaManager.kt index 07b0050..a04c93f 100644 --- a/android/app/src/main/java/nl/eddydevink/sylda/OtaManager.kt +++ b/android/app/src/main/java/nl/eddydevink/sylda/OtaManager.kt @@ -23,7 +23,7 @@ class OtaManager( ) { companion object { private const val TAG = "OtaManager" - private const val OTA_CHUNK_DATA_SIZE = 500 + private const val OTA_CHUNK_DATA_SIZE = 248 private const val OTA_CMD_START: Byte = 0x10 private const val OTA_CMD_END: Byte = 0x11 private const val OTA_STATUS_ACK: Byte = 0x00 diff --git a/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt b/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt index e6d90ae..10d810d 100644 --- a/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt +++ b/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt @@ -64,7 +64,7 @@ class SettingsActivity : AppCompatActivity() { private const val REBOOT_WAIT_MS = 5000L private const val REBOOT_POLL_MS = 500L private const val REBOOT_MAX_WAIT_MS = 15000L - private const val EXPECTED_FIRMWARE_VERSION = "1" + private const val EXPECTED_FIRMWARE_VERSION = "5" } private enum class UsbAction { NONE, EXCHANGE_KEY, FLASH } @@ -77,6 +77,8 @@ class SettingsActivity : AppCompatActivity() { private var otaManager: OtaManager? = null private var otaJob: Job? = null private var lastTheme: String? = null + private val rebootTimeoutHandler = Handler(Looper.getMainLooper()) + private var rebootTimeoutRunnable: Runnable? = null private val usbAttachedReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { @@ -138,13 +140,12 @@ class SettingsActivity : AppCompatActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.title = getString(R.string.title_settings) - findViewById