From 25317282d70fbfd9746b533cd3b709679cfce4f7 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Tue, 13 Oct 2026 10:21:49 +0900 Subject: [PATCH] =?UTF-8?q?refactor(firmware):=20=EC=9E=84=EC=83=81?= =?UTF-8?q?=EC=95=B1=EC=97=90=EC=84=9C=20=ED=94=84=EB=A1=9C=EB=B8=8C=20DFU?= =?UTF-8?q?=20=EC=99=80=20=ED=8E=8C=EC=9B=A8=EC=96=B4=20=EB=B2=84=EC=A0=84?= =?UTF-8?q?=20=ED=8C=90=EC=A0=95=EC=9D=84=20=EB=BA=80=EB=8B=A4=20=E2=80=94?= =?UTF-8?q?=20=ED=8E=8C=EC=9B=A8=EC=96=B4=20=EA=B0=B1=EC=8B=A0=EC=9D=80=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=95=B1=EC=9D=B4=20=EB=A7=A1?= =?UTF-8?q?=EB=8A=94=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 사용자 결정(2026-10-13). 임상 폰 두 대 모두 사용자 앱이 같이 깔려 있고 거기서 양산 펌웨어 VB0FW0100 으로 올리므로, 임상앱이 번들 zip 과 버전 판정을 따로 들고 있을 이유가 없다. 실제로 임상 번들은 1.0.0+5 로 VBTFW0207 보다 낡아 "재설치"가 다운그레이드였고, 최소빌드 118 규칙은 0100 부터 다시 세는 양산 펌웨어에 "구버전" 거짓 경고를 낼 참이었다. 뺀 것 - firmware/ 패키지 전부(DfuManager·DfuNus·DfuNusConnection·DfuBleScanner·FirmwarePackage· FirmwareUpdateView)와 assets/dfu_application_1.0.0+5.zip, mcumgr-ble 의존성. - AppScreen.FIRMWARE_UPDATE 라우트·뒤로가기 매핑, 홈 화면 "펌웨어 업데이트" 버튼(여백만 남김). - BleManager 의 MIN_FIRMWARE_BUILD · parseFirmwareBuild · parseFwSemver · isFirmwareOutdated · isFirmwareUpdateAvailable · currentBluetoothDevice(DFU 전용이었다). - 배너의 주황(구버전)·파랑(새 펌웨어) 분기와 그 문자열. 빨강 "기기 응답 없음"은 생존 신호라 남긴다. 남긴 것 - 펌웨어 버전 표시(설정)와 세션 JSON·CSV 의 firmware_version 기록 — 어떤 펌웨어로 잰 세션인지는 계속 추적된다. - ClinicalEvent.FIRMWARE_OUTDATED 카테고리는 스키마 호환을 위해 두되, 올리는 곳은 없다. 검증: assembleDemoDebug · testDemoDebugUnitTest 통과. 수신 CRC 가드(사용자 앱 a0a61773)는 별건으로 남아 있다. Co-Authored-By: Claude Fable 5.1 --- app/build.gradle.kts | 1 - .../main/assets/dfu_application_1.0.0+5.zip | Bin 238901 -> 0 bytes .../java/com/medithings/vesiscan/AppState.kt | 5 +- .../com/medithings/vesiscan/MainActivity.kt | 4 - .../com/medithings/vesiscan/ble/BleManager.kt | 88 +-- .../vesiscan/firmware/DfuBleScanner.kt | 163 ------ .../vesiscan/firmware/DfuManager.kt | 468 ---------------- .../medithings/vesiscan/firmware/DfuNus.kt | 77 --- .../vesiscan/firmware/DfuNusConnection.kt | 193 ------- .../vesiscan/firmware/FirmwarePackage.kt | 117 ---- .../firmware/ui/FirmwareUpdateView.kt | 509 ------------------ .../ui/components/FirmwareWarningBanner.kt | 60 +-- .../vesiscan/ui/views/home/HomeView.kt | 15 +- .../views/monitoring/PiezoMonitoringView.kt | 7 +- .../ui/views/monitoring/PlacementGuideView.kt | 7 +- app/src/main/res/values-ko/strings.xml | 5 - app/src/main/res/values/strings.xml | 5 - gradle/libs.versions.toml | 4 +- 18 files changed, 32 insertions(+), 1696 deletions(-) delete mode 100644 app/src/main/assets/dfu_application_1.0.0+5.zip delete mode 100644 app/src/main/java/com/medithings/vesiscan/firmware/DfuBleScanner.kt delete mode 100644 app/src/main/java/com/medithings/vesiscan/firmware/DfuManager.kt delete mode 100644 app/src/main/java/com/medithings/vesiscan/firmware/DfuNus.kt delete mode 100644 app/src/main/java/com/medithings/vesiscan/firmware/DfuNusConnection.kt delete mode 100644 app/src/main/java/com/medithings/vesiscan/firmware/FirmwarePackage.kt delete mode 100644 app/src/main/java/com/medithings/vesiscan/firmware/ui/FirmwareUpdateView.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 70e391d..90b6d58 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -109,7 +109,6 @@ dependencies { // 2026-08-12: YOLO/CameraX/MLKit 제거 (소변컵 사진 인식 기능 폐기). implementation("com.squareup.okhttp3:okhttp:4.12.0") // HF API - implementation(libs.mcumgr.ble) // Firmware DFU (SMP-over-BLE) testImplementation(libs.junit) // org.json 은 안드로이드 단위테스트에서 **모든 메서드가 스텁**이라 호출하면 예외가 diff --git a/app/src/main/assets/dfu_application_1.0.0+5.zip b/app/src/main/assets/dfu_application_1.0.0+5.zip deleted file mode 100644 index b9d47904b925b27a330e51edb5bed1115701e42d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238901 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%0A08Ne<%%EA<@$2d~!7@7yXH;ya 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
z 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 DrLVhS diff --git a/app/src/main/java/com/medithings/vesiscan/AppState.kt b/app/src/main/java/com/medithings/vesiscan/AppState.kt index ddee70a..0166a3b 100644 --- a/app/src/main/java/com/medithings/vesiscan/AppState.kt +++ b/app/src/main/java/com/medithings/vesiscan/AppState.kt @@ -18,8 +18,9 @@ enum class AppScreen { CLINICAL_HOME, // ★ Dev 모드 한정 — 임상 R&D 측정 세션 화면 (입력 폼) CLINICAL_LIVE, // ★ Dev 모드 한정 — 6채널 라이브 시각화 + Capture HOSPITAL_MODE, // ★ Dev 모드 한정 — 병원 임상 측정 (주파수×cycle 자동 순회) - ANCHOR_ALIGN, // ★ Dev 모드 한정 — 부착 위치 정렬 (병원 임상 전 단계) - FIRMWARE_UPDATE // ★ 2026-08-03 (cloud-mvp 672e679 이식) — VBT 프로브 firmware DFU + ANCHOR_ALIGN // ★ Dev 모드 한정 — 부착 위치 정렬 (병원 임상 전 단계) + // FIRMWARE_UPDATE(프로브 DFU)는 2026-10-13 에 뺐다 — 펌웨어 갱신은 같은 폰의 사용자 앱이 맡는다. + // 번들 zip·버전 판정을 두 앱에 이중으로 두면 어긋나기만 했다(임상 번들이 1.0.0+5 로 낡아 있었다). } class AppState(private val context: Context) { diff --git a/app/src/main/java/com/medithings/vesiscan/MainActivity.kt b/app/src/main/java/com/medithings/vesiscan/MainActivity.kt index c2ac711..76517eb 100644 --- a/app/src/main/java/com/medithings/vesiscan/MainActivity.kt +++ b/app/src/main/java/com/medithings/vesiscan/MainActivity.kt @@ -177,7 +177,6 @@ fun MedilightApp(modifier: Modifier = Modifier) { AppScreen.MEASUREMENT_HISTORY -> appState.currentScreen = AppScreen.PIEZO_MONITORING AppScreen.VOIDING_DIARY -> appState.currentScreen = AppScreen.PIEZO_MONITORING AppScreen.REMINDER_SETTINGS -> appState.currentScreen = AppScreen.PIEZO_MONITORING - AppScreen.FIRMWARE_UPDATE -> appState.currentScreen = AppScreen.HOME // 정렬은 병원 임상 모드에서 들어온다 — 돌아갈 곳도 거기다. AppScreen.ANCHOR_ALIGN -> appState.currentScreen = AppScreen.HOSPITAL_MODE // 병원 임상 모드의 진입점은 시작 화면이다. else 로 흘려도 HOME 이지만 @@ -219,9 +218,6 @@ fun MedilightApp(modifier: Modifier = Modifier) { AppScreen.HOSPITAL_MODE -> com.medithings.vesiscan.ui.views.clinical.HospitalModeView(appState) AppScreen.ANCHOR_ALIGN -> com.medithings.vesiscan.ui.views.clinical.AnchorAlignView(appState) AppScreen.CLINICAL_LIVE -> ClinicalLiveView(appState) - AppScreen.FIRMWARE_UPDATE -> com.medithings.vesiscan.firmware.ui.FirmwareUpdateScreen( - onBack = { appState.currentScreen = AppScreen.HOME } - ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/medithings/vesiscan/ble/BleManager.kt b/app/src/main/java/com/medithings/vesiscan/ble/BleManager.kt index 04707d9..1ad178d 100644 --- a/app/src/main/java/com/medithings/vesiscan/ble/BleManager.kt +++ b/app/src/main/java/com/medithings/vesiscan/ble/BleManager.kt @@ -54,8 +54,6 @@ 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()) } @@ -199,85 +197,13 @@ class BleManager private constructor(private val context: Context) { val hardwareVersion = mutableStateOf("") // "VBTHW0100" val serialNumber = mutableStateOf("") // "VBT26040001" /** 마지막으로 의미있는 BLE RX (reb 등) 가 도착한 시각 ms. - * FirmwareWarningBanner false-positive 차단용. */ + * FirmwareWarningBanner("기기 응답 없음") false-positive 차단용. */ val lastBleRxAt = mutableStateOf(0L) - /** "VBTFW0116" → 116, 형식 안 맞으면 null. */ - fun parseFirmwareBuild(raw: String): Int? { - val m = Regex("(\\d+)$").find(raw) ?: return null - return m.groupValues[1].toIntOrNull() - } + // 펌웨어 버전 판정(최소빌드 118 경고 · 번들 DFU 비교)은 2026-10-13 에 뺐다. 임상앱은 버전을 + // 세션 JSON·CSV 에 기록만 하고 판정하지 않는다 — 판정과 DFU 는 같은 폰의 사용자 앱이 맡는다. + // (양산 펌웨어 VB0FW0100 은 0100 부터 다시 세므로 옛 규칙이 "구버전" 거짓 경고를 냈다.) - /** - * 2026-08-05: FW 팀 스펙 (VBTFW 코드표) 반영. 두 포맷 통일 매핑. - * - * A. VBTFW MMNN → (M, 0, N) - * 예: VBTFW0100 = 1.0.0, VBTFW0200 = 2.0.0, VBTFW0201 = 2.0.1 - * B. MCUboot major.minor.patch[+build] → (major, minor, patch) - * 예: 1.0.0+5 = 1.0.0 (build 5 는 major/minor/patch 비교와 무관) - * - * Returns Triple(major, minor, patch) · 파싱 실패 시 null. - */ - private fun parseFwSemver(raw: String): Triple? { - // VBTFW / VB0FW / VBFW MMNN - val vbt = Regex("""VB\d?FW(\d{2})(\d{2})""").find(raw) - if (vbt != null) { - val major = vbt.groupValues[1].toIntOrNull() ?: return null - val patch = vbt.groupValues[2].toIntOrNull() ?: return null - return Triple(major, 0, patch) - } - // MCUboot semver - val mcu = Regex("""(\d+)\.(\d+)\.(\d+)""").find(raw) - if (mcu != null) { - return Triple( - mcu.groupValues[1].toInt(), - mcu.groupValues[2].toInt(), - mcu.groupValues[3].toInt(), - ) - } - return null - } - - /** 튜플 비교: a>b 면 양수, 같으면 0, 작으면 음수. */ - private fun compareSemver(a: Triple, b: Triple): Int { - if (a.first != b.first) return a.first - b.first - if (a.second != b.second) return a.second - b.second - return a.third - b.third - } - - /** 펌웨어 버전이 MIN_FIRMWARE_BUILD 미만이면 true. legacy "VBTFWxxxx" 만 판정. - * 신규 semver 는 별도 update-available 로 처리. */ - val isFirmwareOutdated: Boolean - get() { - val fw = firmwareVersion.value - if (fw.isEmpty()) return false - if (fw.startsWith("1.") || fw.contains("+")) return false - val n = parseFirmwareBuild(fw) ?: return false - return n < MIN_FIRMWARE_BUILD - } - - /** - * 앱 번들 DFU 가 기기 fw 보다 **엄격히 최신** 이면 true (2026-08-05). - * → "새 펌웨어 사용 가능" 배너 노출. - * - * 매핑 규칙 (FW 팀 스펙 · VBTFW 코드표): - * VBTFW MMNN = M.0.N (major=MM, minor=0, patch=NN) - * MCUboot X.Y.Z+B = (X, Y, Z) · +B build 는 무시 (같은 major.minor.patch 는 동일 취급) - * - * 예: - * device VBTFW0200 (2.0.0) · bundled 1.0.0+5 (1.0.0) → bundled < device → **false (배너 X)** - * device VBTFW0100 (1.0.0) · bundled 2.0.0+0 (2.0.0) → bundled > device → **true (배너 O)** - * device VBTFW0200 (2.0.0) · bundled 2.0.1+0 (2.0.1) → bundled > device → true - */ - val isFirmwareUpdateAvailable: Boolean - get() { - val fw = firmwareVersion.value - if (fw.isEmpty()) return false - val bundled = com.medithings.vesiscan.firmware.FirmwareLoader.BUNDLED_VERSION - val devTuple = parseFwSemver(fw) ?: return false - val bunTuple = parseFwSemver(bundled) ?: return false - return compareSemver(bunTuple, devTuple) > 0 - } val batteryLevel = mutableStateOf(0) /** 현재 연결된 디바이스 RSSI (dBm) · 미측정/미연결 시 null. dev-mode UI 오버레이용. */ @@ -353,12 +279,6 @@ class BleManager private constructor(private val context: Context) { val bluetoothEnabled = mutableStateOf(bluetoothAdapter?.isEnabled == true) val isServiceReady = mutableStateOf(false) - /** 현재 GATT 연결된 BluetoothDevice · 없으면 null. Firmware DFU 진입 시 - * 스캔 생략하고 바로 이 기기로 재연결하는 경로에서 사용. */ - val currentBluetoothDevice: android.bluetooth.BluetoothDevice? - @android.annotation.SuppressLint("MissingPermission") - get() = bluetoothGatt?.device - val isBonded: Boolean @android.annotation.SuppressLint("MissingPermission") get() = bluetoothGatt?.device?.bondState == android.bluetooth.BluetoothDevice.BOND_BONDED diff --git a/app/src/main/java/com/medithings/vesiscan/firmware/DfuBleScanner.kt b/app/src/main/java/com/medithings/vesiscan/firmware/DfuBleScanner.kt deleted file mode 100644 index a9f017c..0000000 --- a/app/src/main/java/com/medithings/vesiscan/firmware/DfuBleScanner.kt +++ /dev/null @@ -1,163 +0,0 @@ -/* - * MEDiDFU — VesiSeek firmware updater - * - * BLE discovery. Also detects the SMP service that marks a device already in DFU mode, - * and reports the conditions that make Android drop scan results silently. - * - * Author: Charles KWON OhJun - * MEDiThings Inc. - */ -package com.medithings.vesiscan.firmware -import android.annotation.SuppressLint -import android.bluetooth.BluetoothAdapter -import android.bluetooth.BluetoothDevice -import android.bluetooth.BluetoothManager -import android.bluetooth.le.ScanCallback -import android.bluetooth.le.ScanResult -import android.bluetooth.le.ScanSettings -import android.content.Context -import android.location.LocationManager -import android.os.Build -import android.os.Handler -import android.os.Looper -import android.os.ParcelUuid -import androidx.core.location.LocationManagerCompat - -data class ScannedDevice( - val device: BluetoothDevice, - val name: String, - val rssi: Int, - /** True when the advertisement carries the SMP service, i.e. the device is waiting for DFU. */ - val inDfuMode: Boolean, -) { - val address: String get() = device.address -} - -/** - * Thin BLE scanner. - * - * No hardware scan filter is used: the SMP UUID is advertised in the *scan response*, and some - * controllers will not match an offloaded filter against it. Filtering in software costs a few - * extra callbacks and is reliable everywhere. - */ -@SuppressLint("MissingPermission") -class BleScanner(context: Context) { - - private val appContext = context.applicationContext - private val handler = Handler(Looper.getMainLooper()) - private val adapter: BluetoothAdapter? = - (appContext.getSystemService(Context.BLUETOOTH_SERVICE) as? BluetoothManager)?.adapter - - private var callback: ScanCallback? = null - private var timeoutTask: Runnable? = null - - val isBluetoothEnabled: Boolean get() = adapter?.isEnabled == true - - var isScanning: Boolean = false - private set - - /** - * Raw advertisements delivered during the last scan, counted before the "has a name" filter. - * Zero while devices are clearly nearby points at a permission problem rather than at the - * filter, so it is worth logging. - */ - var advertisementsSeen: Int = 0 - private set - - /** - * Android 11 and below refuse to report scan results while location services are off, and do - * so silently. Returns a message describing the problem, or null when scanning can proceed. - */ - fun blockingCondition(): String? { - if (adapter == null) return "This device has no Bluetooth adapter" - if (!adapter.isEnabled) return "Bluetooth is off" - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) return null - val lm = appContext.getSystemService(Context.LOCATION_SERVICE) as? LocationManager - ?: return null - return if (LocationManagerCompat.isLocationEnabled(lm)) { - null - } else { - "Location services are off — Android 11 and below need them for BLE scanning" - } - } - - /** - * Starts a scan. [onResult] fires for every named advertisement (repeatedly for the same - * device as the RSSI updates); [onFinished] fires exactly once when the scan ends. - */ - fun start( - timeoutMs: Long, - onResult: (ScannedDevice) -> Unit, - onFinished: (error: String?) -> Unit, - ) { - stop() - advertisementsSeen = 0 - blockingCondition()?.let { - onFinished(it) - return - } - val scanner = adapter?.bluetoothLeScanner - if (scanner == null) { - onFinished("Bluetooth LE scanner unavailable") - return - } - - val smpUuid = ParcelUuid(VesiSeekUuids.SMP_SERVICE) - val cb = object : ScanCallback() { - override fun onScanResult(callbackType: Int, result: ScanResult) { - advertisementsSeen++ - val name = try { - result.scanRecord?.deviceName ?: result.device.name - } catch (_: SecurityException) { - null - } ?: return - if (name.isEmpty()) return - val inDfu = result.scanRecord?.serviceUuids?.contains(smpUuid) == true - handler.post { onResult(ScannedDevice(result.device, name, result.rssi, inDfu)) } - } - - override fun onScanFailed(errorCode: Int) { - handler.post { - isScanning = false - callback = null - onFinished("Scan failed (error $errorCode)") - } - } - } - - callback = cb - isScanning = true - try { - val settings = ScanSettings.Builder() - .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) - .build() - scanner.startScan(null, settings, cb) - } catch (e: Exception) { - isScanning = false - callback = null - onFinished("Scan could not be started: ${e.message}") - return - } - - val task = Runnable { - stop() - onFinished(null) - } - timeoutTask = task - handler.postDelayed(task, timeoutMs) - } - - fun stop() { - timeoutTask?.let { handler.removeCallbacks(it) } - timeoutTask = null - callback?.let { cb -> - try { - adapter?.bluetoothLeScanner?.stopScan(cb) - } catch (_: Exception) { - // Adapter may have been turned off while scanning. - } - } - callback = null - isScanning = false - } -} diff --git a/app/src/main/java/com/medithings/vesiscan/firmware/DfuManager.kt b/app/src/main/java/com/medithings/vesiscan/firmware/DfuManager.kt deleted file mode 100644 index bf15100..0000000 --- a/app/src/main/java/com/medithings/vesiscan/firmware/DfuManager.kt +++ /dev/null @@ -1,468 +0,0 @@ -/* - * MEDiDFU — VesiSeek firmware updater - * - * The update state machine: NUS connect -> mdf? -> re-scan for SMP -> MCUmgr upload. - * Ported from the Go host tool at D:\mt_project\vesiseek_ble_dfu. - * - * Author: Charles KWON OhJun - * MEDiThings Inc. - */ -package com.medithings.vesiscan.firmware -import android.annotation.SuppressLint -import android.bluetooth.BluetoothDevice -import android.content.Context -import android.os.Handler -import android.os.Looper -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.mutableStateOf -import com.medithings.vesiscan.firmware.BleScanner -import com.medithings.vesiscan.firmware.NusConnection -import com.medithings.vesiscan.firmware.NusPacket -import com.medithings.vesiscan.firmware.ScannedDevice -import io.runtime.mcumgr.ble.McuMgrBleTransport -import io.runtime.mcumgr.dfu.FirmwareUpgradeCallback -import io.runtime.mcumgr.dfu.FirmwareUpgradeController -import io.runtime.mcumgr.dfu.mcuboot.FirmwareUpgradeManager -import io.runtime.mcumgr.dfu.mcuboot.model.ImageSet -import io.runtime.mcumgr.exception.McuMgrException -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale - -enum class DfuPhase { - IDLE, - SCANNING, - CONNECTING, - CONNECTED, - ENTERING_DFU, - SEARCHING_DFU, - UPLOADING, - COMPLETED, - FAILED, -} - -/** - * Drives the full VesiSeek firmware update, ported from the Go host tool (`vesiseek_ble_dfu`): - * - * 1. scan and connect over NUS, - * 2. send `mdf?` — the device answers `rdf:`, drops the link and re-advertises with the SMP - * service, - * 3. re-scan and hand the device to Nordic's [FirmwareUpgradeManager], which uploads the signed - * image, marks it for test and resets. - * - * All state is Compose-observable and is only mutated on the main thread. - */ -@SuppressLint("MissingPermission") -class DfuManager(context: Context) { - - private companion object { - const val SCAN_TIMEOUT_MS = 15_000L - const val DFU_SCAN_TIMEOUT_MS = 30_000L - /** The firmware sends `rdf:` then disconnects ~100 ms later; don't wait much longer. */ - const val RDF_TIMEOUT_MS = 5_000L - /** Let the device finish re-advertising and the local stack settle before re-scanning. */ - const val RESCAN_DELAY_MS = 1_500L - const val MAX_LOG_LINES = 300 - /** nRF52 flash writes are word aligned. */ - const val MEMORY_ALIGNMENT = 4 - } - - private val appContext = context.applicationContext - private val handler = Handler(Looper.getMainLooper()) - private val scanner = BleScanner(appContext) - private val timeFormat = SimpleDateFormat("HH:mm:ss", Locale.US) - - private var nus: NusConnection? = null - private var transport: McuMgrBleTransport? = null - private var upgradeManager: FirmwareUpgradeManager? = null - - private var dfuEntryHandled = false - private var rdfTimeout: Runnable? = null - private val dfuCandidates = LinkedHashMap() - - // ── Observable state ──────────────────────────────────────────────────────────────────── - - val phase = mutableStateOf(DfuPhase.IDLE) - val status = mutableStateOf("Ready") - val devices = mutableStateListOf() - val logLines = mutableStateListOf() - val firmware = mutableStateOf(null) - val firmwareError = mutableStateOf(null) - val target = mutableStateOf(null) - /** Upload progress in 0f..1f. */ - val progress = mutableStateOf(0f) - val bytesSent = mutableStateOf(0) - - val isBluetoothEnabled: Boolean get() = scanner.isBluetoothEnabled - - val canStartDfu: Boolean - get() = phase.value == DfuPhase.CONNECTED && firmware.value != null - - val isBusy: Boolean - get() = phase.value in setOf( - DfuPhase.CONNECTING, DfuPhase.ENTERING_DFU, DfuPhase.SEARCHING_DFU, DfuPhase.UPLOADING, - ) - - // ── Firmware ──────────────────────────────────────────────────────────────────────────── - - fun loadFirmware() { - if (firmware.value != null) return - try { - val pkg = FirmwareLoader.loadFromAssets(appContext) - firmware.value = pkg - firmwareError.value = null - log("firmware ${pkg.imageFileName} v${pkg.version} (${pkg.sizeBytes} bytes)") - } catch (e: Exception) { - firmwareError.value = e.message ?: e.toString() - log("firmware load FAILED: ${e.message}") - } - } - - // ── Scan / connect ────────────────────────────────────────────────────────────────────── - - fun startScan() { - if (isBusy) return - devices.clear() - phase.value = DfuPhase.SCANNING - status.value = "Scanning…" - log("scanning ${SCAN_TIMEOUT_MS / 1000}s…") - scanner.start( - timeoutMs = SCAN_TIMEOUT_MS, - onResult = { found -> - val index = devices.indexOfFirst { it.address == found.address } - if (index >= 0) devices[index] = found else devices.add(found) - }, - onFinished = { error -> - if (phase.value != DfuPhase.SCANNING) return@start - phase.value = DfuPhase.IDLE - if (error != null) { - status.value = error - log("scan error: $error") - } else { - status.value = "Scan finished — ${devices.size} device(s)" - log("scan finished: ${devices.size} named device(s), " + - "${scanner.advertisementsSeen} advertisement(s) seen") - if (scanner.advertisementsSeen == 0) { - log("no advertisements at all — check the Nearby devices permission") - } - } - }, - ) - } - - /** Non-null when something outside the app prevents scanning (adapter off, location off). */ - fun bleBlockingCondition(): String? = scanner.blockingCondition() - - fun stopScan() { - scanner.stop() - if (phase.value == DfuPhase.SCANNING) { - phase.value = DfuPhase.IDLE - status.value = "Scan stopped" - } - } - - fun connect(device: ScannedDevice) { - if (isBusy) return - scanner.stop() - closeNus() - - target.value = device - phase.value = DfuPhase.CONNECTING - status.value = "Connecting to ${device.name}…" - log("connecting to ${device.name} (${device.address})") - - nus = NusConnection( - context = appContext, - onReady = { - if (phase.value != DfuPhase.CONNECTING) return@NusConnection - phase.value = DfuPhase.CONNECTED - status.value = "Connected to ${device.name}" - // Drop the scan results: the connected device is shown in the status card, and - // leaving the stale entries would offer a Connect button for other devices while - // a link is already up. - devices.clear() - log("NUS ready") - }, - onNotify = ::onNusNotification, - onDisconnected = ::onNusDisconnected, - onError = { message -> - if (phase.value == DfuPhase.CONNECTING || phase.value == DfuPhase.CONNECTED) { - fail(message) - } else { - log("BLE: $message") - } - }, - ).also { it.connect(device.device) } - } - - /** - * 스캔 생략 · 이미 알고 있는 기기에 바로 연결 (2026-08-03). - * 메인 앱이 이미 프로브에 연결됐던 상태에서 FirmwareUpdate 진입할 때 사용. - */ - fun connectDirectly(device: BluetoothDevice, name: String) { - val scanned = ScannedDevice(device = device, name = name, rssi = 0, inDfuMode = false) - log("skip scan — using previously connected device: $name") - connect(scanned) - } - - fun disconnect() { - closeNus() - if (phase.value == DfuPhase.CONNECTED || phase.value == DfuPhase.CONNECTING) { - phase.value = DfuPhase.IDLE - status.value = "Disconnected" - log("disconnected") - } - } - - // ── DFU ───────────────────────────────────────────────────────────────────────────────── - - fun startDfu() { - val pkg = firmware.value - if (phase.value != DfuPhase.CONNECTED || pkg == null) return - val connection = nus ?: return - - progress.value = 0f - bytesSent.value = 0 - dfuEntryHandled = false - dfuCandidates.clear() - phase.value = DfuPhase.ENTERING_DFU - status.value = "Entering DFU mode…" - log("sending mdf? (enter DFU / SMP advertising)") - - if (!connection.send(NusPacket.enterDfu())) { - fail("mdf? write failed") - return - } - - // The device answers rdf: and then drops the link on its own. Either event moves us on; - // the timeout covers the case where the disconnect beats the notification. - val timeout = Runnable { - if (dfuEntryHandled) return@Runnable - log("no rdf: response within ${RDF_TIMEOUT_MS / 1000}s — continuing anyway") - proceedToDfuScan() - } - rdfTimeout = timeout - handler.postDelayed(timeout, RDF_TIMEOUT_MS) - } - - private fun onNusNotification(packet: ByteArray) { - val tag = NusPacket.tagOf(packet) - if (tag == null) { - log("rx: bad CRC (${packet.size} bytes)") - return - } - if (phase.value == DfuPhase.ENTERING_DFU && tag == "rdf:") { - // Payload is a u16 status: 0x0000 accepted, 0xFFFF already in DFU advertising. - val already = packet.size >= 6 && - packet[4] == 0xFF.toByte() && packet[5] == 0xFF.toByte() - log(if (already) "rdf: device was already in DFU mode" else "rdf: DFU mode accepted") - handler.postDelayed({ proceedToDfuScan() }, 500) - } else { - log("rx: $tag") - } - } - - private fun onNusDisconnected() { - when (phase.value) { - DfuPhase.ENTERING_DFU -> { - log("device disconnected (switching to SMP advertising)") - proceedToDfuScan() - } - - DfuPhase.CONNECTING, DfuPhase.CONNECTED -> fail("device disconnected") - else -> Unit - } - } - - /** Tears down the NUS link and starts looking for the device in DFU mode. Runs once. */ - private fun proceedToDfuScan() { - if (dfuEntryHandled) return - dfuEntryHandled = true - rdfTimeout?.let { handler.removeCallbacks(it) } - rdfTimeout = null - closeNus() - - phase.value = DfuPhase.SEARCHING_DFU - status.value = "Looking for the device in DFU mode…" - handler.postDelayed({ scanForDfuDevice() }, RESCAN_DELAY_MS) - } - - private fun scanForDfuDevice() { - if (phase.value != DfuPhase.SEARCHING_DFU) return - val wanted = target.value - log("scanning for SMP advertising (up to ${DFU_SCAN_TIMEOUT_MS / 1000}s)…") - - scanner.start( - timeoutMs = DFU_SCAN_TIMEOUT_MS, - onResult = { found -> - if (!found.inDfuMode || phase.value != DfuPhase.SEARCHING_DFU) return@start - dfuCandidates[found.address] = found - if (wanted == null || found.name == wanted.name || found.address == wanted.address) { - scanner.stop() - log("found ${found.name} (${found.address}) in DFU mode") - startUpload(found.device) - } - }, - onFinished = { error -> - if (phase.value != DfuPhase.SEARCHING_DFU) return@start - // The device may advertise under a different address after the reset. If exactly - // one SMP device showed up, it is unambiguous — use it. - val onlyCandidate = dfuCandidates.values.singleOrNull() - when { - error != null -> fail(error) - onlyCandidate != null -> { - log("no name match; using the only SMP device found: ${onlyCandidate.name}") - startUpload(onlyCandidate.device) - } - - else -> fail("device not found in DFU mode — is it still advertising?") - } - }, - ) - } - - private fun startUpload(device: BluetoothDevice) { - val pkg = firmware.value ?: run { - fail("firmware not loaded") - return - } - - phase.value = DfuPhase.UPLOADING - status.value = "Uploading…" - log("uploading ${pkg.sizeBytes} bytes over SMP") - - val bleTransport = McuMgrBleTransport(appContext, device).apply { - setLoggingEnabled(true) - } - transport = bleTransport - - val manager = FirmwareUpgradeManager(bleTransport, upgradeCallback).apply { - // TEST_ONLY matches the Go tool: mark the image for test, then reset. TEST_AND_CONFIRM - // is not usable here because the device advertises NUS again after rebooting, so the - // library could never reconnect over SMP to send the confirm. - setMode(FirmwareUpgradeManager.Mode.TEST_ONLY) - } - upgradeManager = manager - - val settings = FirmwareUpgradeManager.Settings.Builder() - .setMemoryAlignment(MEMORY_ALIGNMENT) - .setWindowCapacity(1) - .build() - - try { - manager.start(ImageSet().add(pkg.image), settings) - } catch (e: McuMgrException) { - fail("image rejected: ${e.message}") - } - } - - fun cancelDfu() { - upgradeManager?.takeIf { it.isInProgress }?.cancel() - } - - private val upgradeCallback = object : FirmwareUpgradeCallback { - - override fun onUpgradeStarted(controller: FirmwareUpgradeController?) { - log("SMP upgrade started") - } - - override fun onStateChanged( - prevState: FirmwareUpgradeManager.State?, - newState: FirmwareUpgradeManager.State?, - ) { - log("state: ${newState?.name ?: "?"}") - status.value = when (newState) { - FirmwareUpgradeManager.State.VALIDATE -> "Validating image…" - FirmwareUpgradeManager.State.UPLOAD -> "Uploading…" - FirmwareUpgradeManager.State.TEST -> "Marking image for test…" - FirmwareUpgradeManager.State.RESET -> "Resetting device…" - FirmwareUpgradeManager.State.CONFIRM -> "Confirming image…" - else -> status.value - } - } - - override fun onUploadProgressChanged(sent: Int, imageSize: Int, timestamp: Long) { - bytesSent.value = sent - progress.value = if (imageSize > 0) sent.toFloat() / imageSize else 0f - } - - override fun onUpgradeCompleted() { - progress.value = 1f - phase.value = DfuPhase.COMPLETED - status.value = "Done — device is rebooting into the new image" - log("DFU complete; MCUboot will swap on boot") - releaseTransport() - } - - override fun onUpgradeFailed( - state: FirmwareUpgradeManager.State?, - error: McuMgrException?, - ) { - fail("DFU failed in ${state?.name ?: "?"}: ${error?.message ?: error.toString()}") - } - - override fun onUpgradeCanceled(state: FirmwareUpgradeManager.State?) { - phase.value = DfuPhase.FAILED - status.value = "DFU canceled" - log("DFU canceled in ${state?.name ?: "?"}") - releaseTransport() - } - } - - // ── Lifecycle / helpers ───────────────────────────────────────────────────────────────── - - fun reset() { - scanner.stop() - closeNus() - releaseTransport() - rdfTimeout?.let { handler.removeCallbacks(it) } - rdfTimeout = null - dfuEntryHandled = false - dfuCandidates.clear() - devices.clear() - target.value = null - progress.value = 0f - bytesSent.value = 0 - phase.value = DfuPhase.IDLE - status.value = "Ready" - } - - fun shutdown() { - scanner.stop() - closeNus() - releaseTransport() - rdfTimeout?.let { handler.removeCallbacks(it) } - rdfTimeout = null - } - - private fun closeNus() { - nus?.close() - nus = null - } - - private fun releaseTransport() { - upgradeManager = null - transport?.let { - try { - it.release() - } catch (_: Exception) { - // Already released or never connected. - } - } - transport = null - } - - private fun fail(message: String) { - phase.value = DfuPhase.FAILED - status.value = message - log("FAILED: $message") - scanner.stop() - closeNus() - releaseTransport() - } - - private fun log(message: String) { - logLines.add("${timeFormat.format(Date())} $message") - while (logLines.size > MAX_LOG_LINES) logLines.removeAt(0) - } -} diff --git a/app/src/main/java/com/medithings/vesiscan/firmware/DfuNus.kt b/app/src/main/java/com/medithings/vesiscan/firmware/DfuNus.kt deleted file mode 100644 index f02807d..0000000 --- a/app/src/main/java/com/medithings/vesiscan/firmware/DfuNus.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * MEDiDFU — VesiSeek firmware updater - * - * VesiSeek BLE identifiers and the NUS command framing shared with the firmware. - * - * Author: Charles KWON OhJun - * MEDiThings Inc. - */ -package com.medithings.vesiscan.firmware -import java.util.UUID - -/** - * VesiSeek BLE identifiers. - * - * During normal operation the device advertises the Nordic UART Service. After the `mdf?` command - * it disconnects and re-advertises with the Zephyr SMP service instead, keeping the same - * advertised name (its serial number). - */ -object VesiSeekUuids { - val NUS_SERVICE: UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") - /** host -> device (write) */ - val NUS_WRITE: UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E") - /** device -> host (notify) */ - val NUS_NOTIFY: UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E") - val CCCD: UUID = UUID.fromString("00002902-0000-1000-8000-00805F9B34FB") - /** Zephyr SMP-over-BLE service, advertised only in DFU mode. */ - val SMP_SERVICE: UUID = UUID.fromString("8D53DC1D-1DB7-4CD3-868B-8A527460AA84") -} - -/** - * CRC-16/CCITT (poly 0x1021, init 0xFFFF) — byte-for-byte identical to the firmware's - * `cmd_crc16_compute` (Nordic SDK `crc16_compute`). - */ -object Crc16 { - fun compute(data: ByteArray): Int { - var crc = 0xFFFF - for (byte in data) { - crc = crc xor ((byte.toInt() and 0xFF) shl 8) - repeat(8) { - crc = if ((crc and 0x8000) != 0) (crc shl 1) xor 0x1021 else crc shl 1 - crc = crc and 0xFFFF - } - } - return crc - } - - /** Appends the CRC little-endian, matching the firmware's packet layout. */ - fun appendTo(data: ByteArray): ByteArray { - val crc = compute(data) - return data + byteArrayOf((crc and 0xFF).toByte(), ((crc shr 8) and 0xFF).toByte()) - } -} - -/** NUS packet framing: `[TAG 4B][DATA N][CRC16 2B little-endian]`. */ -object NusPacket { - - fun build(tag: String, data: ByteArray = ByteArray(0)): ByteArray { - require(tag.length == 4) { "tag must be 4 characters, got '$tag'" } - return Crc16.appendTo(tag.toByteArray(Charsets.US_ASCII) + data) - } - - /** - * Enter-DFU command. The firmware ignores the payload but the command dispatcher needs at - * least one data byte, so a single 0x00 is sent — the same packet the Go host tool uses. - */ - fun enterDfu(): ByteArray = build("mdf?", byteArrayOf(0x00)) - - /** Returns the 4-character response tag, or null if the frame is too short or the CRC fails. */ - fun tagOf(packet: ByteArray): String? { - if (packet.size < 6) return null - val body = packet.copyOfRange(0, packet.size - 2) - val received = (packet[packet.size - 2].toInt() and 0xFF) or - ((packet[packet.size - 1].toInt() and 0xFF) shl 8) - if (Crc16.compute(body) != received) return null - return String(packet, 0, 4, Charsets.US_ASCII) - } -} diff --git a/app/src/main/java/com/medithings/vesiscan/firmware/DfuNusConnection.kt b/app/src/main/java/com/medithings/vesiscan/firmware/DfuNusConnection.kt deleted file mode 100644 index 9a5f4dc..0000000 --- a/app/src/main/java/com/medithings/vesiscan/firmware/DfuNusConnection.kt +++ /dev/null @@ -1,193 +0,0 @@ -/* - * MEDiDFU — VesiSeek firmware updater - * - * GATT client for the Nordic UART Service command channel, used only to hand the device - * into DFU mode. The firmware image itself travels over SMP, not over this link. - * - * Author: Charles KWON OhJun - * MEDiThings Inc. - */ -package com.medithings.vesiscan.firmware -import android.annotation.SuppressLint -import android.bluetooth.BluetoothDevice -import android.bluetooth.BluetoothGatt -import android.bluetooth.BluetoothGattCallback -import android.bluetooth.BluetoothGattCharacteristic -import android.bluetooth.BluetoothGattDescriptor -import android.bluetooth.BluetoothProfile -import android.bluetooth.BluetoothStatusCodes -import android.content.Context -import android.os.Build -import android.os.Handler -import android.os.Looper - -/** - * GATT client for the VesiSeek NUS command channel. - * - * Mirrors the connection sequence of the VesiScan Basic app: connect, negotiate MTU 247, discover - * services, then enable notifications on the TX characteristic. [onReady] fires once the CCCD - * write completes, at which point [send] may be used. - * - * All callbacks are delivered on the main thread. - */ -@SuppressLint("MissingPermission") -class NusConnection( - context: Context, - private val onReady: () -> Unit, - private val onNotify: (ByteArray) -> Unit, - private val onDisconnected: () -> Unit, - private val onError: (String) -> Unit, -) { - private val appContext = context.applicationContext - private val handler = Handler(Looper.getMainLooper()) - - @Volatile private var gatt: BluetoothGatt? = null - @Volatile private var writeChar: BluetoothGattCharacteristic? = null - @Volatile private var released = false - - val isReady: Boolean get() = writeChar != null - - fun connect(device: BluetoothDevice) { - released = false - gatt = device.connectGatt(appContext, false, gattCallback, BluetoothDevice.TRANSPORT_LE) - if (gatt == null) onError("connectGatt() returned null") - } - - fun send(data: ByteArray): Boolean { - val g = gatt ?: return false - val ch = writeChar ?: return false - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - g.writeCharacteristic(ch, data, BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) == - BluetoothStatusCodes.SUCCESS - } else { - @Suppress("DEPRECATION") - run { - ch.value = data - ch.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE - g.writeCharacteristic(ch) - } - } - } - - /** - * Tears the connection down. Further GATT callbacks are ignored, so [onDisconnected] will not - * fire for a close initiated here. Safe to call more than once. - */ - fun close() { - released = true - writeChar = null - gatt?.let { g -> - try { - g.disconnect() - g.close() - } catch (_: Exception) { - // Nothing useful to do if the stack already dropped the client. - } - } - gatt = null - } - - private val gattCallback = object : BluetoothGattCallback() { - - override fun onConnectionStateChange(g: BluetoothGatt, status: Int, newState: Int) { - if (released) return - handler.post { - if (released) return@post - when { - newState == BluetoothProfile.STATE_CONNECTED && - status == BluetoothGatt.GATT_SUCCESS -> { - // Service discovery continues from onMtuChanged. - if (!g.requestMtu(247)) g.discoverServices() - } - - newState == BluetoothProfile.STATE_DISCONNECTED -> { - writeChar = null - onDisconnected() - } - - else -> onError("GATT error (status $status)") - } - } - } - - override fun onMtuChanged(g: BluetoothGatt, mtu: Int, status: Int) { - if (released) return - handler.post { if (!released) g.discoverServices() } - } - - override fun onServicesDiscovered(g: BluetoothGatt, status: Int) { - if (released) return - handler.post { - if (released) return@post - if (status != BluetoothGatt.GATT_SUCCESS) { - onError("Service discovery failed (status $status)") - return@post - } - val service = g.getService(VesiSeekUuids.NUS_SERVICE) - if (service == null) { - onError("NUS service not found on this device") - return@post - } - writeChar = service.getCharacteristic(VesiSeekUuids.NUS_WRITE) - val notifyChar = service.getCharacteristic(VesiSeekUuids.NUS_NOTIFY) - if (writeChar == null || notifyChar == null) { - onError("NUS characteristics not found") - return@post - } - g.setCharacteristicNotification(notifyChar, true) - val cccd = notifyChar.getDescriptor(VesiSeekUuids.CCCD) - if (cccd == null) { - // No CCCD to write — notifications are already enabled locally. - onReady() - return@post - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - g.writeDescriptor(cccd, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) - } else { - @Suppress("DEPRECATION") - run { - cccd.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - g.writeDescriptor(cccd) - } - } - } - } - - override fun onDescriptorWrite( - g: BluetoothGatt, - descriptor: BluetoothGattDescriptor, - status: Int, - ) { - if (released || descriptor.uuid != VesiSeekUuids.CCCD) return - handler.post { - if (released) return@post - if (status == BluetoothGatt.GATT_SUCCESS) { - onReady() - } else { - onError("Enabling notifications failed (status $status)") - } - } - } - - override fun onCharacteristicChanged( - g: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - value: ByteArray, - ) { - if (released || characteristic.uuid != VesiSeekUuids.NUS_NOTIFY) return - handler.post { if (!released) onNotify(value) } - } - - @Deprecated("Superseded by the API 33 overload") - override fun onCharacteristicChanged( - g: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - ) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) return - if (released || characteristic.uuid != VesiSeekUuids.NUS_NOTIFY) return - @Suppress("DEPRECATION") - val value = characteristic.value ?: return - handler.post { if (!released) onNotify(value) } - } - } -} diff --git a/app/src/main/java/com/medithings/vesiscan/firmware/FirmwarePackage.kt b/app/src/main/java/com/medithings/vesiscan/firmware/FirmwarePackage.kt deleted file mode 100644 index 0cf7aca..0000000 --- a/app/src/main/java/com/medithings/vesiscan/firmware/FirmwarePackage.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * MEDiDFU — VesiSeek firmware updater - * - * Unpacks the DFU archive bundled in assets/ and extracts the signed MCUboot image. - * - * Author: Charles KWON OhJun - * MEDiThings Inc. - */ -package com.medithings.vesiscan.firmware -import android.content.Context -import org.json.JSONObject -import java.io.ByteArrayOutputStream -import java.util.zip.ZipInputStream - -/** A signed MCUboot application image unpacked from a `dfu_application_*.zip`. */ -data class FirmwarePackage( - val assetName: String, - val imageFileName: String, - /** `version_MCUBOOT` from the manifest, e.g. "0.0.2+35". Empty when the manifest omits it. */ - val version: String, - val image: ByteArray, -) { - val sizeBytes: Int get() = image.size - - // Generated equals/hashCode would compare the ByteArray by reference; identify the package by - // its source instead. - override fun equals(other: Any?): Boolean = - this === other || (other is FirmwarePackage && - assetName == other.assetName && - imageFileName == other.imageFileName && - version == other.version && - image.size == other.image.size) - - override fun hashCode(): Int = - (((assetName.hashCode() * 31 + imageFileName.hashCode()) * 31) + version.hashCode()) * 31 + - image.size -} - -/** - * Reads a DFU zip bundled in `assets/`. - * - * The zip is the nRF Connect SDK / Zephyr layout: a `manifest.json` listing the images plus the - * signed binaries themselves. The application image (`image_index` 0, or `type` "application") is - * the one uploaded over SMP. - */ -object FirmwareLoader { - - const val DEFAULT_ASSET = "dfu_application_1.0.0+5.zip" - - /** - * 번들된 DFU 버전 (manifest.json 의 version_MCUBOOT 필드와 일치). - * 2026-08-04: BleManager 의 update-available 배너가 이 값 vs 런타임 FW 를 비교. - */ - const val BUNDLED_VERSION = "1.0.0+5" - - private const val MANIFEST = "manifest.json" - - @Throws(IllegalStateException::class) - fun loadFromAssets(context: Context, assetName: String = DEFAULT_ASSET): FirmwarePackage { - val entries = readZipEntries(context, assetName) - - val manifestBytes = entries.entries - .firstOrNull { it.key.equals(MANIFEST, ignoreCase = true) } - ?.value - ?: error("$MANIFEST not found in $assetName") - - val files = JSONObject(String(manifestBytes, Charsets.UTF_8)).optJSONArray("files") - ?: error("$MANIFEST has no \"files\" array") - check(files.length() > 0) { "$MANIFEST lists no images" } - - var chosen = files.getJSONObject(0) - for (i in 0 until files.length()) { - val entry = files.getJSONObject(i) - if (entry.optString("image_index") == "0" || - entry.optString("type").equals("application", ignoreCase = true) - ) { - chosen = entry - break - } - } - - val fileName = chosen.optString("file") - check(fileName.isNotEmpty()) { "$MANIFEST entry has no \"file\" field" } - val image = entries[fileName] ?: error("$fileName listed in $MANIFEST but missing from the zip") - check(image.isNotEmpty()) { "$fileName is empty" } - - return FirmwarePackage( - assetName = assetName, - imageFileName = fileName, - version = chosen.optString("version_MCUBOOT"), - image = image, - ) - } - - private fun readZipEntries(context: Context, assetName: String): Map { - val entries = LinkedHashMap() - ZipInputStream(context.assets.open(assetName)).use { zip -> - val buffer = ByteArray(16 * 1024) - while (true) { - val entry = zip.nextEntry ?: break - if (entry.isDirectory) { - zip.closeEntry() - continue - } - val out = ByteArrayOutputStream() - while (true) { - val read = zip.read(buffer) - if (read < 0) break - out.write(buffer, 0, read) - } - entries[entry.name] = out.toByteArray() - zip.closeEntry() - } - } - return entries - } -} diff --git a/app/src/main/java/com/medithings/vesiscan/firmware/ui/FirmwareUpdateView.kt b/app/src/main/java/com/medithings/vesiscan/firmware/ui/FirmwareUpdateView.kt deleted file mode 100644 index 4e189d9..0000000 --- a/app/src/main/java/com/medithings/vesiscan/firmware/ui/FirmwareUpdateView.kt +++ /dev/null @@ -1,509 +0,0 @@ -/* - * VesiScan firmware updater — MEDiDFU 이식 (2026-08-03). - * Author: Charles KWON OhJun · adapt: dw.jang - * - * VesiScan 앱 통합: 설정 > 앱정보 > "펌웨어 업데이트" 진입점. - * FirmwareUpdateScreen() = 권한 · manager 라이프사이클 처리하는 host composable. - * DfuScreen() = 원본 UI (scan · connect · upload · log). - */ -package com.medithings.vesiscan.firmware.ui -import android.Manifest -import android.content.pm.PackageManager -import android.os.Build -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.material3.ButtonDefaults -import androidx.compose.ui.graphics.Brush -import com.medithings.vesiscan.ui.theme.MlBackground -import com.medithings.vesiscan.ui.theme.MlCardBackground -import com.medithings.vesiscan.ui.theme.MlCritical -import com.medithings.vesiscan.ui.theme.MlPrimary -import com.medithings.vesiscan.ui.theme.MlSecondaryText -import com.medithings.vesiscan.ui.theme.MlSuccess -import com.medithings.vesiscan.ui.theme.MlTeal -import com.medithings.vesiscan.ui.theme.MlWarning -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material3.Button -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.LinearProgressIndicator -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.content.ContextCompat -import com.medithings.vesiscan.firmware.ScannedDevice -import com.medithings.vesiscan.firmware.DfuManager -import com.medithings.vesiscan.firmware.DfuPhase -import kotlin.math.roundToInt - -/** - * VesiScan 통합용 host — 권한 · manager 생성/해제 · 뒤로가기 처리. - * MEDiDFU 의 MainActivity.DfuApp() 상당. - */ -@Composable -fun FirmwareUpdateScreen(onBack: () -> Unit, modifier: Modifier = Modifier) { - val context = LocalContext.current - val manager = remember { DfuManager(context) } - - val perms: Array = remember { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT) - } else { - arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) - } - } - - var granted by remember { - mutableStateOf(perms.all { - ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED - }) - } - val launcher = rememberLauncherForActivityResult( - ActivityResultContracts.RequestMultiplePermissions() - ) { result -> granted = result.values.all { it } } - - LaunchedEffect(Unit) { - manager.loadFirmware() - if (!granted) { - launcher.launch(perms) - return@LaunchedEffect - } - - // 이미 메인 앱이 연결된 기기가 있으면 스캔 생략 · 자동 재연결로 UX 단축 (2026-08-03). - val bleManager = com.medithings.vesiscan.ble.BleManager.getInstance(context) - val preConnectedDevice = if (bleManager.isConnected.value) bleManager.currentBluetoothDevice else null - val preConnectedName = bleManager.connectedDeviceName.value - - // 메인 앱 BLE 연결 해제 — 프로브가 연결 중이면 광고 중단되어 스캔 안 보임. - runCatching { bleManager.disconnect() } - - // 이미 알던 기기가 있으면 스캔 없이 바로 재연결 시도. - if (preConnectedDevice != null && preConnectedName.isNotEmpty()) { - kotlinx.coroutines.delay(1500) // BLE stack 정리 · 재광고 대기 - manager.connectDirectly(preConnectedDevice, preConnectedName) - } - } - DisposableEffect(Unit) { onDispose { manager.shutdown() } } - - Column(modifier = modifier.fillMaxSize().background(MlBackground)) { - Row( - modifier = Modifier.fillMaxWidth().padding(horizontal = 4.dp, vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - IconButton(onClick = onBack) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "뒤로", tint = MlPrimary) - } - Text("펌웨어 업데이트", style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold) - } - if (granted) { - DfuScreen(manager = manager, modifier = Modifier.fillMaxSize()) - } else { - Column( - modifier = Modifier.fillMaxSize().padding(24.dp), - verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterVertically), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - "펌웨어 업데이트에는 Bluetooth 권한이 필요합니다.", - style = MaterialTheme.typography.bodyMedium, - color = MlSecondaryText, - ) - PrimaryGradientButton(text = "권한 허용", onClick = { launcher.launch(perms) }) - } - } - } -} - -/** 앱 스타일 통일 primary 버튼 (MlTeal → MlPrimary gradient · rounded 14). */ -@Composable -private fun PrimaryGradientButton( - text: String, - onClick: () -> Unit, - enabled: Boolean = true, - modifier: Modifier = Modifier, -) { - Button( - onClick = onClick, - enabled = enabled, - modifier = modifier.heightIn(min = 48.dp), - shape = RoundedCornerShape(14.dp), - colors = ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - disabledContainerColor = Color.Transparent, - ), - contentPadding = PaddingValues(), - ) { - Box( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 48.dp) - .background( - brush = if (enabled) - Brush.horizontalGradient(listOf(MlTeal, MlPrimary)) - else Brush.horizontalGradient(listOf(Color(0xFFCCCCCC), Color(0xFFAAAAAA))), - shape = RoundedCornerShape(14.dp), - ) - .padding(horizontal = 20.dp, vertical = 12.dp), - contentAlignment = Alignment.Center, - ) { - Text(text, color = Color.White, fontWeight = FontWeight.SemiBold, fontSize = 15.sp) - } - } -} - -/** Phase → 사용자용 한글 라벨 + 상태 색상. */ -private fun phaseKo(phase: DfuPhase): Pair = when (phase) { - DfuPhase.IDLE -> "대기 중" to MlSecondaryText - DfuPhase.SCANNING -> "기기 검색 중…" to MlWarning - DfuPhase.CONNECTING -> "연결 중…" to MlWarning - DfuPhase.CONNECTED -> "연결됨 · 업데이트 준비 완료" to MlSuccess - DfuPhase.ENTERING_DFU -> "DFU 모드 진입 중…" to MlPrimary - DfuPhase.SEARCHING_DFU -> "DFU 모드 확인 중…" to MlPrimary - DfuPhase.UPLOADING -> "업데이트 진행 중…" to MlPrimary - DfuPhase.COMPLETED -> "완료 ✓" to MlSuccess - DfuPhase.FAILED -> "실패" to MlCritical -} - -@Composable -fun DfuScreen(manager: DfuManager, modifier: Modifier = Modifier) { - val phase by manager.phase - val status by manager.status - val firmware by manager.firmware - val firmwareError by manager.firmwareError - val progress by manager.progress - val bytesSent by manager.bytesSent - val target by manager.target - - val cardShape = RoundedCornerShape(16.dp) - val cardColors = CardDefaults.cardColors(containerColor = MlCardBackground) - - Column( - modifier = modifier - .fillMaxSize() - .background(MlBackground) - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - // ── 스캔 실패 원인 안내 (블루투스 꺼짐 등) ──────────────────────────────────────── - val blocker = manager.bleBlockingCondition() - if (blocker != null) { - Card( - modifier = Modifier.fillMaxWidth(), - shape = cardShape, - colors = CardDefaults.cardColors(containerColor = MlCritical.copy(alpha = 0.10f)), - ) { - Text( - blocker, - modifier = Modifier.padding(14.dp), - style = MaterialTheme.typography.bodyMedium, - color = MlCritical, - fontWeight = FontWeight.Medium, - ) - } - } - - // ── 펌웨어 정보 (APK 번들) ──────────────────────────────────────────────────────── - Card(modifier = Modifier.fillMaxWidth(), shape = cardShape, colors = cardColors) { - Column(Modifier.padding(14.dp)) { - Text("펌웨어 정보", style = MaterialTheme.typography.labelLarge, color = MlSecondaryText) - Spacer(Modifier.height(6.dp)) - val fw = firmware - when { - fw != null -> { - val ver = if (fw.version.isNotEmpty()) "v${fw.version}" else "버전 정보 없음" - val sizeKb = fw.sizeBytes / 1024 - Text("$ver · ${sizeKb} KB", - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.SemiBold) - Spacer(Modifier.height(2.dp)) - Text(fw.imageFileName, - style = MaterialTheme.typography.bodySmall, - color = MlSecondaryText) - } - - firmwareError != null -> Text( - firmwareError ?: "", - style = MaterialTheme.typography.bodySmall, - color = MlCritical, - ) - - else -> Text("불러오는 중…", - style = MaterialTheme.typography.bodySmall, - color = MlSecondaryText) - } - } - } - - // ── 상태 + 진행률 ───────────────────────────────────────────────────────────────── - Card(modifier = Modifier.fillMaxWidth(), shape = cardShape, colors = cardColors) { - Column(Modifier.padding(14.dp)) { - Text("기기 상태", style = MaterialTheme.typography.labelLarge, color = MlSecondaryText) - Spacer(Modifier.height(6.dp)) - val (phaseLabel, phaseColor) = phaseKo(phase) - Row(verticalAlignment = Alignment.CenterVertically) { - Box( - modifier = Modifier - .size(10.dp) - .background(phaseColor, shape = RoundedCornerShape(50)), - ) - Spacer(Modifier.width(8.dp)) - Text(phaseLabel, - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.SemiBold, - color = phaseColor) - } - if (status.isNotEmpty()) { - Spacer(Modifier.height(4.dp)) - Text(status, style = MaterialTheme.typography.bodySmall, color = MlSecondaryText) - } - target?.let { - Spacer(Modifier.height(4.dp)) - Text("기기: ${it.name}", - style = MaterialTheme.typography.bodySmall, - color = MlSecondaryText) - } - if (phase == DfuPhase.UPLOADING || phase == DfuPhase.COMPLETED) { - Spacer(Modifier.height(10.dp)) - LinearProgressIndicator( - progress = { progress }, - modifier = Modifier.fillMaxWidth().height(8.dp), - color = MlPrimary, - trackColor = MlPrimary.copy(alpha = 0.15f), - ) - Spacer(Modifier.height(6.dp)) - val total = firmware?.sizeBytes ?: 0 - val sentKb = bytesSent / 1024 - val totalKb = total / 1024 - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Text("${(progress * 100).roundToInt()}%", - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.SemiBold, - color = MlPrimary) - Text("$sentKb KB / $totalKb KB", - style = MaterialTheme.typography.bodySmall, - color = MlSecondaryText) - } - } - } - } - - // ── 액션 버튼 (primary 는 gradient · secondary 는 outline) ─────────────────────── - // 2026-08-03: auto-connect 로 대부분 target 즉시 설정됨. target 없을 때만 Scan 노출. - val hasTarget = target != null - val outlineColors = ButtonDefaults.outlinedButtonColors(contentColor = MlPrimary) - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - // 주 액션: 업데이트 시작 (조건부 gradient primary) - if (phase != DfuPhase.UPLOADING && phase != DfuPhase.COMPLETED && phase != DfuPhase.FAILED) { - PrimaryGradientButton( - text = "업데이트 시작", - onClick = { manager.startDfu() }, - enabled = manager.canStartDfu, - modifier = Modifier.fillMaxWidth(), - ) - } - - // 보조 액션 (조건부) - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - if (!hasTarget || phase == DfuPhase.IDLE || phase == DfuPhase.SCANNING) { - if (phase == DfuPhase.SCANNING) { - OutlinedButton( - onClick = { manager.stopScan() }, - shape = RoundedCornerShape(12.dp), - colors = outlineColors, - ) { Text("검색 중지") } - } else { - OutlinedButton( - onClick = { manager.startScan() }, - enabled = !manager.isBusy, - shape = RoundedCornerShape(12.dp), - colors = outlineColors, - ) { Text("기기 검색") } - } - } - if (phase == DfuPhase.CONNECTED) { - OutlinedButton( - onClick = { manager.disconnect() }, - shape = RoundedCornerShape(12.dp), - colors = outlineColors, - ) { Text("연결 해제") } - } - if (phase == DfuPhase.UPLOADING) { - OutlinedButton( - onClick = { manager.cancelDfu() }, - shape = RoundedCornerShape(12.dp), - colors = ButtonDefaults.outlinedButtonColors(contentColor = MlCritical), - ) { Text("취소") } - } - if (phase == DfuPhase.COMPLETED || phase == DfuPhase.FAILED) { - OutlinedButton( - onClick = { manager.reset() }, - shape = RoundedCornerShape(12.dp), - colors = outlineColors, - ) { Text("초기화") } - } - } - } - - // ── 발견된 기기 목록 (auto-connect 실패 · 첫 사용) ─────────────────────────────── - if (!hasTarget) { - Text( - "발견된 기기 (${manager.devices.size})", - style = MaterialTheme.typography.labelLarge, - color = MlSecondaryText, - ) - Card( - modifier = Modifier.fillMaxWidth().heightIn(min = 80.dp, max = 220.dp), - shape = cardShape, - colors = cardColors, - ) { - if (manager.devices.isEmpty()) { - Text( - when (phase) { - DfuPhase.SCANNING -> "검색 중…" - else -> "기기가 없습니다. 검색을 눌러주세요." - }, - modifier = Modifier.padding(14.dp), - style = MaterialTheme.typography.bodySmall, - color = MlSecondaryText, - ) - } else { - LazyColumn { - items(manager.devices, key = { it.address }) { device -> - DeviceRow( - device = device, - enabled = !manager.isBusy, - onClick = { manager.connect(device) }, - ) - HorizontalDivider(color = MlBackground) - } - } - } - } - } - - // ── 상세 로그 (개발자용 · 그대로 유지) ──────────────────────────────────────────── - Text("상세 로그", style = MaterialTheme.typography.labelLarge, color = MlSecondaryText) - LogView( - lines = manager.logLines, - modifier = Modifier.fillMaxWidth().weight(1f), - ) - } -} - -@Composable -private fun DeviceRow(device: ScannedDevice, enabled: Boolean, onClick: () -> Unit) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 14.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Column(Modifier.weight(1f)) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(device.name, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.SemiBold) - if (device.inDfuMode) { - Spacer(Modifier.width(6.dp)) - Surface( - color = MlTeal.copy(alpha = 0.15f), - shape = RoundedCornerShape(6.dp), - ) { - Text( - "DFU 모드", - modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp), - style = MaterialTheme.typography.labelSmall, - color = MlTeal, - fontWeight = FontWeight.SemiBold, - ) - } - } - } - Spacer(Modifier.height(2.dp)) - Text( - "${device.rssi} dBm", - style = MaterialTheme.typography.bodySmall, - color = MlSecondaryText, - ) - } - OutlinedButton( - onClick = onClick, - enabled = enabled, - shape = RoundedCornerShape(10.dp), - colors = ButtonDefaults.outlinedButtonColors(contentColor = MlPrimary), - ) { Text("연결", fontWeight = FontWeight.SemiBold) } - } -} - -@Composable -private fun LogView(lines: List, modifier: Modifier = Modifier) { - val listState = rememberLazyListState() - LaunchedEffect(lines.size) { - if (lines.isNotEmpty()) listState.animateScrollToItem(lines.size - 1) - } - Card( - modifier = modifier, - shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = MlSecondaryText.copy(alpha = 0.08f)), - ) { - LazyColumn( - state = listState, - modifier = Modifier - .fillMaxSize() - .background(Color.Transparent) - .padding(10.dp), - ) { - itemsIndexed(lines) { _, line -> - Text( - line, - fontFamily = FontFamily.Monospace, - fontSize = 11.sp, - fontWeight = FontWeight.Normal, - color = MlSecondaryText, - style = MaterialTheme.typography.bodySmall, - ) - } - } - } -} diff --git a/app/src/main/java/com/medithings/vesiscan/ui/components/FirmwareWarningBanner.kt b/app/src/main/java/com/medithings/vesiscan/ui/components/FirmwareWarningBanner.kt index 6bc8d60..e45b5a8 100644 --- a/app/src/main/java/com/medithings/vesiscan/ui/components/FirmwareWarningBanner.kt +++ b/app/src/main/java/com/medithings/vesiscan/ui/components/FirmwareWarningBanner.kt @@ -1,7 +1,6 @@ package com.medithings.vesiscan.ui.components import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -32,28 +31,30 @@ import com.medithings.vesiscan.ble.BleManager import kotlinx.coroutines.delay /** - * 펌웨어 상태 배너 — PlacementGuide / PiezoMonitoring 상단에 노출. + * 기기 응답 배너 — PlacementGuide / PiezoMonitoring 상단에 노출. * * 표시 케이스: - * (1) 펌웨어 구버전 (build < MIN_FIRMWARE_BUILD) — 주황 경고 - * (2) 연결 후 8초 넘게 mid? 응답 미수신 — 빨강 경고 (펌웨어가 mid 미지원) - * (3) 정상 또는 미연결 — 안 보임 + * (1) 연결 후 8초 넘게 mid? 응답 미수신이고 최근 12초간 수신도 없음 — 빨강 "기기 응답 없음" + * (2) 정상 또는 미연결 — 안 보임 + * + * 2026-10-13: 펌웨어 버전 판정(최소빌드 118 "구버전" 주황 · 번들 DFU "새 펌웨어" 파랑)을 뺐다. + * 임상앱은 펌웨어 버전을 세션 기록에 남길 뿐 판정하지 않는다 — 판정과 DFU 는 같은 폰의 + * 사용자 앱이 맡는다. 양산 펌웨어(VB0FW0100)는 0100 부터 다시 세므로 옛 규칙이 거짓 경고를 냈다. */ @Composable fun FirmwareWarningBanner( bleManager: BleManager, modifier: Modifier = Modifier, - onUpdateAvailableTap: (() -> Unit)? = null, // 2026-08-04 · 파랑 배너 탭 시 DFU 이동 ) { val fw by bleManager.firmwareVersion val isConnected by bleManager.isConnected val lastRxAt by bleManager.lastBleRxAt - // 미연결 상태에선 펌웨어 배너 일절 노출 X. dev bypass / demo mode / 이전 세션 + // 미연결 상태에선 배너 일절 노출 X. dev bypass / demo mode / 이전 세션 // 잔여 firmwareVersion 값으로 인한 false positive 방지. if (!isConnected) return - // (2) 연결됐는데 일정 시간 동안 펌웨어 미수신 추적 + // 연결됐는데 일정 시간 동안 펌웨어 미수신 추적 var timedOut by remember { mutableStateOf(false) } LaunchedEffect(isConnected, fw) { timedOut = false @@ -80,53 +81,26 @@ fun FirmwareWarningBanner( // Watchdog 15초 timeout 이 진짜 disconnect 판정하므로 12초까지는 조용히 대기. val deviceAlive = lastRxAt > 0 && (System.currentTimeMillis() - lastRxAt) < 12_000 - val outdated = bleManager.isFirmwareOutdated - val updateAvailable = bleManager.isFirmwareUpdateAvailable - val showTimedOut = timedOut && !deviceAlive - if (!outdated && !showTimedOut && !updateAvailable) return + if (!(timedOut && !deviceAlive)) return - // 우선순위: outdated (빨강) > timedOut (빨강) > updateAvailable (파랑 · 정보성). - val bgColor = when { - outdated -> Color(0xFFFF9500) // 주황 · 강한 경고 - showTimedOut -> Color(0xFFD32F2F) // 빨강 · 응답 없음 - else -> Color(0xFF1976D2) // 파랑 · 업데이트 사용 가능 - } - val title = when { - outdated -> stringResource(R.string.firmware_outdated_title) - showTimedOut -> stringResource(R.string.firmware_no_response_title) - else -> stringResource(R.string.firmware_update_available_title) - } - val subtitle: String? = when { - outdated -> stringResource(R.string.firmware_outdated_desc, fw, BleManager.MIN_FIRMWARE_BUILD) - showTimedOut -> null - else -> stringResource( - R.string.firmware_update_available_desc, - fw, - com.medithings.vesiscan.firmware.FirmwareLoader.BUNDLED_VERSION, - ) - } - - // 파랑 배너 (update available) 는 탭 가능 · 나머지는 정보 표시만. - val clickableModifier = if (updateAvailable && onUpdateAvailableTap != null) { - Modifier.clickable { onUpdateAvailableTap() } - } else Modifier Row( modifier = modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 6.dp) .clip(RoundedCornerShape(10.dp)) - .background(bgColor) - .then(clickableModifier) + .background(Color(0xFFD32F2F)) // 빨강 · 응답 없음 .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(title, fontSize = 13.sp, fontWeight = FontWeight.Bold, color = Color.White) - if (subtitle != null) { - Text(subtitle, fontSize = 11.sp, color = Color.White.copy(alpha = 0.9f)) - } + Text( + stringResource(R.string.firmware_no_response_title), + fontSize = 13.sp, + fontWeight = FontWeight.Bold, + color = Color.White, + ) } } } diff --git a/app/src/main/java/com/medithings/vesiscan/ui/views/home/HomeView.kt b/app/src/main/java/com/medithings/vesiscan/ui/views/home/HomeView.kt index 080c316..cd5b7c2 100644 --- a/app/src/main/java/com/medithings/vesiscan/ui/views/home/HomeView.kt +++ b/app/src/main/java/com/medithings/vesiscan/ui/views/home/HomeView.kt @@ -173,18 +173,9 @@ fun HomeView(appState: AppState) { Text("병원 임상 측정", color = Color.White, fontWeight = FontWeight.SemiBold) } } - // 2026-08-03 (cloud-mvp 672e679 이식): 프로브 firmware 업데이트 진입점. - TextButton( - onClick = { appState.currentScreen = com.medithings.vesiscan.AppScreen.FIRMWARE_UPDATE }, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 32.dp) - .padding(bottom = 48.dp), - ) { - Text("펌웨어 업데이트 (프로브 firmware)", - color = com.medithings.vesiscan.ui.theme.MlPrimary, - fontWeight = FontWeight.SemiBold, fontSize = 13.sp) - } + // 프로브 펌웨어 업데이트 진입점은 2026-10-13 에 뺐다 — 사용자 앱에서 올린다. + // 버튼이 차지하던 아래 여백(48dp)만 남긴다. + Box(modifier = Modifier.fillMaxWidth().padding(bottom = 48.dp)) {} } } // Box (top-bar gear overlay) close diff --git a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt index 5512593..d20da17 100644 --- a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt @@ -1357,11 +1357,8 @@ fun PiezoMonitoringView(appState: AppState) { // BLE 끊김 banner는 사내 테스트 피드백으로 제거됨 — 백그라운드 자동 재연결만 유지. - // 펌웨어 구버전 경고 - com.medithings.vesiscan.ui.components.FirmwareWarningBanner( - bleManager, - onUpdateAvailableTap = { appState.currentScreen = com.medithings.vesiscan.AppScreen.FIRMWARE_UPDATE }, - ) + // 기기 응답 없음 경고 (버전 판정은 2026-10-13 에 뺐다 — 펌웨어는 사용자 앱이 관리) + com.medithings.vesiscan.ui.components.FirmwareWarningBanner(bleManager) com.medithings.vesiscan.ui.components.BatteryWarningBanner(bleManager) val scrollState = rememberScrollState() diff --git a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt index 2923204..18517ec 100644 --- a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt +++ b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PlacementGuideView.kt @@ -314,11 +314,8 @@ fun PlacementGuideView(appState: AppState) { ) } - // 펌웨어 구버전 경고 - com.medithings.vesiscan.ui.components.FirmwareWarningBanner( - bleManager, - onUpdateAvailableTap = { appState.currentScreen = com.medithings.vesiscan.AppScreen.FIRMWARE_UPDATE }, - ) + // 기기 응답 없음 경고 (버전 판정은 2026-10-13 에 뺐다 — 펌웨어는 사용자 앱이 관리) + com.medithings.vesiscan.ui.components.FirmwareWarningBanner(bleManager) // 배터리 잔량 경고 (<15%) com.medithings.vesiscan.ui.components.BatteryWarningBanner(bleManager) diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index b65559f..06ca848 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -158,12 +158,7 @@ 기기 배터리 부족 현재 %d%% · 측정이 갑자기 중단될 수 있습니다. 즉시 충전하세요. 현재 %d%% · 곧 충전이 필요합니다. - 펌웨어 업데이트 필요 기기 응답 없음 - 현재: %1$s · 필요: VBTFW%2$04d 이상. 측정이 정상 동작하지 않을 수 있습니다. - - 새 펌웨어가 있습니다 - 기기: %1$s · 신규: %2$s. 눌러서 DFU 업데이트를 진행하세요. 잠금 해제됨 — 다시 탭하여 잠금 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7860dac..ea47e02 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -158,12 +158,7 @@ Low battery %d%% · Measurement may stop suddenly. Charge immediately. %d%% · Please charge soon. - Firmware update required No response from device - Current: %1$s · Required: VBTFW%2$04d or higher. Measurement may not work properly. - - New firmware available - Device: %1$s · New: %2$s. Tap to update via DFU. Unlocked — tap again to lock diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 03c9638..da93dd8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,6 @@ rive = "9.4.2" startupRuntime = "1.2.0" lifecycleViewmodelCompose = "2.10.0" # 2026-08-03 (cherry-pick from cloud-mvp): Firmware DFU -mcumgr = "2.5.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -22,9 +21,8 @@ junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } -# 2026-08-03: LocalLifecycleOwner (Compose) 및 mcumgr-ble +# 2026-08-03: LocalLifecycleOwner (Compose) — mcumgr-ble 는 2026-10-13 DFU 제거와 함께 뺐다 androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeKtx" } -mcumgr-ble = { group = "no.nordicsemi.android", name = "mcumgr-ble", version.ref = "mcumgr" } androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }