11.2. BLE 스택

네트워킹과 마찬가지로, Bluetooth Low Energy는 계층의 스택으로 구축되며, 각 계층은 하나의 문제를 해결하고 그 위의 계층에 깔끔한 추상화를 노출합니다. 아래의 이름들은 Bluetooth Core 사양에서 그대로 가져온 것이며 aioblebluetooth API에 나타납니다.

A vertical stack of five labelled boxes. From bottom to top: Physical (radio), Link Layer, GAP, GATT, Application. An arrow on the right points up the stack labelled "what we build". An arrow on the left points down the stack labelled "what is provided".

Bluetooth Low Energy 스택. 각 계층은 더 깔끔한 추상화를 다음 계층으로 넘겨주며, 이는 네트워킹 스택이 사용하는 것과 동일한 패턴입니다.

물리 계층. 2.4 GHz 무선 송수신기를 통해 두 장치 사이에서 비트 를 이동시킵니다. 채널 선택, 변조, 송신 전력을 담당합니다. 카메라의 역할은 전원을 켜는 것이고, 나머지는 실리콘이 처리합니다.

링크 계층. 서로 통신하기로 합의한 두 장치 사이에서 패킷 을 이동시킵니다. 각 패킷이 하나의 이웃을 향할 수 있도록 장치 주소를 추가하고, 연결을 구성하는 주기적 무선 이벤트를 스케줄링하며, 수신자가 확인 응답하지 않은 패킷의 재전송을 처리합니다.

Generic Access Profile (GAP). 검색 및 연결 계층입니다. 네 가지 역할 – broadcaster, observer, peripheral, central – 과, 두 장치가 애초에 서로를 찾을 수 있게 해주는 광고 / 스캐닝 프로토콜, 그리고 둘 사이의 연결을 열고 닫는 절차를 정의합니다. 주소, 광고 페이로드, 연결 매개변수, 페어링이 여기에 속합니다.

Generic Attribute Profile (GATT). 데이터 계층입니다. 열린 GAP 연결 위에 위치하며 작은 키/값 데이터베이스를 노출합니다. 한쪽은 characteristics 라는 이름이 붙은 값들의 트리를 호스팅하고, 다른 쪽은 이를 읽거나 쓰거나 구독합니다. 실제 애플리케이션 바이트가 흐르는 곳이 바로 여기입니다.

Application. 카메라와 피어가 바이트의 의미에 대해 합의한 그 무엇이든 됩니다. Bluetooth SIG는 표준 프로파일 – 심박수, 배터리 레벨, 환경 센싱 – 을 게시하여 자주 사용되는 특성을 정의함으로써 서로 무관한 장치들이 상호 운용될 수 있게 합니다. 하지만 모든 애플리케이션은 자유롭게 자신만의 것을 정의할 수 있습니다.

11.2.1. 런타임에 계층이 쌓이는 방식

이 패턴은 네트워킹 스택과 일치합니다:

  • 애플리케이션의 바이트는 characteristic 값 으로 들어갑니다.

  • GATT는 그 바이트가 어떤 characteristic에 속하는지 식별하는 헤더로 이를 감쌉니다.

  • GAP는 GATT가 보낼 곳을 갖도록 열린 연결을 계속 유지합니다.

  • 링크 계층은 그 전부를 피어의 장치 주소로 지정된 패킷으로 감싸고, 이를 전송할 무선 이벤트를 스케줄링합니다.

  • 물리 계층은 패킷을 짧은 2.4 GHz 무선 버스트로 변환합니다.

물리 계층과 링크 계층은 Python에서 거의 보이지 않습니다 – 실리콘과 무선 펌웨어가 이를 처리합니다. GAP 이상부터는 카메라의 Python 코드가 더 많은 발언권을 갖습니다.

11.2.2. 사용자 대상 API가 조용히 건너뛰는 두 계층

Bluetooth 사양은 링크 계층과 GAP/GATT 사이에 위치하는 두 계층을 더 명명합니다: Host Controller Interface (HCI) – 호스트 CPU가 별도의 무선 칩을 구동하는 데 사용하는 프로토콜 – 와 L2CAP – 하나의 링크 계층 연결을 여러 논리 채널로 분할하는 멀티플렉서입니다.

둘 다 aioble API에서는 보이지 않지만, 둘 다 사라지는 것은 아닙니다. HCI는 BLE 포트 내부에 위치하며 MicroPython의 커스텀 빌드가 사용되지 않는 한 보이지 않고, L2CAP은 GATT가 그 위에서 실행되는 운반체입니다. 원시 바이트 스트림을 원하는 애플리케이션은 자체 L2CAP 채널을 요청할 수 있습니다(L2CAP 채널).