fix: critical code review — thread safety, state management
CRITICAL fixes: - #1: lastMultiChannelResult 변경을 handler.post로 (메인 스레드 보장) - #3: measureDoneSignal var=remember → val mutableStateOf (recomposition 안전) - #34,35: BleManager bluetoothGatt/tx/rxCharacteristic/lastRxTimestamp @Volatile - #66: GreenZoneConstants 모든 mutable var @Volatile - #56: PiezoHW.distancePerSample @Volatile - nested handler.post 제거 (불필요한 프레임 지연) - maa throttle deadlock 방지 (Boolean 반환 + state 리셋) - Plot/Log 불일치 수정 (channelLogs를 allWalls 기준으로 통일) - Placement 센서 위치/화살표 조정, gradient dead zone, CV relaxation - 개발자 모드 CV 표시, 가이드 상자 항상 표시 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -48,9 +48,9 @@ class BleManager private constructor(private val context: Context) {
|
||||
private val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
private val bluetoothAdapter: BluetoothAdapter? = bluetoothManager.adapter
|
||||
private var bluetoothLeScanner: BluetoothLeScanner? = null
|
||||
private var bluetoothGatt: BluetoothGatt? = null
|
||||
private var txCharacteristic: BluetoothGattCharacteristic? = null
|
||||
private var rxCharacteristic: BluetoothGattCharacteristic? = null
|
||||
@Volatile private var bluetoothGatt: BluetoothGatt? = null
|
||||
@Volatile private var txCharacteristic: BluetoothGattCharacteristic? = null
|
||||
@Volatile private var rxCharacteristic: BluetoothGattCharacteristic? = null
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
val debugLogger = com.example.medilightv2android.services.BleDebugLogger.getInstance(context)
|
||||
private var scanTimer: Runnable? = null
|
||||
@@ -62,7 +62,7 @@ class BleManager private constructor(private val context: Context) {
|
||||
private var reconnectAttempt = 0
|
||||
private val reconnectIntervalMs: Long = 3000
|
||||
private var reconnectTimer: Runnable? = null
|
||||
private var lastRxTimestamp: Long = 0
|
||||
@Volatile private var lastRxTimestamp: Long = 0
|
||||
private var watchdogTimer: Runnable? = null
|
||||
private val watchdogTimeoutMs: Long = 15000
|
||||
|
||||
@@ -238,6 +238,7 @@ class BleManager private constructor(private val context: Context) {
|
||||
scheduleAutoReconnect()
|
||||
}
|
||||
|
||||
|
||||
fun disconnect() {
|
||||
isUserDisconnect = true
|
||||
cancelAutoReconnect()
|
||||
@@ -395,16 +396,16 @@ class BleManager private constructor(private val context: Context) {
|
||||
sendRaw(CRC16.buildCommandBE("mec", intArrayOf(freqOption, delayUs, 140, cycles, 1, piezoCh)))
|
||||
}
|
||||
|
||||
fun sendAllChannels(mode: Int = 0) {
|
||||
fun sendAllChannels(mode: Int = 0): Boolean {
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastMaaSentMs < 1000) {
|
||||
if (now - lastMaaSentMs < 800) {
|
||||
android.util.Log.w("BleManager", "maa THROTTLED — ${now - lastMaaSentMs}ms since last")
|
||||
debugLogger.warn("maa THROTTLED ${now - lastMaaSentMs}ms")
|
||||
return
|
||||
return false
|
||||
}
|
||||
lastMaaSentMs = now
|
||||
piezoCollector.startMultiChannel(6)
|
||||
sendRaw(CRC16.buildCommandASCII("maa", " "))
|
||||
return true
|
||||
}
|
||||
|
||||
// ── NIRS Commands ──
|
||||
@@ -453,18 +454,18 @@ class BleManager private constructor(private val context: Context) {
|
||||
sendRaw(CRC16.buildCommandASCII("mbb", " "))
|
||||
}
|
||||
|
||||
/** 6채널 측정만 (maa) — 최소 1초 간격 throttle */
|
||||
/** 6채널 측정만 (maa) — 최소 800ms 간격 throttle */
|
||||
private var lastMaaSentMs = 0L
|
||||
fun sendChannelsOnly() {
|
||||
fun sendChannelsOnly(): Boolean {
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastMaaSentMs < 1000) {
|
||||
if (now - lastMaaSentMs < 800) {
|
||||
android.util.Log.w("BleManager", "maa THROTTLED — ${now - lastMaaSentMs}ms since last")
|
||||
debugLogger.warn("maa THROTTLED ${now - lastMaaSentMs}ms")
|
||||
return
|
||||
return false
|
||||
}
|
||||
lastMaaSentMs = now
|
||||
piezoCollector.startMultiChannel(6)
|
||||
sendRaw(CRC16.buildCommandASCII("maa", " "))
|
||||
return true
|
||||
}
|
||||
|
||||
fun startBatteryPolling() {
|
||||
|
||||
Reference in New Issue
Block a user