From fc476a16833de56f327066cc91e4527af7c19320 Mon Sep 17 00:00:00 2001 From: loucass003 Date: Thu, 26 Mar 2026 19:05:40 +0100 Subject: [PATCH] Proper handling of the reconnect on ota and serial --- .../src/main/java/dev/slimevr/firmware/ota.kt | 16 ++++++++++------ .../src/main/java/dev/slimevr/firmware/serial.kt | 11 ++++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/server/core/src/main/java/dev/slimevr/firmware/ota.kt b/server/core/src/main/java/dev/slimevr/firmware/ota.kt index d300ef2bd..7d8a72be5 100644 --- a/server/core/src/main/java/dev/slimevr/firmware/ota.kt +++ b/server/core/src/main/java/dev/slimevr/firmware/ota.kt @@ -12,6 +12,9 @@ import io.ktor.utils.io.core.writeFully import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout @@ -154,14 +157,15 @@ suspend fun doOtaFlash( onStatus(FirmwareUpdateStatus.REBOOTING, 0) - // wait for the tracker with the correct id to come online + // Wait for the device to come back online after reboot. + // flatMapLatest switches to the matched device's own state flow so that + // status changes (which don't emit a new VRServerState) are also observed. + @OptIn(ExperimentalCoroutinesApi::class) val connected = withTimeoutOrNull(60_000) { server.context.state - .map { state -> - state.devices.values.any { - it.context.state.value.id.toUByte() == deviceId.id && - it.context.state.value.status != TrackerStatus.DISCONNECTED - } + .flatMapLatest { state -> + val device = state.devices.values.find { it.context.state.value.id.toUByte() == deviceId.id } + device?.context?.state?.map { it.status != TrackerStatus.DISCONNECTED } ?: flowOf(false) } .filter { it } .first() diff --git a/server/core/src/main/java/dev/slimevr/firmware/serial.kt b/server/core/src/main/java/dev/slimevr/firmware/serial.kt index acd262342..a21903d20 100644 --- a/server/core/src/main/java/dev/slimevr/firmware/serial.kt +++ b/server/core/src/main/java/dev/slimevr/firmware/serial.kt @@ -10,6 +10,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch @@ -181,13 +183,12 @@ internal suspend fun doSerialFlashPostFlash( } // wait for the tracker with that MAC to connect to the server via UDP + @OptIn(ExperimentalCoroutinesApi::class) val connected = withTimeoutOrNull(60_000) { server.context.state - .map { state -> - state.devices.values.any { - it.context.state.value.macAddress?.uppercase() == macAddress && - it.context.state.value.status != TrackerStatus.DISCONNECTED - } + .flatMapLatest { state -> + val device = state.devices.values.find { it.context.state.value.macAddress?.uppercase() == macAddress } + device?.context?.state?.map { it.status != TrackerStatus.DISCONNECTED } ?: flowOf(false) } .filter { it } .first()