44460d5149
앞 커밋은 반쪽 연결을 **복구**했다. 이건 **생기지 않게** 한다. ## 전제가 틀렸다 `connectByAddress` 는 바로 connectGatt 했다. 주석이 "스캔 결과에 안 잡혀도 OS 본드가 있으면 바로 됨"이라고 적고 있었는데, **BLE 는 상대가 광고(connectable)하지 않으면 연결이 성립하지 않는다.** 광고 전/직후에 [저장된 기기] 를 누르면 링크만 붙고 서비스가 안 올라온다 — 현장 재연 ③의 "광고를 하기 전 또는 직후, 휴대폰이 인지하지 못한 상황" 이 정확히 그것이다. ## 방금 봤으면 기다리지 않는다 주소별로 광고를 마지막에 본 시각을 들고 있다가(`lastSeenAtMs`), 5초 안이면 바로 연결한다. 기기 목록 화면은 이미 스캔 중이라 **대부분 이 경로**다 — 평소 연결이 느려지지 않는다. 매번 스캔을 돌리면 안드로이드 스캔 횟수 제한(30초에 5회)에 걸린다. 못 봤으면 그 주소만 필터로 걸어 최대 6초 기다린다. 광고가 오면 그 ScanResult 의 device 로 연결하고, 안 오면 "기기를 찾을 수 없습니다. 전원이 켜져 있는지 확인한 뒤 다시 눌러 주세요." 로 끝낸다 — **연결을 시도하지 않으므로 반쪽 연결이 애초에 안 생긴다.** 기록은 **이름 검사보다 먼저** 한다. 광고에 이름이 안 실린 패킷도 "지금 광고 중"이라는 증거다 — 놓치면 멀쩡히 광고하는 기기를 6초 기다린다. ## 확인이 불가능할 때는 막지 않는다 스캐너가 없거나 스캔이 실패하면(권한·횟수 제한) 확인을 포기하고 그냥 시도한다. 여기서 멈추면 연결할 길이 아예 없어진다. 그 경우는 앞 커밋의 반쪽 연결 가드(20초)가 받는다. ## unbondSmart 타임아웃 5초 → 14초 그 함수는 `connectByAddress` 로 재연결한 뒤 msr? 를 보낸다. 광고 대기가 최대 6초라 5초면 스캔 단계에서 잘려 **항상 "기기 오프라인"** 으로 떨어진다. 테스트 143개 통과. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>