Throttle volume commands to prevent ESP32 overload

Limits volume API calls to max 1 per 300ms while dragging the slider.
UI updates remain immediate for smooth feedback, and the final value
is always sent when the user stops adjusting.
This commit is contained in:
vesp 2025-11-22 23:48:54 +01:00
parent ca796007d6
commit 074ed30b8e

View File

@ -47,9 +47,13 @@ class MainViewModel @Inject constructor(
private var pollingJob: Job? = null
private var lastStationName: String? = null
private var connectionFailedSince: Long? = null
private var volumeJob: Job? = null
private var lastVolumeSentTime: Long = 0
private var pendingVolume: Int? = null
companion object {
private const val ERROR_DISPLAY_DELAY_MS = 10_000L // 10 seconds
private const val VOLUME_THROTTLE_MS = 300L // Throttle volume commands
}
init {
@ -161,15 +165,35 @@ class MainViewModel @Inject constructor(
}
fun setVolume(volume: Int) {
viewModelScope.launch {
val serverAddress = _uiState.value.serverAddress
if (serverAddress.isBlank()) return@launch
if (serverAddress.isBlank()) return
// Optimistically update UI
// Always update UI immediately for smooth feedback
_uiState.update {
it.copy(karadioStatus = it.karadioStatus.copy(volume = volume))
}
// Throttle network calls
val now = System.currentTimeMillis()
pendingVolume = volume
if (now - lastVolumeSentTime >= VOLUME_THROTTLE_MS) {
// Enough time has passed, send immediately
sendVolumeToDevice(serverAddress, volume)
} else {
// Schedule a delayed send for the pending value
volumeJob?.cancel()
volumeJob = viewModelScope.launch {
delay(VOLUME_THROTTLE_MS - (now - lastVolumeSentTime))
pendingVolume?.let { sendVolumeToDevice(serverAddress, it) }
}
}
}
private fun sendVolumeToDevice(serverAddress: String, volume: Int) {
lastVolumeSentTime = System.currentTimeMillis()
pendingVolume = null
viewModelScope.launch {
karadioRepository.setVolume(serverAddress, volume)
}
}