fix(ble): 폴링 건너뛰기를 파일 로그로 · 광고 없음 문구를 실제 원인에 맞게

2026-09-11 실기기 시험(IM-H091)에서 둘이 드러났다.

## ① 건너뛰기가 파일 로그에 안 남았다

`logd` 로 남겨서 logcat 에만 갔다. 현장에서는 `Download/VesiScan_BLE_*.log` 파일만 받아
보므로, 그러면 **"왜 배터리가 안 갱신되나"를 파일로 답할 수 없다.** `debugLogger.info` 로
올렸다 — `BATT_POLL_SKIP`. 최대 30초에 한 줄이라 부담이 없다.

## ② 문구가 틀린 원인을 가리켰다

시험 로그가 이랬다:

    09:11:11.980  DISCONNECTED
    09:11:12.863  ADVERT_WAIT        0.88초 뒤 연결 누름 — 광고를 못 봐서 대기
    09:11:18.867  ADVERT_TIMEOUT     6초 기다려도 없음
    09:11:26.988  ADVERT_TIMEOUT     또 없음
    09:11:28.967  ADVERT_FOUND       16초 만에 광고 재개 → 연결 성공

**프로브가 빠른 연결/해제 반복 뒤 약 16초간 광고를 멈췄다.** 가드는 정확히 작동했다 —
연결을 시도하지 않아 반쪽 연결도, 무한 스피너도, 본드 비대칭도 없었다(HALF_CONNECTED ·
CONNECT_TIMEOUT · stale GATT 전부 안 찍힘).

그런데 문구가 "전원이 켜져 있는지 확인" 이었다. 기기는 켜져 있었다 — 광고를 아직 안
시작한 것이다. 사용자를 엉뚱한 곳으로 보낸다. 실제 원인과 할 일을 적었다:

    기기 신호가 잡히지 않습니다. 방금 연결을 끊었다면 기기가 다시 신호를 보낼 때까지
    10~20초 걸릴 수 있습니다 — 잠시 뒤 다시 눌러 주세요. 계속 안 되면 전원을 확인하세요.

## 펌웨어 쪽에 남길 것

광고 재개가 16초 걸린 것은 **펌웨어 동작**이다. 빠른 연결/해제를 7회 반복한 뒤였다. 앱은
기다리고 다시 시도하면 되지만, 그 지연 자체는 펌웨어팀이 볼 문제다.

demo-final 143 · user 79 · caregiver 33 테스트 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 09:17:20 +09:00
parent ef221a81c6
commit 14e4b33072
3 changed files with 11 additions and 7 deletions
@@ -1512,12 +1512,16 @@ class BleManager private constructor(private val context: Context) {
override fun run() { override fun run() {
if (!isConnected.value) return if (!isConnected.value) return
when { when {
isMtbBusy -> logd { "battery poll skip: mtb stream in progress" } // 건너뛴 사실을 **파일 로그**에 남긴다. logd 는 logcat 에만 가는데
// 현장에서는 파일만 받아 보므로, 그러면 "왜 배터리가 안 갱신되나"를
// 파일로 답할 수 없다. 최대 30초에 한 줄이라 부담이 없다.
isMtbBusy ->
debugLogger.info("BATT_POLL_SKIP mtb 응답 진행 중 — 다음 주기에")
// 측정 중이다. 건너뛰고 다음 tick 에 다시 본다 — 끝나면 잡힌다. // 측정 중이다. 건너뛰고 다음 tick 에 다시 본다 — 끝나면 잡힌다.
!isTxQuiet -> logd { !isTxQuiet -> debugLogger.info(
"battery poll skip: TX active " + "BATT_POLL_SKIP 측정 중 " +
"(${System.currentTimeMillis() - lastTxAtMs}ms ago)" "(직전 TX ${System.currentTimeMillis() - lastTxAtMs}ms 전) — 다음 주기에"
} )
else -> sendBatteryQuery() else -> sendBatteryQuery()
} }
handler.postDelayed(this, BATTERY_POLL_INTERVAL_MS) handler.postDelayed(this, BATTERY_POLL_INTERVAL_MS)
+1 -1
View File
@@ -373,7 +373,7 @@
<string name="device_scan_connect_stuck_err">연결이 끝나지 않았습니다. 기기를 다시 눌러 주세요.</string> <string name="device_scan_connect_stuck_err">연결이 끝나지 않았습니다. 기기를 다시 눌러 주세요.</string>
<string name="ble_error_half_connected">연결이 끝까지 되지 않았습니다 — 기기가 응답했지만 준비를 마치지 못했습니다. 다시 연결합니다.</string> <string name="ble_error_half_connected">연결이 끝까지 되지 않았습니다 — 기기가 응답했지만 준비를 마치지 못했습니다. 다시 연결합니다.</string>
<string name="ble_error_unbond_unreachable">페어링을 삭제할 수 없습니다: 기기에 명령이 닿지 않습니다. 기기 버튼을 15초 길게 눌러 초기화한 뒤, 저장된 기기를 삭제하고 다시 페어링하세요.</string> <string name="ble_error_unbond_unreachable">페어링을 삭제할 수 없습니다: 기기에 명령이 닿지 않습니다. 기기 버튼을 15초 길게 눌러 초기화한 뒤, 저장된 기기를 삭제하고 다시 페어링하세요.</string>
<string name="ble_error_not_advertising">기기를 찾을 수 없습니다. 전원이 켜져 있는지 확인한 뒤 다시 눌러 주세요.</string> <string name="ble_error_not_advertising">기기 신호가 잡히지 않습니다. 방금 연결을 끊었다면 기기가 다시 신호를 보낼 때까지 10~20초 걸릴 수 있습니다 — 잠시 뒤 다시 눌러 주세요. 계속 안 되면 전원을 확인하세요.</string>
<string name="device_scan_new_devices">새 기기</string> <string name="device_scan_new_devices">새 기기</string>
<string name="device_scan_grant_permissions">권한 허용</string> <string name="device_scan_grant_permissions">권한 허용</string>
<string name="device_scan_stop_scan">검색 중지</string> <string name="device_scan_stop_scan">검색 중지</string>
+1 -1
View File
@@ -373,7 +373,7 @@
<string name="device_scan_connect_stuck_err">Connection did not finish. Tap the device again.</string> <string name="device_scan_connect_stuck_err">Connection did not finish. Tap the device again.</string>
<string name="ble_error_half_connected">Connection was incomplete — the device answered but did not finish setup. Reconnecting.</string> <string name="ble_error_half_connected">Connection was incomplete — the device answered but did not finish setup. Reconnecting.</string>
<string name="ble_error_unbond_unreachable">Cannot delete pairing: the device is not reachable. Hold the device button for 15 seconds to reset it, then delete the saved device and pair again.</string> <string name="ble_error_unbond_unreachable">Cannot delete pairing: the device is not reachable. Hold the device button for 15 seconds to reset it, then delete the saved device and pair again.</string>
<string name="ble_error_not_advertising">Device not found. Make sure it is powered on, then tap it again.</string> <string name="ble_error_not_advertising">No signal from the device. If you just disconnected, it can take 10-20 seconds to start advertising again — wait a moment and tap it again. If it keeps failing, check the power.</string>
<string name="device_scan_new_devices">New Devices</string> <string name="device_scan_new_devices">New Devices</string>
<string name="device_scan_grant_permissions">Grant Permissions</string> <string name="device_scan_grant_permissions">Grant Permissions</string>
<string name="device_scan_stop_scan">Stop Scan</string> <string name="device_scan_stop_scan">Stop Scan</string>