티스토리 뷰

거의 1인 모바일 앱 개발자로 개발한 회사 프로젝트에서 블루투스 온도계 연동을 하고, 그 값을 받아서 사용하도록 해보자는 의견이 나와서 이게 API문서 없이(실제 발주처에서 어떤 장비를 쓸 지 모르니...) 가능한 지 한 번 테스트 하기 위해 시작을 했다.

 

뭐, 패킷 까보는거야 보안기사 준비나 워게임을 하면서 많이 해봤으니까 나름 자신 있다고 생각했는데, 그 생각 보다는 삽질을 많이 했다.


API 문서가 없는 서드파티 블루투스 온도계(BG-BT1W, AiLink 1001)를 연동하기 위해 수행한 리버스 엔지니어링 과정과 프로토콜 분석 내용을 정리한다.

1. BLE (Bluetooth Low Energy) 개요

연동 대상 기기들은 모두 저전력에 최적화된 BLE 프로토콜을 사용한다.

BLE 통신의 핵심은 GATT (Generic Attribute Profile) 구조를 이해하는 것이다.

  • Profile: 기기의 성격을 정의 (예: 온도계, 심박계)
  • Service: 특정 기능을 수행하는 데이터의 집합 (고유 UUID 보유)
  • Characteristic: 실제 데이터가 담긴 최소 단위 (Read, Write, Notify 등의 속성을 가짐)

통신 메커니즘

  1. Advertising: 기기가 자신의 존재(UUID, 이름 등)를 주기적으로 송출.
  2. Connection: 앱이 기기와 1:1 연결 수립 (GATT Table 로딩).
  3. Subscription: 실시간 데이터 수신을 위해 특정 Characteristic에 Notification 활성화 요청.
  4. Data Stream: 데이터 변경 시 기기가 앱으로 패킷 전송.

2. 리버스 엔지니어링 수행 과정 (Packet Sniffing)

제조사 API가 없으므로 안드로이드 시스템의 HCI (Host Controller Interface) 로그를 캡처하여 분석했다.

2.1. 로그 추출 (Android)

  1. 설정 활성화: 개발자 옵션 -> 블루투스 HCI 스누프 로그 사용 활성화.
  2. 재시작: 블루투스 기능을 껐다 켜서 로깅 시작.
  3. 시나리오 수행: 공식 앱(tempWise 등)을 실행하여 실제 데이터 통신 발생 유도.
  4. 파일 추출: PC 연결 후 adb 명령어 사용.
    adb bugreport my_logs
    # 압축 해제 후 FS/data/misc/logs/bt/btsnoop_hci.log 확인
    

2.2. 로그 분석 (Wireshark)

추출한 로그를 Wireshark로 분석한다. 최신 안드로이드 로그 포맷 호환을 위해 editcap으로 변환이 필요할 수 있다.

  • 필터링 조건: BLE 데이터만 확인하기 위해 아래 필터 적용.
    btatt && !btsmp && (bluetooth.src == [기기MAC] || bluetooth.src == [폰MAC])
    
  • 핵심 패킷 확인:
    • Write Request (Opcode 0x12): 앱 -> 기기. 데이터 구독 시작 신호.
    • Notification (Opcode 0x1B): 기기 -> 앱. 실제 온도 데이터 포함.
    • 즉, 아래 사진과 같이 Info 탭에서 "Rcvd Handle Value Notification"을 가지고 있는 패킷을 확인하면 온도 데이터 송신 패킷을 확인할 수 있다.

- UUID: 대분류(난 탐침 온도계(제조사 어디)의 고유한 블루투스 데이터입니다.) - Service UUID: 소분류(이 서비스는 어떤 역할의 데이터입니다. 예: "데이터 송신", "상태 보고" 등) - Value: 패턴 분석 후 온도 데이터의 위치를 알아내야 하는 핵심 데이터.

Tip: 복잡한 패킷 분석 대신 nRF Connect 앱을 사용하면 연결된 기기의 Service UUID, Characteristic UUID, Value를 직관적으로 확인할 수 있다.

3. 기기별 프로토콜 분석 결과

두 기기 모두 BLE를 사용하지만 Payload 구조가 다르다.

항목 BG-BT1W (Simple Type) AiLink 1001 (Header Type)
Service UUID ...0000-1000-8000-00805f9b34fb ...ffe0-0000-1000-8000-00805f9b34fb
패킷 특징 헤더 없는 Raw Data (4 Bytes) 0xA7 헤더로 시작하는 가변 길이 패킷
배터리 정보 포함됨 긴 패킷에는 포함되지 않음

3.1. 데이터 파싱 (Data Parsing)

A. BG-BT1W (Raw Packet)

  • 예시 데이터: 16 1C 62 (Hex)
  • 온도: Byte[0] ~ Byte[1] 이용. 0x1B -> 27℃ (정수형)
  • 배터리: Byte[3]. 0x62 -> 98%

B. AiLink 1001 (A7 Protocol)

  • 예시 데이터: A7 08 ... 01 7E ... (Long Packet)
  • Header: Byte[0] (0xA7)
  • Length: Byte[1] (0x08 등 Payload 길이)
  • 온도: Byte[10], Byte[11] (Big Endian)
    • 0x017E -> 382 -> 38.2℃ (소수점 1자리 포함)
  • 주의: Length가 짧은 패킷(0x07)도 들어오지만, 정밀 온도를 위해 긴 패킷(Length >= 17 등)만 필터링하여 처리.

4. 구현 로직 (React Native)

react-native-ble-plx 라이브러리를 사용하여 구현 시 주요 흐름:

  1. scanAndConnect(): 기기 스캔 및 연결.
  2. discoverAllServicesAndCharacteristics(): 서비스 검색.
  3. monitorCharacteristicForService(): Notification 구독 및 데이터 수신 콜백 등록.
  4. 수신된 Base64 데이터를 Buffer로 변환 후, 위 프로토콜에 맞춰 파싱.
반응형
Comments