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 836e54a..c9d385c 100644 --- a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt +++ b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt @@ -39,6 +39,9 @@ class BleManager private constructor(private val context: Context) { instance ?: BleManager(context.applicationContext).also { instance = it } } + /** Logger 같은 context-free 컴포넌트에서 BLE state 읽기용. instance 생성 후에만 non-null. */ + val current: BleManager? get() = instance + val SERVICE_UUID: UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") val TX_CHAR_UUID: UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E") val RX_CHAR_UUID: UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E") @@ -980,12 +983,16 @@ class BleManager private constructor(private val context: Context) { debugLogger.info("DEVICE_INFO $info") // 형식: "VBTHW0100 VBT26040001 VBTFW0111" (HW, Serial, FW) val parts = info.split(Regex("\\s+")).filter { it.isNotBlank() } + val hw = parts.firstOrNull { it.startsWith("VBTHW") } ?: "" + val fw = parts.firstOrNull { it.startsWith("VBTFW") } ?: "" + val sn = parts.firstOrNull { it.startsWith("VBT") && !it.startsWith("VBTHW") && !it.startsWith("VBTFW") } ?: "" handler.post { - parts.firstOrNull { it.startsWith("VBTHW") }?.let { hardwareVersion.value = it } - parts.firstOrNull { it.startsWith("VBTFW") }?.let { firmwareVersion.value = it } - parts.firstOrNull { it.startsWith("VBT") && !it.startsWith("VBTHW") && !it.startsWith("VBTFW") } - ?.let { serialNumber.value = it } + if (hw.isNotEmpty()) hardwareVersion.value = hw + if (fw.isNotEmpty()) firmwareVersion.value = fw + if (sn.isNotEmpty()) serialNumber.value = sn } + // ble.log에 헤더 블록 형태로 (텍스트 에디터로 열었을 때 즉시 보임) + debugLogger.deviceInfo(fw, hw, sn) } "rls:" -> { val state = if (data.size >= 5) data[4].toInt() and 0xFF else -1 diff --git a/app/src/main/java/com/example/medilightv2android/services/AdcCsvLogger.kt b/app/src/main/java/com/example/medilightv2android/services/AdcCsvLogger.kt index cb58825..e5060b7 100644 --- a/app/src/main/java/com/example/medilightv2android/services/AdcCsvLogger.kt +++ b/app/src/main/java/com/example/medilightv2android/services/AdcCsvLogger.kt @@ -70,11 +70,13 @@ object AdcCsvLogger { val sgStr = if (analyzer.useSgFilter) "ON" else "OFF" val clinicalLabel = ClinicalSessionStore.currentLabel() // 일반 모드면 "" + // BLE 펌웨어 버전 (연결 안 됐으면 "") + val fwVersion = com.example.medilightv2android.ble.BleManager.current?.firmwareVersion?.value ?: "" java.io.FileWriter(file, !isNew).buffered().use { writer -> if (isNew) { val header = buildString { - append("scan_id,timestamp,clinical_label,volume_ml,lr_ratio,threshold,dps,sg_filter,channel") + append("scan_id,timestamp,clinical_label,firmware_version,volume_ml,lr_ratio,threshold,dps,sg_filter,channel") for (i in 0 until 100) append(",s$i") } writer.write(header) @@ -83,7 +85,7 @@ object AdcCsvLogger { for ((chIdx, buffer) in channels.withIndex()) { val row = buildString { - append("$scanCounter,$timestamp,$clinicalLabel,$volStr,$lrStr,$thrStr,$dpsStr,$sgStr,CH$chIdx") + append("$scanCounter,$timestamp,$clinicalLabel,$fwVersion,$volStr,$lrStr,$thrStr,$dpsStr,$sgStr,CH$chIdx") for (sample in buffer) { append(",${sample.toInt()}") } diff --git a/app/src/main/java/com/example/medilightv2android/services/BleDebugLogger.kt b/app/src/main/java/com/example/medilightv2android/services/BleDebugLogger.kt index 3236c0a..ff2a1f2 100644 --- a/app/src/main/java/com/example/medilightv2android/services/BleDebugLogger.kt +++ b/app/src/main/java/com/example/medilightv2android/services/BleDebugLogger.kt @@ -130,6 +130,15 @@ class BleDebugLogger private constructor(private val context: Context) { add(Entry(System.currentTimeMillis(), Level.RSSI, "RSSI=$value dBm", rssi = value)) } + /** mid?/rid: 응답 받은 후 호출 — 펌웨어 정보를 ble.log에 보기 좋게 헤더 형태로 기록 */ + fun deviceInfo(fw: String, hw: String, sn: String) { + appendToFile("─── Device Info ───") + if (fw.isNotEmpty()) appendToFile("Firmware: $fw") + if (hw.isNotEmpty()) appendToFile("Hardware: $hw") + if (sn.isNotEmpty()) appendToFile("Serial: $sn") + appendToFile("───────────────────") + } + fun connected(name: String, address: String) { deviceName = name sessionStart = System.currentTimeMillis() diff --git a/app/src/main/java/com/example/medilightv2android/services/MeasurementLogService.kt b/app/src/main/java/com/example/medilightv2android/services/MeasurementLogService.kt index dfd2f16..5793754 100644 --- a/app/src/main/java/com/example/medilightv2android/services/MeasurementLogService.kt +++ b/app/src/main/java/com/example/medilightv2android/services/MeasurementLogService.kt @@ -69,6 +69,9 @@ class MeasurementLogService private constructor(private val context: Context) { put("app_version_code", appVersionCode) val clinical = ClinicalSessionStore.currentLabel() if (clinical.isNotEmpty()) put("clinical_label", clinical) + // BLE 펌웨어 버전 (연결 시 mid?/rid: 응답에서 받음) + val fw = com.example.medilightv2android.ble.BleManager.current?.firmwareVersion?.value + if (!fw.isNullOrEmpty()) put("firmware_version", fw) } if (volumeMl != null) { @@ -132,6 +135,9 @@ class MeasurementLogService private constructor(private val context: Context) { if (score >= 0) put("score", score) val clinical = ClinicalSessionStore.currentLabel() if (clinical.isNotEmpty()) put("clinical_label", clinical) + // BLE 펌웨어 버전 + val fw = com.example.medilightv2android.ble.BleManager.current?.firmwareVersion?.value + if (!fw.isNullOrEmpty()) put("firmware_version", fw) } appendLog(entry, "placements.jsonl") }