1.1.33 fix #211 properly set GUI state when during a firmware update and the view gets rebuilt

pull/214/head
Kevin Hester 2021-01-05 15:02:11 +08:00
rodzic 1eb63e4f1c
commit 89fd3e16d8
6 zmienionych plików z 102 dodań i 42 usunięć

Wyświetl plik

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

Wyświetl plik

@ -9,6 +9,7 @@ const val prefix = "com.geeksville.mesh"
// a bool true means now connected, false means not
const val EXTRA_CONNECTED = "$prefix.Connected"
const val EXTRA_PROGRESS = "$prefix.Progress"
/// a bool true means we expect this condition to continue until, false means device might come back
const val EXTRA_PERMANENT = "$prefix.Permanent"

Wyświetl plik

@ -23,6 +23,7 @@ import com.geeksville.mesh.MeshProtos.ToRadio
import com.geeksville.mesh.database.MeshtasticDatabase
import com.geeksville.mesh.database.PacketRepository
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.service.SoftwareUpdateService.Companion.ProgressNotStarted
import com.geeksville.util.*
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.ResolvableApiException
@ -891,6 +892,7 @@ class MeshService : Service(), Logging {
// Do our startup init
try {
connectTimeMsec = System.currentTimeMillis()
SoftwareUpdateService.sendProgress(this, ProgressNotStarted) // Kinda crufty way of reiniting software update
startConfig()
} catch (ex: InvalidProtocolBufferException) {

Wyświetl plik

@ -147,6 +147,8 @@ class SoftwareUpdateService : JobIntentService(), Logging {
const val ACTION_START_UPDATE = "$prefix.START_UPDATE"
const val ACTION_UPDATE_PROGRESS = "$prefix.UPDATE_PROGRESS"
const val EXTRA_MACADDR = "macaddr"
private const val SCAN_PERIOD: Long = 10000
@ -170,10 +172,15 @@ class SoftwareUpdateService : JobIntentService(), Logging {
private val MANUFACTURE_CHARACTER = longBLEUUID("2a29")
private val HW_VERSION_CHARACTER = longBLEUUID("2a27")
const val ProgressSuccess = -1
const val ProgressUpdateFailed = -2
const val ProgressBleException = -3
const val ProgressNotStarted = -4
/**
* % progress through the update
*/
var progress = 0
var progress = ProgressNotStarted
/**
* Convenience method for enqueuing work in to this service.
@ -187,6 +194,17 @@ class SoftwareUpdateService : JobIntentService(), Logging {
}
fun sendProgress(context: Context, p: Int) {
if(progress != p) {
progress = p
val intent = Intent(ACTION_UPDATE_PROGRESS).putExtra(
EXTRA_PROGRESS,
p
)
context.sendBroadcast(intent)
}
}
/** Return true if we thing the firmwarte shoulde be updated
*
@ -200,7 +218,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
val minVer =
DeviceVersion("0.7.8") // The oldest device version with a working software update service
(curVer > deviceVersion) && (deviceVersion >= minVer)
((curVer > deviceVersion) && (deviceVersion >= minVer))
} catch (ex: Exception) {
errormsg("Error finding swupdate info", ex)
false // If we fail parsing our update info
@ -262,7 +280,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
errormsg("Ignoring failure to update spiffs on old appload")
}
assets.appLoad?.let { doUpdate(context, sync, it, FLASH_REGION_APPLOAD) }
progress = -1 // success
sendProgress(context, ProgressSuccess)
}
// writable region codes in the ESP32 update code
@ -288,7 +306,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
info("Starting firmware update for $assetName, flash region $flashRegion")
progress = 0
sendProgress(context,0)
val totalSizeDesc = getCharacteristic(SW_UPDATE_TOTALSIZE_CHARACTER)
val dataDesc = getCharacteristic(SW_UPDATE_DATA_CHARACTER)
val crc32Desc = getCharacteristic(SW_UPDATE_CRC32_CHARACTER)
@ -336,7 +354,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
// yet
val maxProgress = if(flashRegion != FLASH_REGION_APPLOAD)
50 else 100
progress = firmwareNumSent * maxProgress / firmwareSize
sendProgress(context, firmwareNumSent * maxProgress / firmwareSize)
debug("sending block ${progress}%")
var blockSize = 512 - 3 // Max size MTU excluding framing
@ -366,7 +384,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
sync.readCharacteristic(updateResultDesc)
.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)
if (updateResult != 0) {
progress = -2
sendProgress(context, ProgressUpdateFailed)
throw Exception("Device update failed, reason=$updateResult")
}
@ -377,7 +395,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
}
}
} catch (ex: BLEException) {
progress = -3
sendProgress(context, ProgressBleException)
throw ex // Unexpected BLE exception
}
}

Wyświetl plik

@ -29,7 +29,6 @@ import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.android.hideKeyboard
import com.geeksville.android.isGooglePlayAvailable
import com.geeksville.concurrent.handledLaunch
import com.geeksville.mesh.MainActivity
import com.geeksville.mesh.R
import com.geeksville.mesh.android.bluetoothManager
@ -40,6 +39,9 @@ import com.geeksville.mesh.service.BluetoothInterface
import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.service.RadioInterfaceService
import com.geeksville.mesh.service.SerialInterface
import com.geeksville.mesh.service.SoftwareUpdateService.Companion.ACTION_UPDATE_PROGRESS
import com.geeksville.mesh.service.SoftwareUpdateService.Companion.ProgressNotStarted
import com.geeksville.mesh.service.SoftwareUpdateService.Companion.ProgressSuccess
import com.geeksville.util.anonymize
import com.geeksville.util.exceptionReporter
import com.google.android.gms.location.LocationRequest
@ -50,9 +52,9 @@ import com.hoho.android.usbserial.driver.UsbSerialDriver
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import java.util.regex.Pattern
object SLogging : Logging {}
/// Change to a new macaddr selection, updating GUI and radio
@ -484,27 +486,13 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
private fun doFirmwareUpdate() {
model.meshService?.let { service ->
mainScope.handledLaunch {
debug("User started firmware update")
binding.updateFirmwareButton.isEnabled = false // Disable until things complete
binding.updateProgressBar.visibility = View.VISIBLE
binding.updateProgressBar.progress = 0 // start from scratch
debug("User started firmware update")
binding.updateFirmwareButton.isEnabled = false // Disable until things complete
binding.updateProgressBar.visibility = View.VISIBLE
binding.updateProgressBar.progress = 0 // start from scratch
binding.scanStatusText.text = "Updating firmware, wait up to eight minutes..."
try {
service.startFirmwareUpdate()
while (service.updateStatus >= 0) {
binding.updateProgressBar.progress = service.updateStatus
delay(2000) // Only check occasionally
}
} finally {
val isSuccess = (service.updateStatus == -1)
binding.scanStatusText.text =
if (isSuccess) "Update successful" else "Update failed"
binding.updateProgressBar.isEnabled = false
binding.updateFirmwareButton.isEnabled = !isSuccess
}
}
// We rely on our broadcast receiver to show progress as this progresses
service.startFirmwareUpdate()
}
}
@ -516,20 +504,55 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
return binding.root
}
private fun initNodeInfo() {
val connected = model.isConnected.value
// If actively connected possibly let the user update firmware
/// Set the correct update button configuration based on current progress
private fun refreshUpdateButton() {
debug("Reiniting the udpate button")
val info = model.myNodeInfo.value
if (connected == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate && info.couldUpdate) {
val service = model.meshService
if (model.isConnected.value == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate && info.couldUpdate && service != null) {
binding.updateFirmwareButton.visibility = View.VISIBLE
binding.updateFirmwareButton.isEnabled = true
binding.updateFirmwareButton.text =
getString(R.string.update_to).format(getString(R.string.cur_firmware_version))
val progress = service.updateStatus
binding.updateFirmwareButton.isEnabled =
(progress < 0) // if currently doing an upgrade disable button
if (progress >= 0) {
binding.updateProgressBar.progress = progress // update partial progress
binding.scanStatusText.setText(R.string.updating_firmware)
binding.updateProgressBar.visibility = View.VISIBLE
} else
when (progress) {
ProgressSuccess -> {
binding.scanStatusText.setText(R.string.update_successful)
binding.updateProgressBar.visibility = View.GONE
}
ProgressNotStarted -> {
// Do nothing - because we don't want to overwrite the status text in this case
binding.updateProgressBar.visibility = View.GONE
}
else -> {
binding.scanStatusText.setText(R.string.update_failed)
binding.updateProgressBar.visibility = View.VISIBLE
}
}
binding.updateProgressBar.isEnabled = false
} else {
binding.updateFirmwareButton.visibility = View.GONE
binding.updateProgressBar.visibility = View.GONE
}
}
private fun initNodeInfo() {
val connected = model.isConnected.value
refreshUpdateButton()
// If actively connected possibly let the user update firmware
val info = model.myNodeInfo.value
when (connected) {
MeshService.ConnectionState.CONNECTED -> {
@ -784,11 +807,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
initClassicScan()
}
override fun onPause() {
super.onPause()
scanModel.stopScan()
}
/**
* If the user has not turned on location access throw up a toast warning
*/
@ -842,11 +860,29 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
}
}
private val updateProgressFilter = IntentFilter(ACTION_UPDATE_PROGRESS)
private val updateProgressReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
refreshUpdateButton()
}
}
override fun onPause() {
super.onPause()
scanModel.stopScan()
requireActivity().unregisterReceiver(updateProgressReceiver)
}
override fun onResume() {
super.onResume()
if (!hasCompanionDeviceApi)
scanModel.startScan()
requireActivity().registerReceiver(updateProgressReceiver, updateProgressFilter)
// Keep reminding user BLE is still off
val hasUSB = activity?.let { SerialInterface.findDrivers(it).isNotEmpty() } ?: true
if (!hasUSB) {

Wyświetl plik

@ -77,4 +77,7 @@
<string name="debug_panel">Debug Panel</string>
<string name="debug_last_messages">500 last messages</string>
<string name="clear_last_messages">Clear</string>
<string name="updating_firmware">Updating firmware, wait up to eight minutes...</string>
<string name="update_successful">Update successful</string>
<string name="update_failed">Update failed</string>
</resources>