diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index 35e10fff2..43cc475c9 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -21,6 +21,7 @@ import com.geeksville.analytics.DataPair import com.geeksville.android.GeeksvilleApplication import com.geeksville.android.Logging import com.geeksville.android.ServiceClient +import com.geeksville.concurrent.handledLaunch import com.geeksville.mesh.* import com.geeksville.mesh.MeshProtos.MeshPacket import com.geeksville.mesh.MeshProtos.ToRadio @@ -35,21 +36,8 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration import java.util.concurrent.TimeUnit -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -private val errorHandler = CoroutineExceptionHandler { _, exception -> - Exceptions.report(exception, "MeshService-coroutine", "coroutine-exception") -} - -/// Wrap launch with an exception handler, FIXME, move into a utility lib -fun CoroutineScope.handledLaunch( - context: CoroutineContext = EmptyCoroutineContext, - start: CoroutineStart = CoroutineStart.DEFAULT, - block: suspend CoroutineScope.() -> Unit -) = this.launch(context = context + errorHandler, start = start, block = block) - /** * Handles all the communication with android apps. Also keeps an internal model * of the network state. @@ -67,7 +55,7 @@ class MeshService : Service(), Logging { class IdNotFoundException(id: String) : Exception("ID not found $id") class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id") - class NotInMeshException() : Exception("We are not yet in a mesh") + // class NotInMeshException() : Exception("We are not yet in a mesh") /** A little helper that just calls startService */ diff --git a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt index d9aa9c4aa..6de76b89d 100644 --- a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt @@ -17,6 +17,7 @@ import com.geeksville.android.BinaryLogFile import com.geeksville.android.GeeksvilleApplication import com.geeksville.android.Logging import com.geeksville.concurrent.DeferredExecution +import com.geeksville.concurrent.handledLaunch import com.geeksville.mesh.IRadioInterfaceService import com.geeksville.mesh.anonymized import com.geeksville.util.exceptionReporter diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt index d50bb145e..e6a3b092e 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -25,6 +25,7 @@ import androidx.lifecycle.Observer import com.geeksville.android.GeeksvilleApplication import com.geeksville.android.Logging import com.geeksville.android.hideKeyboard +import com.geeksville.concurrent.handledLaunch import com.geeksville.mesh.MainActivity import com.geeksville.mesh.R import com.geeksville.mesh.anonymized @@ -34,6 +35,10 @@ import com.geeksville.mesh.service.RadioInterfaceService import com.geeksville.util.exceptionReporter import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.android.synthetic.main.settings_fragment.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import java.util.regex.Pattern object SLogging : Logging {} @@ -290,6 +295,11 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { private val scanModel: BTScanModel by activityViewModels() private val model: UIViewModel by activityViewModels() + // FIXME - move this into a standard GUI helper class + private val guiJob = Job() + private val mainScope = CoroutineScope(Dispatchers.Main + guiJob) + + private val hasCompanionDeviceApi: Boolean by lazy { RadioInterfaceService.hasCompanionDeviceApi(requireContext()) } @@ -298,6 +308,33 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { requireContext().getSystemService(CompanionDeviceManager::class.java) } + override fun onDestroy() { + guiJob.cancel() + super.onDestroy() + } + + private fun doFirmwareUpdate() { + model.meshService?.let { service -> + + mainScope.handledLaunch { + debug("User started firmware update") + updateFirmwareButton.isEnabled = false // Disable until things complete + updateProgressBar.visibility = View.VISIBLE + + scanStatusText.text = "Updating firmware, wait up to eight minutes..." + service.startFirmwareUpdate() + while (service.updateStatus >= 0) { + updateProgressBar.progress = service.updateStatus + delay(2000) // Only check occasionally + } + scanStatusText.text = + if (service.updateStatus == -1) "Update successful" else "Update failed" + updateProgressBar.isEnabled = false + updateFirmwareButton.isEnabled = true + } + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -340,11 +377,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { }) updateFirmwareButton.setOnClickListener { - debug("User started firmware update") - updateFirmwareButton.isEnabled = false // Disable until things complete - updateProgressBar.visibility = View.VISIBLE - model.meshService?.startFirmwareUpdate() - scanStatusText.text = "Updating firmware, wait up to eight minutes..." + doFirmwareUpdate() } usernameEditText.on(EditorInfo.IME_ACTION_DONE) { diff --git a/geeksville-androidlib b/geeksville-androidlib index 1c729d801..b53b7f90b 160000 --- a/geeksville-androidlib +++ b/geeksville-androidlib @@ -1 +1 @@ -Subproject commit 1c729d801162380f2db9c2a3c681458f4a719bd1 +Subproject commit b53b7f90b326ef6b1dedca32a2472784e63d10e6 diff --git a/images/firmware-update.png b/images/firmware-update.png new file mode 100644 index 000000000..6ab5a7da8 Binary files /dev/null and b/images/firmware-update.png differ