ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BLE 프로토콜 구조
    iOS Swift 2023. 6. 7. 13:41

    BLE 프로토콜은 세 개의 주요 파트로 구성 되는데 각각 application, host, controller 라고 부릅니다. 이 블럭 내에는 별개의 레이어로 이루어 집니다. 

    BLE 프로토콜 레이어 

    PHY (Physical Layer) 

    물리 계층(PHY)은 실제 블루투스 무선 라디오 주파수를 이용해 통신을 하는 계층으로 아날로그 신호와 디지털 신호를 변조/복조하는 회로를 포함합니다. 기본적으로 2.4GHz 신호를 40개의 채널로 나누어 통신하는 데 그 중 세 채널은 Advertising 을 위해 나머지는 Data 전송을 위해 사용됩니다. 

    Link Layer

    링크 계층은 물리 계층과 인터페이스 하는 부분으로 블루투스의 저전력 사양을 준수하기 위한 타이밍 요구 사항이나 무선 상태를 관리하는 역할을 합니다. 

    Host Controller Interface(HCI)

    호스트 계층과 컨트롤러 계층 사이의 인터페이스

    Logical Link Control and Adaptation Protocol(L2CAP) 

    L2CAP 계층은 프로토콜 멀티플렉싱 레이어 역할을 합니다. 상위 계층에서 여러 프로토콜을 가져와 표준 BLE 패킷을 만들고 해당 패킷을 하위 계층에 전달합니다. 

    Attribute Protocol(ATT)

    서버가 데이터를 클라이언트에 노출하는 방법과 데이터를 구성하는 방법을 정의합니다. 

    Generic Attribute Profile(GATT)

    BLE 장치에서 노출하는 데이터의 형식과 장치에서 노출하는 데이터에 엑세스하는 데 필요한 절차를 정의 합니다. 

    Generic Access Profile(GAP)

    GAP는 BLE 장치 간에 통신을 적용하는 방식을 정의합니다. 

    Security Manager(SM)

    BLE 장치 간 통신에 보안을 정의합니다. 

     

    여기서는 GAP를 통해 블루투스 디바이스가 채널을 통해 통신하는 내용을 자세히 다루고 GATT와 ATT를 통해 데이터를 구성하는 방식과 디바이스 간에 데이터를 공유하는 방법에 대해 이야기하겠습니다. 

    GAP에 정의된 디바이스 간 통신 연결 

    Bluetooth LE 디바이스가 서로 통신을 하려면 채널을 형성해야 합니다. 이 채널을 형성하고 유지하는 방법을 GAP에서 정의하고 있습니다.  두 장치가 연결되고 서로 데이터를 교환하려면 한 쪽은 Central(중앙 장치) 역할을 수행하고 다른 쪽은 Peripheral(주변 장치) 역할을 맡아야 합니다. 중앙장치는 일반적으로 스마트폰과 같은 장치인 반면 주변 장치는 심박 센서와 같은 전력 소모가 적은 장치인 경우가 많습니다. 블루투스 장치 간에 연결은 크게 Advertising/Scan 과 Connection 단계로 진행됩니다. 

     

    주변 장치가 연결할 준비가 되면 advertising 모드로 들어가고 LE 라디오를 사용하여 기본 advertising 채널(37, 38, 39)에 advertising 패킷을 브로드캐스팅하여 디바이스가 연결 준비가 되어 있음을 알립니다.

     

    중앙 장치는 Scanning 상태로 전환하고 이 세 채널에서 advertising 패킷을 수신해야 합니다.

     

     중앙 장치는 일정 간격으로 advertising 채널을 스캔하게 되는 데 해당 채널을 스캔하는 동안 해당 채널에 advertising 패킷을 수신하면 해당 주변 장치를 발견합니다. advertising 패킷을 확인하면 다음 단계는 중앙 장치에서 connection request packet을 전송하여 주변 장치에 대한 연결을 시작합니다. 여기서 GAP 가 디바이스 간의 역할을 중앙 장치와 주변 장치로 나누는 이유를 알 수 있습니다. 중앙 장치가 연결에 대한 최종 권한을 가지고 있고 연결을 요청할 때 해당 연결에 대한 방식을 설정하고 주변 장치는 중앙장치가 정한 연결 방식을 따르게 됩니다. 중앙 장치는 연결 요청 패킷을 전달할 때 파라미터로 아래와 같은 정보를 전달 합니다. 

    • 연결 간격 – 연결 이벤트 사이의 경과 시간 지정
    • Peripheral Latency – 주변 장치에서 건너뛸 수 있는 연결 이벤트 수 지정
    • 채널 맵 - 37개의 사용 가능한 데이터 채널 중 전송에 사용할 채널을 지정합니다.

    중앙 장치가 연결 요청을 보내면 연결이 생성 되었다고 하는 데 주변 장치는 연결 요청에 대한 응답을 주지는 않는다. 이후 연결 간격으로 설정된 시간 이후 중앙 장치는 데이터를 보내게 되고 주변장치가 해당 데이터 패킷을 응답으로 다시 보내게 되면 연결이 설정됩니다. 

    연결을 설정되면 이제 두 장치간에 영구적으로 데이터를 송 수신할 수있게 됩니다. 디바이스 간에 데이터를 전송할 수 있지만 이 데이터가 어떤 의미가 있는 지는 알 수 없습니다. 예를 들어 파일은 이진 데이터로 이루어지는 데 어떤 형식의 파일이냐 에 따라 텍스트 파일이나 이미지 파일일 수 있는 것 처럼 수신된 데이터가 어떤 형식으로 이루어지느냐에 대한 표준이 있어야지만 디바이스 간에 해당 데이터의 의미를 확인 할 수 있습니다. 이렇게 디바이스 간에 데이터를 이해하고 저장하는 방식에 대한 표준이 필요한데 이를 GATT가 수행하게 됩니다. 

    GATT는 위의 BLE 프로토콜에서 보는 바와 같이 ATT 레이어 위에 있는 데 이는 ATT를 이용해 GATT가 정의되어 있어서 그렇습니다. 이제 GATT를 이해하기 위해서 ATT에 대한 내용에 대해서 살펴보겠습니다. 

     

    ATT 프로토콜의 역할 

    ATT는 처음 디바이스 간에 역할을 정의합니다. 이 때 우리가 흔히 알고 서버-클라이언트 모델을 따릅니다. 클라이언트는 원하는 정보를 서버에게 요청하고 서버는 저장된 정보를 클라이언트에게 전달합니다. 예를 들어 심박 수를 측정하는 장비가 있고 스마트폰에서 해당 장비에 심박 수 정보를 요구하게 되면 심박 수 측정 장비는 이를 스마트폰에 전달하게 됩니다. 여기서 심박 수 측정 장비는 서버 역할을 하게되고 스마트 폰은 클라이언트 역할을 하게 됩니다. 위에서 GAP 간 디바이스 통신을 할 때 중앙 장치와 주변 장치의 역할에 대해 이야기 했는데 어떻게 보면 중앙 장치가 클라이언트가 되고 주변 장치가 서버가 되는 경우가 많지만 꼭 같지는 않습니다. 두 개념은 독립적으로 존재합니다. 만약 심박 센서가 스마트폰의 시간 값으로 동기화 한다면 심박 센서는 스마트폰에 시간 정보를 요청하고 스마트폰은 해당 시간 값을 심박 센서에 전달하게 되므로 시간 데이터의 관점에서는 스마트폰이 서버가 되고 심박 센서가 클라이언트 역할을 하게 될 수도 있습니다. 서버와 클라이언트는 특정 정보에 대해 저장 관리하고 요청에 따라 전달하는 역할을 하는 쪽이 서버, 해당 정보가 필요한 경우 서버를 통해 요청하는 쪽이 클라이언트라고 보시면 됩니다. 

    서버의 역할 

    서버 장치는 클라이언트와 공유해야 하는 데이터를 저장하는 데이터베이스의 역할을 합니다. 적절한 기능을 위해 서버는 다른 데이터베이스와 같이 다음과 같은 기능이 필요합니다. 

    • 데이터를 저장하고 구성하는 표준 방법
    • 데이터에 엑세스하기 위한 표준 방법

    클라이언트가 읽고 쓸 수 있는 방식으로 데이터를 저장하는 수단을 서버 장치에 제공하고 클라이언트가 해당 데이터에 엑세스하고 쓰고 읽을 수 있는 메커니즘을 제공하는 게 ATT의 역할입니다. ATT는 데이터를 효율적으로 구성하기 위한 방법으로 속성 테이블을 사용합니다. 

    속성 테이블의 구조는 아래와 같습니다. 

    • 핸들 - 고유한 16비트 식별자로 클라이언트가 서버의 속성을 참조하는데 사용합니다. 속성은 주소 지정 가능하게 만들고 단일 연결 중에 변경되지 않습니다. 
    • UUID -  값 필드에 저장된 데이터의 유형과 의미를 정의하는 고유한 2바이트 또는 16바이트 UUID 식별자입니다. UUID는 서비스 UUID와 특성(Characteristic) UUID 두 가지가 있습니다. 
    • 값 - 저장되는 실제 데이터 입니다. 예를 들어 심박 센서 같은 경우 심박 수가 될 것이고 온도 센서 같은 경우 측정된 온도 값이 되겠습니다. 
    • 권한 - 속성 값에 엑세스하는 데 필요한 권한이나 방법을 설정합니다.

    속성 접근 메서드 

    ATT 프로토콜은 속성에 대한 접근 방법에 대해 정의합니다. 속성 접근 방법은 서버냐 클라이언트나에 따라 조금 다릅니다. 

    클라이언트가 해당 속성에 엑세스하기 위한 방법으로 읽기와 쓰기를 정의합니다. 읽기는 클라이언트가 서버에 속성 값을 읽는데 사용되고 서버는 속성 값을 응답으로 전달합니다. 쓰기는 클라이언트가 서버에 속성 값을 쓰는 데 사용하는 데 서버는 쓰기 성공 여부를 나타내는 상태를 응답으로 전달합니다. 서버는 통지(Notification) 와 표시(Indication)라는 두가지 방법으로 속성에 접근합니다. 통지는 속성이 변경될 때마다 속성의 업데이트 된 값을 클라이언트에게 보내기 위해 서버에서 사용됩니다. 클라이언트는 이 통지를 받은 후 응답하지 않습니다. 표시 작업은 알림 작업과 유사하지만 클라이언트는 값을 올바르게 수신했는 지 여부를 나타내는 승인 상태와 함께 응답을 보내야 합니다. 

     

    속성 접근 권한 

    클라이언트가 속성 값을 읽거나 쓸 수 있는지(또는 둘 다)를 결정합니다. 각 속성에는 다음 엑세스 수준 중 하나를 할당할 수 있습니다. 

    • 없음 – 클라이언트는 속성을 읽거나 쓸 수 없습니다.
    • 읽기 가능 – 클라이언트가 속성을 읽을 수 있습니다.
    • 쓰기 가능 – 클라이언트는 속성을 쓸 수 있습니다.
    • 읽기 및 쓰기 가능 – 클라이언트는 속성을 읽고 쓸 수 있습니다.

    보안 요구 사항과 관련하여 속성의 UUID와 핸들은 공개 정보이지만 값과 권한은 그렇지 않습니다. 결과적으로 클라이언트가 이 두 개의 필드에 엑세스하려면 다음이 필요할 수 있습니다. 

    • 읽기 또는 쓰기 인증
    • 읽기 또는 쓰기 권한
    • 읽기 또는 쓰기를 위한 암호화 및 페어링

    GATT는 ATT 서버에 저장된 데이터 간의 관계 또는 연결을 나타내는 계층적 데이터 구조를 정의합니다.

     

    GATT를 이용한 데이터의 계층 구조 

    GATT 프로토콜 계층은 서버 데이터베이스의 리소스가 어떻게 구성되는 지를 계층적 관계로 표시하도록 구성하는 프레임워크를 정의합니다. GATT 계층은 트리와 같은 4단계 프레임워크를 정의합니다. 

    • 루트 노드의 이름은 프로필입니다. (레벨 0)
    • 프로필의 자식은 명명된 서비스입니다. (레벨 1)
    • 서비스의 자식은 특성으로 명명됩니다. (2 단계)
    • 그리고 특성은 단일 값과 0-n 설명자(레벨 3)로 정의할 수 있습니다.

    특성(Characteristic)

    특성은 데이터가 "기록"되고 "읽어지는" 기본 저장 단위입니다. 그냥 파일과 같다고 보시면 됩니다. 모든 특성은 다음과 같이 정의 됩니다. 

    값(value) - 실제 저장된 애플리케이션의 데이터 

    설명(descriptor) - 값에 대한 자세히 알려주는 선택적 정보입니다. 여기에는 사람이 읽을 수 있는 내용, 값에 대한 허용 범위 또는 특성 값에 대한 측정 단위가 포함될 수 있습니다. 

    가장 널리 사용되는 설명자는 CCCD(Client Characteristic Configuration Descriptor)입니다. CCCD GATT 서버의 표시(Indication) 또는 알림(Notification)을 활성화 또는 비활성화하는 사용됩니다. 특정 특성에 대한 알림 또는 표시를 활성화하면 클라이언트는 서버에서 특성 값이 변경될 때마다 알림을 받거나 업데이트를 받을 있습니다.

    GATT 심박수 프로필이 있는 피트니스 트래커를 살펴보고 계층적 관계가 어떻게 작동하는지 살펴보겠습니다.

    심박 수 GATT 프로필에 따르면 이를 구현하는 장치에는 다음이 포함됩니다.

    • 심박수 측정 특성(필수)
    • 신체 측정 특성(옵션)
    • 장치 정보 특성(선택 사항)

    심박수 특성은 다음과 같이 정의됩니다. 

    • 심박수 값- 이것은 실제 심박수 센서 데이터입니다.
    • 특성 구성 설명 - 클라이언트가 심박수 값의 변경 사항을 알릴 수 있도록 알림 목적으로 사용됩니다.

    신체 측정 특성은 다음과 같이 정의됩니다.

    • 신체 측정 값 – 장치를 착용할 신체의 위치를 설명하는 데 사용됩니다.

     

    장치 정보 특성은 다음과 같이 정의됩니다.

    • 제조업체 이름 문자열 – 장치 제조업체의 이름입니다.

    서비스(Service)

    서비스는 특성들을 특성들을 특정 목적에 따라 카테고리화 하는 데 사용됩니다. 이는 파일들을 가지고 있는 폴더처럼 특성들을가지고 있습니다. 피트니스 트래커에 해당 서비스는 다음과 같이 구성할 수 있습니다. 

    • 심박수 서비스- 이 서비스에는 심박수 특성[심박수 값 + 특성 구성 설명자]이 포함됩니다.
    • 신체 측정 서비스- 이 서비스에는 신체 측정 특성이 포함됩니다.
    • 기기 정보 서비스 - 이 서비스는 기기 정보 특성을 포함합니다.

    프로파일(Profile)

    프로파일은 서비스를 포함하는 최상위 계층이다. 

    특정 프로파일을 따르는 모든 디바이스는 스펙에 정의된 필수 서비스는 반드시 구현해야 합니다. 이는 동일한 GATT 프로파일을 지원하는 장치가 서로 통신할 수 있도록 하기 위해서 수행됩니다. 어떤 디바이스가 Heart Rate GATT 프로파일을 지원한다고 하면 

    • 심박수 서비스를 이용할 수 있습니다.
    • 신체 측정 서비스는 선택사항 입니다. 
    • 기기정보 서비스 를 통해 해당 제조사를 확인할 수 있습니다.

    이런 식으로 GATT가 정한 프로파일을  따라 디바이스를 구현하면 데이터의 구조가 어떻게 구성되어 있는지 알 수 있기 때문에 클라이언트 장치가 서버에서 제공하는 서비스에 신속하게 접근할 수 있습니다. 

     

    지금까지의 내용을 요약하면 다음과 같습니다. 서버는 디바이스에 속성테이블을 정의하고 관리합니다(ATT). 디바이스의 속성 값들은 GATT를 통해서 구조화 됩니다. 

    handle uuid value permission
    0x001C 0x2800 0x180D
    0x001D 0x2803 0A 1E 00 F1 FF 0x0A
    0x001E 0xFFFF1 01
    0x0A
    0x001F 0x2901 hello
    0x0028 0x2902 00 00  

    위의 테이블을 이용해 지금까지 내용을 정리해보면 0x001C는 UUID로 0x2800 을 가지는 데 이는 스펙에 정의된 Primary Service의 UUID로 서비스를 정의하고 해당 서비스는 0x180D 이다. 0x180D는 Heart Rate service 를 의미한다. 즉 이 속성은 해당 장비가 Heart Rate 서비스를 정의하고 있다는 걸 알 수 있다.  0x001D의 UUID는 0x2803은 특성을 나타내는 UUID로 해당 값은 0A 1E 00 F2 FF 값을 가지고 있다. 스펙 문서를 통해 해당 값을 분석해 보면 0A 는 속성의 권한을 나타내는 데 0x02 | 0x08 로 읽고 쓰기가 가능하다는 의미이다. 다음 00 1E는 해당 특성의 값이 위치한 핸들 값이고 다음 FF F1은 UUID 에 해당한다. 위의 값 값 중 해당 핸들의 위치로 가면 실제 갑이 존재하는 데 값은 0x01 이다. 핸들 값이 0x001F에는 UUID 0x2901이 있는데 이 값 Characteristic User Description 을 나타내고 hello 값이 저장되어 있다. 다음 UUID 0x2902는 Client Characteristic Configuration 통지 및 표시를 위해 사용되는 데 해당 값은 00 00 으로 통지 및 표시가 비활성화 되어 있음을 표시한다. 

     

     

     

     

     

    댓글

Designed by Tistory.