From 1492030333d90a652240cb5cd1ff5d919efdf7dc Mon Sep 17 00:00:00 2001 From: jjangddu Date: Thu, 11 Jun 2026 15:21:04 +0900 Subject: [PATCH] =?UTF-8?q?ble:=20=ED=8E=8C=EC=9B=A8=EC=96=B4=20=EA=B5=AC?= =?UTF-8?q?=EB=B2=84=EC=A0=84=20=EA=B2=BD=EA=B3=A0=20=EB=B0=B0=EB=84=88=20?= =?UTF-8?q?(<=20VBTFW0118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 새 펌웨어(VBTFW0118+) 와 코드의 BLE throttle/MTU 가정이 맞도록 정렬됨. 더 옛 펌웨어가 연결된 경우 측정이 안 됨에도 사용자 입장에선 원인을 알 수 없어 endless loading 으로 보임 — 그 혼동을 막기 위한 명시적 경고. - BleManager.MIN_FIRMWARE_BUILD = 118 상수 - BleManager.parseFirmwareBuild("VBTFW0116") → 116 - BleManager.isFirmwareOutdated: 파싱한 빌드 < 118 일 때 true - 신규 FirmwareWarningBanner 컴포저블 (주황 경고색) - PlacementGuide / PiezoMonitoring 상단에 노출 펌웨어 미수신 상태(아직 mid? 응답 전)는 false 로 취급 — false positive 방지. --- .../medilightv2android/ble/BleManager.kt | 16 +++++ .../ui/components/FirmwareWarningBanner.kt | 59 +++++++++++++++++++ .../views/monitoring/PiezoMonitoringView.kt | 3 + .../ui/views/monitoring/PlacementGuideView.kt | 3 + 4 files changed, 81 insertions(+) create mode 100644 app/src/main/java/com/example/medilightv2android/ui/components/FirmwareWarningBanner.kt diff --git a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt index 54fd144..81b5ea0 100644 --- a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt +++ b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt @@ -28,6 +28,8 @@ class BleManager private constructor(private val context: Context) { companion object { private const val TAG = "BleManager" + /** 정상 측정에 필요한 최소 펌웨어 빌드 번호 (mtb? throttle/MTU 가정과 일치). */ + const val MIN_FIRMWARE_BUILD = 118 private inline fun logd(msg: () -> String) { if (BuildConfig.DEBUG) Log.d(TAG, msg()) } private inline fun logw(msg: () -> String) { if (BuildConfig.DEBUG) Log.w(TAG, msg()) } private inline fun loge(msg: () -> String) { if (BuildConfig.DEBUG) Log.e(TAG, msg()) } @@ -81,6 +83,20 @@ class BleManager private constructor(private val context: Context) { val firmwareVersion = mutableStateOf("") // "VBTFW0116" val hardwareVersion = mutableStateOf("") // "VBTHW0100" val serialNumber = mutableStateOf("") // "VBT26040001" + + /** "VBTFW0116" → 116, 형식 안 맞으면 null. */ + fun parseFirmwareBuild(raw: String): Int? { + val m = Regex("(\\d+)$").find(raw) ?: return null + return m.groupValues[1].toIntOrNull() + } + + /** 펌웨어 버전이 MIN_FIRMWARE_BUILD 미만이면 true. 모르거나(아직 미수신) 형식 안 맞으면 false. */ + val isFirmwareOutdated: Boolean + get() { + val n = parseFirmwareBuild(firmwareVersion.value) ?: return false + return n < MIN_FIRMWARE_BUILD + } + val batteryLevel = mutableStateOf(0) val bluetoothEnabled = mutableStateOf(bluetoothAdapter?.isEnabled == true) val isServiceReady = mutableStateOf(false) diff --git a/app/src/main/java/com/example/medilightv2android/ui/components/FirmwareWarningBanner.kt b/app/src/main/java/com/example/medilightv2android/ui/components/FirmwareWarningBanner.kt new file mode 100644 index 0000000..4e657d8 --- /dev/null +++ b/app/src/main/java/com/example/medilightv2android/ui/components/FirmwareWarningBanner.kt @@ -0,0 +1,59 @@ +package com.example.medilightv2android.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Warning +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.example.medilightv2android.ble.BleManager + +/** + * 펌웨어 구버전 경고 배너 — PlacementGuide / PiezoMonitoring 상단에 노출. + * isFirmwareOutdated 가 true 일 때만 렌더. 사용자가 측정 안 됨 원인을 즉시 파악하도록. + */ +@Composable +fun FirmwareWarningBanner(bleManager: BleManager, modifier: Modifier = Modifier) { + val fw by bleManager.firmwareVersion + if (!bleManager.isFirmwareOutdated) return + Row( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 6.dp) + .clip(RoundedCornerShape(10.dp)) + .background(Color(0xFFFF9500)) + .padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon(Icons.Default.Warning, "Warning", tint = Color.White) + Spacer(modifier = Modifier.width(10.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + "펌웨어 업데이트 필요", + fontSize = 13.sp, + fontWeight = FontWeight.Bold, + color = Color.White + ) + Text( + "현재: $fw · 필요: VBTFW${"%04d".format(BleManager.MIN_FIRMWARE_BUILD)} 이상. 측정이 정상 동작하지 않을 수 있습니다.", + fontSize = 11.sp, + color = Color.White.copy(alpha = 0.9f) + ) + } + } +} diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt index 7175323..2bef2b7 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt @@ -947,6 +947,9 @@ fun PiezoMonitoringView(appState: AppState) { // BLE 끊김 banner는 사내 테스트 피드백으로 제거됨 — 백그라운드 자동 재연결만 유지. + // 펌웨어 구버전 경고 + com.example.medilightv2android.ui.components.FirmwareWarningBanner(bleManager) + val scrollState = rememberScrollState() LaunchedEffect(showSettings) { if (showSettings) scrollState.animateScrollTo(0) diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt index d655361..18f3394 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt @@ -191,6 +191,9 @@ fun PlacementGuideView(appState: AppState) { } } + // 펌웨어 구버전 경고 + com.example.medilightv2android.ui.components.FirmwareWarningBanner(bleManager) + Box(modifier = Modifier.fillMaxSize()) { Column( modifier = Modifier