통합 차량 관제 시스템 용어 사전
통신·신호캐릭터리스틱

GATT

BLE 에서 데이터를 주고받는 규칙. 메시지가 아니라 서로 합의한 변수를 읽고 쓰는 형태다.

Generic Attribute Profile. BLE 로 데이터를 주고받는 표준 규칙이다.

메시지가 아니라 변수다

TCP 소켓이나 CAN 을 먼저 배운 사람이 가장 헷갈리는 지점이다. BLE 에는 "패킷을 보낸다"는 개념이 없다.

CAN     0x210 프레임을 버스에 던진다              ← 메시지 지향
BLE     "온도" 라는 변수를 읽는다 / 쓴다 / 바뀌면 알림받는다   ← 속성(attribute) 지향

양쪽이 미리 변수 목록에 합의하고, 그 변수를 조작하는 것으로 통신한다. 그 변수 하나를 캐릭터리스틱(characteristic), 관련된 것들을 묶은 상자를 서비스(service)라 한다.

Service: Vehicle Control          ← 상자
  ├ Characteristic: Request       ← 변수 (쓰기 전용)
  ├ Characteristic: ReqResult     ← 변수 (알림 전용)
  └ Characteristic: State         ← 변수 (읽기 + 알림)

서버와 클라이언트가 뒤집혀 있다

변수를 들고 있는 쪽이 서버다. 차량(ESP32)이 GATT 서버, 폰이 GATT 클라이언트다. 폰이 더 강력한 기기인데 클라이언트라는 게 직관에 어긋나지만, "데이터의 소유자가 서버" 라고 보면 맞는다.

조작 방법은 넷뿐이다

연산방향쓰임
Read클라이언트 → 서버 요청현재 상태를 한 번 가져온다
Write클라이언트 → 서버제어 요청을 보낸다
Notify서버 → 클라이언트 (응답 없음)상태가 바뀌면 밀어 준다
Indicate서버 → 클라이언트 (응답 필요)놓치면 안 되는 것

Notify 가 핵심이다. 이게 없으면 폰이 계속 Read 로 물어봐야 하고(폴링), 배터리가 녹는다. 차량 상태처럼 언제 바뀔지 모르는 것은 반드시 Notify 로 받는다.

Notify 와 Indicate 의 차이는 확인 응답이다. Notify 는 던지고 잊고, Indicate 는 클라이언트의 확인을 기다린다. 그래서 Indicate 가 느리다 — 확인이 올 때까지 다음 걸 못 보낸다.

UUID — 128비트를 쓰는 이유

각 서비스·캐릭터리스틱은 UUID 로 구분한다. 표준으로 정해진 것(심박수·배터리 등)은 16비트 축약형을 쓰지만, 우리가 만든 것은 128비트 커스텀 UUID 를 써야 한다. 16비트 공간은 Bluetooth SIG 가 관리하므로 마음대로 쓰면 충돌한다.

가장 흔한 함정 — CCCD

Notify 를 받으려면 두 곳을 켜야 한다.

① 폰 안쪽 설정          setCharacteristicNotification(char, true)
② 차량에게도 알린다      CCCD 디스크립터에 0x0001 쓰기

CCCD(Client Characteristic Configuration Descriptor)는 "나 이 변수의 알림 구독할게" 를 서버에 등록하는 자리다. ①만 하면 폰은 받을 준비가 됐는데 차량이 보내지를 않는다. 아무 에러도 안 나고 그냥 조용하다 — BLE 입문자가 가장 많이 걸린다.

이 시스템에서의 설계 판단

CAN 에서 올라온 신호를 ESP32 가 예쁘게 재포장하지 않고 Trusted<T> 구조 그대로 흘린다. 중간에서 *_trust 를 떼면 앱이 stale 표시 금지 를 지킬 방법이 사라진다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 모바일 인터페이스 — 요청 생애주기·CDM·GATT 설계