diff --git a/app/src/main/java/com/example/variableaxlemonitor/bluetooth/BluetoothManager.kt b/app/src/main/java/com/example/variableaxlemonitor/bluetooth/BluetoothManager.kt index fa66cd4..34661f7 100644 --- a/app/src/main/java/com/example/variableaxlemonitor/bluetooth/BluetoothManager.kt +++ b/app/src/main/java/com/example/variableaxlemonitor/bluetooth/BluetoothManager.kt @@ -52,7 +52,6 @@ class BluetoothManager(private val context: Context) { val foundDevices: StateFlow> = _foundDevices private var gatt: BluetoothGatt? = null - private val dataBuffer = StringBuilder() private val scanCallback = object : ScanCallback() { @SuppressLint("MissingPermission") @@ -154,12 +153,30 @@ class BluetoothManager(private val context: Context) { processReceivedData(characteristic.value) } + + //1. 역할: "구독 승인 확인" + //BLE 기기(ESP32-C3)로부터 데이터를 자동으로 받으려면(Notification), 단순히 앱에서 "받겠다"고 설정하는 것뿐만 아니라, + // **기기 내부의 스위치(Descriptor)**를 켜줘야 합니다. + // onDescriptorWrite는 바로 그 스위치를 켜는 작업이 성공했는지 결과를 알려주는 시점입니다. + //2. 동작 흐름 (Flow) + // 1.서비스 발견: 기기의 기능을 찾습니다. (onServicesDiscovered) + //2.특성 알림 설정: 앱 내부적으로 알림을 받을 준비를 합니다. (setCharacteristicNotification) + //3.디스크립터 쓰기: 기기에게 "이제 데이터를 보내줘"라고 명령을 보냅니다. (writeDescriptor) + //4.결과 수신 (onDescriptorWrite): 기기가 명령을 잘 받았는지 확인합니다. (현재 코드 부분) + //5.데이터 수신: 이때부터 실제 데이터가 들어옵니다. (onCharacteristicChanged) + override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) { + // 1. 로그 기록: 어떤 결과(status)로 어떤 항목(descriptor)에 쓰기가 완료되었는지 남깁니다. Log.d(TAG, "onDescriptorWrite: status=$status, descriptor=${descriptor.uuid}") + // 2. 성공 여부 판단: status가 0(GATT_SUCCESS)이면 성공입니다. if (status == BluetoothGatt.GATT_SUCCESS) { + // 성공 시: 사용자가 볼 수 있게 상태 메시지를 업데이트합니다. + // 이제부터 기기가 데이터를 보내기 시작할 준비가 완벽히 끝났음을 의미합니다. _lastMessage.value = "통신 준비 완료. 데이터 수신 대기 중..." } else { - _lastMessage.value = "구독 설정 실패 (status=$status)" + // 실패 시: 에러 코드와 함께 실패 메시지를 띄웁니다. + // 이 경우 기기가 데이터를 보내지 않으므로 원인을 파악해야 합니다. + _lastMessage.value = "데이터 수신 실패 (status=$status)" } } } @@ -167,42 +184,11 @@ class BluetoothManager(private val context: Context) { private fun processReceivedData(value: ByteArray?) { if (value == null) return - val received = String(value) - // Log.d(TAG, "Raw Data (String): $received") - - synchronized(dataBuffer) { - dataBuffer.append(received) - - // Check for various delimiters including literal strings like "\r\n" or "\r\" - val delimiters = listOf("\r\n", "\\r\\n", "\\r\\", "\n", "\r") - - var foundDelimiter = true - while (foundDelimiter) { - foundDelimiter = false - var earliestIndex = Int.MAX_VALUE - var selectedDelimiter = "" - - for (delim in delimiters) { - val index = dataBuffer.indexOf(delim) - if (index != -1 && index < earliestIndex) { - earliestIndex = index - selectedDelimiter = delim - foundDelimiter = true - } - } - - if (foundDelimiter) { - val line = dataBuffer.substring(0, earliestIndex).trim() - dataBuffer.delete(0, earliestIndex + selectedDelimiter.length) - - if (line.isNotEmpty()) { - Log.d(TAG, "Extracted line: '$line'") - // _lastMessage.value = "데이터 수집 중: $line" - scope.launch { - parseData(line) - } - } - } + val received = String(value).trim() + if (received.isNotEmpty()) { + Log.d(TAG, "Extracted line: '$received'") + scope.launch { + parseData(received) } } }