bluetooth — 저수준 Bluetooth¶
이 모듈은 온보드 Bluetooth 컨트롤러에 대한 인터페이스를 제공합니다. Central, Peripheral, Broadcaster, Observer 역할의 Bluetooth Low Energy(BLE)와 함께 GATT Server 및 Client, 그리고 L2CAP 연결 지향 채널을 지원합니다. 하나의 장치가 여러 역할로 동시에 동작할 수 있습니다. 페어링(pairing)과 본딩(bonding)도 지원됩니다.
이 API는 저수준 Bluetooth 프로토콜에 맞추어, 특정 장치 유형과 같은 상위 수준 추상화를 위한 빌딩 블록을 제공하기 위한 것입니다.
팁
대부분의 애플리케이션에서는 이 모듈을 asyncio 기반으로 감싼 상위 수준 라이브러리인 aioble를 사용하는 것이 좋습니다. aioble — 비동기 BLE을 참고하세요.
class BLE¶
- class bluetooth.BLE¶
싱글톤 BLE 객체를 반환합니다.
설정
- active(active: bool | None = None, /) bool¶
선택적으로 BLE 라디오의 활성 상태를 변경하고, 현재 상태를 반환합니다.
이 클래스의 다른 메서드를 사용하기 전에 라디오를 활성화해야 합니다.
- config(param: str, /) Any¶
- config(*, **kwargs: Any) None
BLE 인터페이스의 설정 값을 가져오거나 설정합니다. 값을 가져오려면 매개변수 이름을 문자열로 따옴표로 묶어야 하며, 한 번에 하나의 매개변수만 조회됩니다. 값을 설정하려면 키워드 구문을 사용하며, 한 번에 하나 이상의 매개변수를 설정할 수 있습니다.
현재 지원되는 값은 다음과 같습니다:
'mac': 현재 주소 모드에 따라 사용 중인 현재 주소입니다.(addr_type, addr)튜플을 반환합니다.주소 유형에 대한 자세한 내용은
gap_scan을 참고하세요.이 값은 인터페이스가 현재 활성 상태일 때만 조회할 수 있습니다.
'addr_mode': 주소 모드를 설정합니다. 값은 다음과 같습니다:값
이름
동작
0x00PUBLIC
컨트롤러의 public 주소를 사용합니다.
0x01RANDOM
생성된 정적(static) 주소를 사용합니다.
0x02RPA
확인 가능한 비공개 주소(resolvable private address)를 사용합니다.
0x03NRPA
확인 불가능한 비공개 주소(non-resolvable private address)를 사용합니다.
기본적으로 인터페이스는 가능한 경우 PUBLIC 주소를 사용하며, 그렇지 않으면 RANDOM 주소를 사용합니다.
'gap_name': Generic Access 서비스(UUID0x1800)의 Device Name 특성(UUID0x2a00)에서 사용하는 GAP 장치 이름을 가져오거나 설정합니다. 이 값은 언제든지 설정할 수 있으며 여러 번 변경할 수 있습니다.'rxbuf': 들어오는 이벤트를 저장하는 데 사용되는 내부 버퍼의 크기를 바이트 단위로 가져오거나 설정합니다. 이 버퍼는 전체 BLE 드라이버에 대해 전역적이므로 모든 특성을 포함한 모든 이벤트의 수신 데이터를 처리합니다. 이를 늘리면 버스트성 수신 데이터(예: 스캔 결과)를 더 잘 처리할 수 있고 더 큰 특성 값을 받을 수 있게 됩니다.'mtu': ATT MTU 교환 중에 사용될 MTU를 가져오거나 설정합니다. 결과 MTU는 이 값과 원격 장치의 MTU 중 더 작은 값이 됩니다. ATT MTU 교환은 (원격 장치가 시작하지 않는 한) 자동으로 일어나지 않으며,gattc_exchange_mtu를 사용해 수동으로 시작해야 합니다. 주어진 연결에 대한 MTU를 알아내려면_IRQ_MTU_EXCHANGED이벤트를 사용하세요.'bond': 페어링 중에 본딩을 활성화할지 여부를 설정합니다. 활성화하면 페어링 요청이 “bond” 플래그를 설정하고 두 장치 모두 키를 저장합니다.'mitm': 페어링에 MITM 보호가 필요한지 여부를 설정합니다.'io': 이 장치의 I/O 기능을 설정합니다.사용 가능한 옵션은 다음과 같습니다:
상수
값
기능
_IO_CAPABILITY_DISPLAY_ONLY0
디스플레이만 가능
_IO_CAPABILITY_DISPLAY_YESNO1
예/아니오 입력이 있는 디스플레이
_IO_CAPABILITY_KEYBOARD_ONLY2
키보드만 가능
_IO_CAPABILITY_NO_INPUT_OUTPUT3
입력 또는 출력 없음
_IO_CAPABILITY_KEYBOARD_DISPLAY4
키보드와 디스플레이
'le_secure': “LE Secure” 페어링이 필요한지 여부를 설정합니다. 기본값은 false입니다(즉, “Legacy Pairing”을 허용).
이벤트 처리
- irq(handler: Callable[[int, Tuple], Any | None], /) None¶
BLE 스택의 이벤트에 대한 콜백을 등록합니다. handler 는 두 개의 인자를 받습니다.
event(아래 코드 중 하나) 와data(이벤트별 값으로 이루어진 튜플) 입니다.참고: 불필요한 할당을 방지하는 최적화로서, 튜플의
addr,adv_data,char_data,notify_data,uuid항목은bluetooth의 내부 링 버퍼를 가리키는 읽기 전용 memoryview 인스턴스이며, IRQ 핸들러 함수가 호출되는 동안에만 유효합니다. 프로그램에서 IRQ 핸들러가 반환된 후에 접근하기 위해 이러한 값 중 하나를 저장해야 한다면(예: 클래스 인스턴스나 전역 변수에 저장), 다음과 같이bytes()나bluetooth.UUID()를 사용하여 데이터의 복사본을 만들어야 합니다:connected_addr = bytes(addr) # equivalently: adv_data, char_data, or notify_data matched_uuid = bluetooth.UUID(uuid)
예를 들어, 스캔 결과에 대한 IRQ 핸들러는
adv_data를 검사하여 올바른 장치인지 판단한 다음에야 프로그램의 다른 곳에서 사용할 주소 데이터를 복사할 수 있습니다. 그리고 IRQ 핸들러 내에서 데이터를 출력하려면print(bytes(addr))가 필요합니다.핸들러는 일반적으로 이벤트 코드에 따라 분기하고 이벤트별 페이로드 튜플을 언팩합니다:
def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: conn_handle, addr_type, addr = data ... elif event == _IRQ_SCAN_RESULT: addr_type, addr, adv_type, rssi, adv_data = data ...
모든 이벤트 코드, 전달하는 페이로드, 그리고 간단한 설명이 아래에 나열되어 있습니다.
status필드가 언급된 이벤트의 경우,status는 성공 시0이고 실패 시 구현별 0이 아닌 값입니다.상수
값
이벤트
페이로드 튜플
_IRQ_CENTRAL_CONNECT1
central이 이 peripheral에 연결되었습니다.
(conn_handle, addr_type, addr)_IRQ_CENTRAL_DISCONNECT2
central이 이 peripheral에서 연결 해제되었습니다.
(conn_handle, addr_type, addr)_IRQ_GATTS_WRITE3
연결된 클라이언트가 로컬 특성 또는 디스크립터에 데이터를 썼습니다. 새 값을 가져오려면
gatts_read를 사용하세요.(conn_handle, attr_handle)_IRQ_GATTS_READ_REQUEST4
연결된 클라이언트가 읽기를 요청했습니다. 읽기를 거부하려면 아래 표의 0이 아닌 오류 코드를 반환하고, 수락하려면
0/None을 반환하세요.(conn_handle, attr_handle)_IRQ_SCAN_RESULT5
활성 스캔 중에 단일 광고 패킷이 수신되었습니다.
(addr_type, addr, adv_type, rssi, adv_data)_IRQ_SCAN_DONE6
설정된 지속 시간이 경과했거나
gap_scan(None)이 호출되었기 때문에 현재 스캔이 종료되었습니다.()_IRQ_PERIPHERAL_CONNECT7
이전에 실행한
gap_connect가 성공했습니다.(conn_handle, addr_type, addr)_IRQ_PERIPHERAL_DISCONNECT8
연결된 peripheral이 연결 해제되었습니다.
(conn_handle, addr_type, addr)_IRQ_GATTC_SERVICE_RESULT9
gattc_discover_services에 의해 하나의 서비스가 발견되었습니다.(conn_handle, start_handle, end_handle, uuid)_IRQ_GATTC_SERVICE_DONE10
서비스 검색이 완료되었습니다.
(conn_handle, status)_IRQ_GATTC_CHARACTERISTIC_RESULT11
gattc_discover_characteristics에 의해 하나의 특성이 발견되었습니다.(conn_handle, end_handle, value_handle, properties, uuid)_IRQ_GATTC_CHARACTERISTIC_DONE12
특성 검색이 완료되었습니다.
(conn_handle, status)_IRQ_GATTC_DESCRIPTOR_RESULT13
gattc_discover_descriptors에 의해 하나의 디스크립터가 발견되었습니다.(conn_handle, dsc_handle, uuid)_IRQ_GATTC_DESCRIPTOR_DONE14
디스크립터 검색이 완료되었습니다.
(conn_handle, status)_IRQ_GATTC_READ_RESULT15
이전에 실행한
gattc_read가 데이터를 반환했습니다.(conn_handle, value_handle, char_data)_IRQ_GATTC_READ_DONE16
이전에 실행한
gattc_read가 완료되었습니다.(conn_handle, value_handle, status)_IRQ_GATTC_WRITE_DONE17
이전에 실행한
gattc_write가 확인(acknowledge)되었습니다.(conn_handle, value_handle, status)_IRQ_GATTC_NOTIFY18
원격 서버가 (확인되지 않은) 알림(notification)을 보냈습니다.
(conn_handle, value_handle, notify_data)_IRQ_GATTC_INDICATE19
원격 서버가 (확인된) 표시(indication)를 보냈습니다.
(conn_handle, value_handle, notify_data)_IRQ_GATTS_INDICATE_DONE20
이전에 보낸 표시(indication)가 클라이언트에 의해 확인되었습니다(또는 시간 초과되었습니다).
(conn_handle, value_handle, status)_IRQ_MTU_EXCHANGED21
ATT MTU 교환이 완료되었습니다(양쪽 중 어느 한쪽이 시작).
(conn_handle, mtu)_IRQ_L2CAP_ACCEPT22
원격 장치가 이 장치가 수신 대기 중인 PSM에 L2CAP 연결을 요청했습니다. 거부하려면 0이 아닌 정수를 반환하고, 수락하려면
0/None을 반환하세요.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_CONNECT23
들어오는 요청을 수락하거나 나가는
l2cap_connect를 완료하여 L2CAP 채널이 이제 설정되었습니다.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_DISCONNECT24
L2CAP 채널이 연결 해제되었습니다.
status는 정상적인 연결 해제의 경우0이고, 나가는 연결 시도가 실패한 경우 0이 아닙니다.(conn_handle, cid, psm, status)_IRQ_L2CAP_RECV25
L2CAP 채널에 데이터가 도착했습니다. 이를 읽으려면
l2cap_recvinto를 호출하세요.(conn_handle, cid)_IRQ_L2CAP_SEND_READY26
False를 반환했던 이전l2cap_send가 비워지고 채널이 다시 준비되었습니다. 0이 아닌status는 송신 버퍼가 오버플로되어 애플리케이션이 데이터를 다시 보내야 함을 의미합니다.(conn_handle, cid, status)_IRQ_CONNECTION_UPDATE27
원격 장치가 연결 매개변수(interval, latency, supervision timeout)를 업데이트했습니다.
(conn_handle, conn_interval, conn_latency, supervision_timeout, status)_IRQ_ENCRYPTION_UPDATE28
연결의 암호화 상태가 변경되었으며, 일반적으로 페어링 또는 본딩이 완료된 후에 발생합니다.
(conn_handle, encrypted, authenticated, bonded, key_size)_IRQ_GET_SECRET29
스택이 저장된 본딩 비밀(secret)을 요청하고 있습니다.
key가None이면sec_type의index번째 저장된 값을 반환하고, 그렇지 않으면 주어진(sec_type, key)와 연관된 값을 반환하세요. 저장된 것이 없으면None을 반환하세요.(sec_type, index, key)_IRQ_SET_SECRET30
스택이 애플리케이션에 본딩 비밀(secret)을 영구 저장하도록 요청하고 있습니다. 저장이 완료되면
True를 반환하세요.(sec_type, key, value)_IRQ_PASSKEY_ACTION31
페어링의 일부로 패스키(passkey) 작업이 필요합니다.
gap_passkey를 사용하여 응답하세요. 가능한 작업은 아래 패스키 작업 표를 참고하세요.(conn_handle, action, passkey)_IRQ_GATTS_READ_REQUEST이벤트의 경우, 사용 가능한 반환 코드는 다음과 같습니다:상수
값
의미
_GATTS_NO_ERROR0x00읽기를 수락합니다.
_GATTS_ERROR_READ_NOT_PERMITTED0x02읽기가 허용되지 않습니다.
_GATTS_ERROR_WRITE_NOT_PERMITTED0x03쓰기가 허용되지 않습니다.
_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION0x05클라이언트가 인증되지 않았습니다.
_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION0x08클라이언트가 권한이 없습니다.
_GATTS_ERROR_INSUFFICIENT_ENCRYPTION0x0f링크가 암호화되지 않았습니다.
_IRQ_PASSKEY_ACTION이벤트의 경우, 사용 가능한 작업은 다음과 같습니다:상수
값
의미
_PASSKEY_ACTION_NONE0
필요한 작업이 없습니다.
_PASSKEY_ACTION_INPUT2
원격 장치에 표시된 패스키를 입력하도록 사용자에게 요청합니다.
_PASSKEY_ACTION_DISPLAY3
원격 장치가 입력할 6자리 패스키를 표시합니다.
_PASSKEY_ACTION_NUMERIC_COMPARISON4
패스키가 원격 장치에 표시된 것과 일치하는지 확인합니다.
펌웨어의 공간을 절약하기 위해 이러한 상수는
bluetooth모듈에 포함되어 있지 않습니다. 위 목록에서 필요한 것을 프로그램에 추가하세요.
Broadcaster 역할(광고자)
- gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None¶
지정된 간격(마이크로초 단위)으로 광고를 시작합니다. 이 간격은 가장 가까운 625us 단위로 내림됩니다. 광고를 중지하려면 interval_us를
None으로 설정하세요.adv_data와 resp_data는 버퍼 프로토콜을 구현하는 모든 유형(예:
bytes,bytearray,str)이 될 수 있습니다. adv_data는 모든 브로드캐스트에 포함되며, resp_data는 활성 스캔에 대한 응답으로 전송됩니다.참고: adv_data(또는 resp_data)가
None이면 이전gap_advertise호출에 전달된 데이터가 재사용됩니다. 이를 통해 브로드캐스터는gap_advertise(interval_us)만으로 광고를 재개할 수 있습니다. 광고 페이로드를 지우려면 빈bytes, 즉b''를 전달하세요.
Observer 역할(스캐너)
- gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None¶
지정된 지속 시간(밀리초 단위) 동안 스캔 작업을 실행합니다.
무기한 스캔하려면 duration_ms를
0으로 설정하세요.스캔을 중지하려면 duration_ms를
None으로 설정하세요.interval_us와 window_us를 사용하여 듀티 사이클을 선택적으로 설정할 수 있습니다. 스캐너는 총 duration_ms 밀리초 동안 interval_us 마이크로초마다 window_us 마이크로초씩 실행됩니다. 기본 interval과 window는 각각 1.28초와 11.25밀리초입니다(백그라운드 스캔).
각 스캔 결과에 대해 이벤트 데이터
(addr_type, addr, adv_type, rssi, adv_data)와 함께_IRQ_SCAN_RESULT이벤트가 발생합니다.addr_type값은 public 또는 random 주소를 나타냅니다:값
이름
의미
0x00PUBLIC
Public 장치 주소.
0x01RANDOM
Random 주소(static, RPA 또는 NRPA 중 하나이며, 유형은 주소 자체에 인코딩되어 있습니다).
adv_type값은 Bluetooth 사양에 해당합니다:값
이름
의미
0x00ADV_IND
연결 가능하고 스캔 가능한 비지향성 광고.
0x01ADV_DIRECT_IND
연결 가능한 지향성 광고.
0x02ADV_SCAN_IND
스캔 가능한 비지향성 광고.
0x03ADV_NONCONN_IND
연결 불가능한 비지향성 광고.
0x04SCAN_RSP
스캔 응답.
결과에서 스캔 응답을 받으려면
active를True로 설정할 수 있습니다.스캔이 중지되면(지속 시간이 끝나거나 명시적으로 중지될 때),
_IRQ_SCAN_DONE이벤트가 발생합니다.
Central 역할
central 장치는 observer 역할을 사용하여 발견한(
gap_scan참고) peripheral이나 알려진 주소를 가진 peripheral에 연결할 수 있습니다.- gap_connect(addr_type: int | None, addr: bytes | None = None, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /) None¶
peripheral에 연결합니다.
주소 유형에 대한 자세한 내용은
gap_scan을 참고하세요.진행 중인 연결 시도를 조기에 취소하려면
gap_connect(None)을 호출하세요.성공하면
_IRQ_PERIPHERAL_CONNECT이벤트가 발생합니다. 연결 시도를 취소하는 경우_IRQ_PERIPHERAL_DISCONNECT이벤트가 발생합니다.장치는 해당 장치로부터 광고 페이로드를 받기 위해 최대 scan_duration_ms 동안 대기합니다.
연결 interval은 min_conn_interval_us와 max_conn_interval_us 중 하나 또는 둘 다를 사용하여 마이크로초 단위로 설정할 수 있습니다. 그렇지 않으면 일반적으로 30000에서 50000마이크로초 사이의 기본 interval이 선택됩니다. interval이 짧을수록 전력 사용량을 희생하여 처리량이 증가합니다.
Peripheral 역할
peripheral 장치는 연결 가능한 광고를 보내야 합니다(
gap_advertise참고). 일반적으로 먼저gatts_register_services를 사용하여 서비스와 특성을 등록한 후 GATT 서버로 동작합니다.central이 연결되면
_IRQ_CENTRAL_CONNECT이벤트가 발생합니다.Central 및 Peripheral 역할
- gap_disconnect(conn_handle: int, /) bool¶
지정된 연결 핸들을 연결 해제합니다. 이는 이 장치에 연결된 central(peripheral로 동작하는 경우)이거나 이전에 이 장치가 연결한 peripheral(central로 동작하는 경우)일 수 있습니다.
성공하면
_IRQ_PERIPHERAL_DISCONNECT또는_IRQ_CENTRAL_DISCONNECT이벤트가 발생합니다.연결 핸들이 연결되어 있지 않으면
False를, 그렇지 않으면True를 반환합니다.
GATT 서버
GATT 서버에는 등록된 서비스 집합이 있습니다. 각 서비스에는 특성이 포함될 수 있으며, 각 특성에는 값이 있습니다. 특성에는 디스크립터도 포함될 수 있으며, 디스크립터 자체에도 값이 있습니다.
이러한 값은 로컬에 저장되며, 서비스 등록 중에 생성되는 “value handle”을 통해 접근됩니다. 또한 원격 클라이언트 장치에서 읽거나 쓸 수 있습니다. 추가로, 서버는 연결 핸들을 통해 연결된 클라이언트에게 특성을 “알림(notify)”할 수 있습니다.
central 또는 peripheral 역할의 장치 모두 GATT 서버로 기능할 수 있지만, 대부분의 경우 peripheral 장치가 서버 역할을 하는 것이 더 일반적입니다.
특성과 디스크립터의 기본 최대 크기는 20바이트입니다(기본 ATT MTU 23바이트에서 3바이트 ATT 헤더를 뺀 값이며, 더 큰 MTU를 협상하는 것만으로는 이 한도가 늘어나지 않습니다). 클라이언트가 쓰는 모든 데이터는 이 길이로 잘립니다. 그러나 모든 로컬 쓰기는 최대 크기를 늘리므로, 클라이언트가 특정 특성에 더 큰 쓰기를 할 수 있도록 하려면 등록 후
gatts_write를 사용하세요. 예:gatts_write(char_handle, bytes(100)).- gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]¶
지정된 서비스로 서버를 설정하며, 기존 서비스를 모두 대체합니다.
services_definition은 서비스의 리스트이며, 각 서비스는 UUID와 특성 리스트를 포함하는 2요소 튜플입니다.
각 특성은 UUID, flags 값, 그리고 선택적으로 descriptors 리스트를 포함하는 2요소 또는 3요소 튜플입니다.
각 descriptor는 UUID와 flags 값을 포함하는 2요소 튜플입니다.
flags는 아래에 정의된 플래그의 비트 OR 조합입니다. 이는 특성(또는 디스크립터)의 동작과 함께 보안 및 프라이버시 요구 사항을 모두 설정합니다.
반환 값은 튜플의 리스트(서비스당 하나의 요소)이며, 각 요소는 value handle입니다. 특성과 디스크립터 핸들은 정의된 순서대로 동일한 튜플로 평탄화됩니다.
다음 예제는 두 가지 서비스(Heart Rate와 Nordic UART)를 등록합니다:
bt = bluetooth.BLE() bt.active(True) # Heart Rate service: one Heart Rate Measurement characteristic. HR_SERVICE = ( bluetooth.UUID(0x180D), ( (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), ), ) # Nordic UART service: a TX characteristic the client subscribes # to for notifications, and an RX characteristic it writes to. UART_SERVICE = ( bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'), ( (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE), ), ) ((hr,), (tx, rx)) = bt.gatts_register_services( (HR_SERVICE, UART_SERVICE), )
세 개의 value handle(
hr,tx,rx)은gatts_read,gatts_write,gatts_notify,gatts_indicate와 함께 사용할 수 있습니다.참고: 서비스를 등록하기 전에 광고를 중지해야 합니다.
특성과 디스크립터에 사용할 수 있는 플래그는 다음과 같습니다:
상수
값
의미
_FLAG_BROADCAST0x0001특성을 브로드캐스트할 수 있습니다.
_FLAG_READ0x0002클라이언트가 값을 읽을 수 있습니다.
_FLAG_WRITE_NO_RESPONSE0x0004클라이언트가 응답을 기대하지 않고 쓸 수 있습니다.
_FLAG_WRITE0x0008클라이언트가 확인 응답과 함께 쓸 수 있습니다.
_FLAG_NOTIFY0x0010서버가 알림(notification, 확인되지 않음)을 보낼 수 있습니다.
_FLAG_INDICATE0x0020서버가 표시(indication, 확인됨)를 보낼 수 있습니다.
_FLAG_AUTHENTICATED_SIGNED_WRITE0x0040클라이언트가 서명된 쓰기를 수행할 수 있습니다.
_FLAG_AUX_WRITE0x0100확장 속성: 큐잉/신뢰성 쓰기가 허용됩니다.
_FLAG_READ_ENCRYPTED0x0200읽기에 암호화된 링크가 필요합니다.
_FLAG_READ_AUTHENTICATED0x0400읽기에 인증된(MITM 보호) 링크가 필요합니다.
_FLAG_READ_AUTHORIZED0x0800읽기에 애플리케이션 수준의 권한 부여가 필요합니다.
_FLAG_WRITE_ENCRYPTED0x1000쓰기에 암호화된 링크가 필요합니다.
_FLAG_WRITE_AUTHENTICATED0x2000쓰기에 인증된(MITM 보호) 링크가 필요합니다.
_FLAG_WRITE_AUTHORIZED0x4000쓰기에 애플리케이션 수준의 권한 부여가 필요합니다.
위의 이벤트 상수와 마찬가지로, 이러한 플래그는
bluetooth모듈에서 제공되지 않습니다. 필요한 것을 프로그램에 복사하세요.
- gatts_read(value_handle: int, /) bytes¶
이 핸들의 로컬 값을 읽습니다(이 값은
gatts_write에 의해 쓰였거나 원격 클라이언트에 의해 쓰인 것입니다).
- gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None¶
이 핸들의 로컬 값을 쓰며, 이 값은 클라이언트가 읽을 수 있습니다.
send_update가
True이면 구독한 모든 클라이언트가 이 쓰기에 대해 알림(또는 구독한 내용과 특성이 지원하는 작업에 따라 표시)을 받습니다.
- gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
연결된 클라이언트에게 알림 요청을 보냅니다.
data 가
None(기본값) 이면, (gatts_write로 설정된) 현재 로컬 값이 전송됩니다.그렇지 않고 data가
None이 아니면 해당 값이 알림의 일부로 클라이언트에 전송됩니다. 로컬 값은 수정되지 않습니다.참고: 이 특성에 대한 클라이언트의 구독 상태와 관계없이 알림이 전송됩니다.
- gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
연결된 클라이언트에게 표시(indication) 요청을 보냅니다.
data 가
None(기본값) 이면, (gatts_write로 설정된) 현재 로컬 값이 전송됩니다.그렇지 않고 data가
None이 아니면 해당 값이 표시의 일부로 클라이언트에 전송됩니다. 로컬 값은 수정되지 않습니다.확인(또는 시간 초과 등의 실패) 시
_IRQ_GATTS_INDICATE_DONE이벤트가 발생합니다.참고: 이 특성에 대한 클라이언트의 구독 상태와 관계없이 표시가 전송됩니다.
- gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None¶
값에 대한 내부 버퍼 크기를 바이트 단위로 설정합니다. 이는 수신할 수 있는 가장 큰 쓰기를 제한합니다. 기본값은 20바이트입니다(기본 ATT MTU 23에서 3바이트 ATT 헤더를 뺀 값).
append를
True로 설정하면 모든 원격 쓰기가 현재 값을 대체하는 대신 추가됩니다. 이 방식으로 최대 len 바이트까지 버퍼링할 수 있습니다.gatts_read를 사용하면 읽은 후 값이 지워집니다. 이 기능은 Nordic UART Service와 같은 것을 구현할 때 유용합니다.
GATT 클라이언트
GATT 클라이언트는 원격 GATT 서버의 특성을 검색하고 읽거나 쓸 수 있습니다.
central 역할 장치가 GATT 클라이언트로 동작하는 것이 더 일반적이지만, peripheral이 연결된 central에 대한 정보를 검색하기 위해(예: device information service에서 장치 이름을 읽기 위해) 클라이언트로 동작하는 것도 가능합니다.
- gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None¶
연결된 서버에 서비스를 조회합니다.
선택적으로 서비스 uuid를 지정하여 해당 서비스만 조회할 수 있습니다.
발견된 각 서비스에 대해
_IRQ_GATTC_SERVICE_RESULT이벤트가 발생하고, 완료 시_IRQ_GATTC_SERVICE_DONE이 뒤따릅니다.
- gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None¶
연결된 서버에 지정된 범위의 특성을 조회합니다.
선택적으로 특성 uuid를 지정하여 해당 특성만 조회할 수 있습니다.
start_handle=1과end_handle=0xffff를 전달하면 전체 GATT 속성 핸들 범위를 포함하므로, 이 조합은 사실상 원격 장치의 모든 서비스를 검색합니다.발견된 각 특성에 대해
_IRQ_GATTC_CHARACTERISTIC_RESULT이벤트가 발생하고, 완료 시_IRQ_GATTC_CHARACTERISTIC_DONE이 뒤따릅니다.
- gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None¶
연결된 서버에 지정된 범위의 디스크립터를 조회합니다.
발견된 각 디스크립터에 대해
_IRQ_GATTC_DESCRIPTOR_RESULT이벤트가 발생하고, 완료 시_IRQ_GATTC_DESCRIPTOR_DONE이 뒤따릅니다.
- gattc_read(conn_handle: int, value_handle: int, /) None¶
지정된 특성 또는 디스크립터 핸들에 대해 연결된 서버에 원격 읽기를 실행합니다.
값을 사용할 수 있게 되면
_IRQ_GATTC_READ_RESULT이벤트가 발생하고, 완료 시_IRQ_GATTC_READ_DONE이 뒤따릅니다.
- gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None¶
지정된 특성 또는 디스크립터 핸들에 대해 연결된 서버에 원격 쓰기를 실행합니다.
mode 인수는 쓰기 동작을 지정하며, 현재 지원되는 값은 다음과 같습니다:
mode=0(기본값) 은 응답 없는 쓰기입니다. 쓰기는 원격 서버로 전송되지만 확인은 반환되지 않으며, 어떤 이벤트도 발생하지 않습니다.mode=1은 응답 있는 쓰기입니다. 원격 서버가 데이터를 받았다는 응답/확인을 보내도록 요청됩니다.
원격 서버로부터 응답을 받으면
_IRQ_GATTC_WRITE_DONE이벤트가 발생합니다.
- gattc_exchange_mtu(conn_handle: int, /) None¶
BLE.config(mtu=value)로 설정한 선호 MTU를 사용하여 연결된 서버와 MTU 교환을 시작합니다.MTU 교환이 완료되면
_IRQ_MTU_EXCHANGED이벤트가 발생합니다.MTU 교환은 일반적으로 central이 시작하지만, NimBLE는 두 역할을 모두 지원합니다.
L2CAP 연결 지향 채널
이 기능은 두 BLE 장치 간의 소켓과 유사한 데이터 교환을 가능하게 합니다. 장치가 GAP를 통해 연결되면, 어느 한 장치든 다른 장치가 숫자 PSM(Protocol/Service Multiplexer)으로 연결하기를 수신 대기할 수 있습니다.
한 번에 하나의 L2CAP 채널만 활성화될 수 있습니다(즉, 수신 대기 중에는 연결할 수 없습니다).
활성 L2CAP 채널은 설정된 연결 핸들과 CID(channel ID)로 식별됩니다.
연결 지향 채널에는 크레딧 기반 흐름 제어가 내장되어 있습니다. 장치가 공유 MTU를 협상하는 ATT와 달리, 수신 대기 장치와 연결 장치는 각각 독립적인 MTU를 설정하며, 이는 원격 장치가
l2cap_recvinto에서 완전히 소비되기 전에 보낼 수 있는 미처리 데이터의 최대량을 제한합니다.- l2cap_listen(psm: int, mtu: int, /) None¶
로컬 MTU를 mtu로 설정한 상태에서 지정된 psm으로 들어오는 L2CAP 채널 요청을 수신 대기하기 시작합니다.
원격 장치가 연결을 시작하면
_IRQ_L2CAP_ACCEPT이벤트가 발생하며, 이는 수신 대기 서버가 (0이 아닌 정수를 반환하여) 들어오는 연결을 거부할 기회를 제공합니다.연결이 수락되면
_IRQ_L2CAP_CONNECT이벤트가 발생하여 서버가 channel ID(CID)와 로컬 및 원격 MTU를 얻을 수 있게 합니다.참고: 현재 수신 대기를 중지하는 것은 불가능합니다.
- l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None¶
로컬 MTU를 mtu로 설정한 상태에서 지정된 psm의 수신 대기 중인 피어에 연결합니다.
연결에 성공하면
_IRQ_L2CAP_CONNECT이벤트가 발생하여 클라이언트가 CID와 로컬 및 원격(피어) MTU를 얻을 수 있게 합니다.연결에 실패하면 0이 아닌 status와 함께
_IRQ_L2CAP_DISCONNECT이벤트가 발생합니다.
- l2cap_disconnect(conn_handle: int, cid: int, /) None¶
지정된 conn_handle과 cid를 가진 활성 L2CAP 채널을 연결 해제합니다.
- l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool¶
conn_handle 와 cid 로 식별되는 L2CAP 채널을 통해 지정된 buf (버퍼 프로토콜을 지원해야 함) 를 전송합니다.
버퍼는 두 가지 한도를 모두 충족해야 합니다. 원격(피어) MTU를 초과해서는 안 되며, 로컬 MTU의 두 배를 초과해서는 안 됩니다.
채널이 이제 “정체(stalled)” 상태이면
False를 반환하며, 이는_IRQ_L2CAP_SEND_READY이벤트를 받을 때까지(원격 장치가 더 많은 크레딧을 부여할 때, 일반적으로 데이터를 받아 처리한 후 발생)l2cap_send를 다시 호출해서는 안 됨을 의미합니다.
- l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int¶
지정된 conn_handle 와 cid 로부터 데이터를 받아 제공된 buf (버퍼 프로토콜을 지원해야 하며, 예를 들어 bytearray 또는 memoryview) 에 저장합니다.
채널에서 읽은 바이트 수를 반환합니다.
buf가
None이면 사용 가능한 바이트 수를 반환합니다.참고:
_IRQ_L2CAP_RECV이벤트를 받은 후, 애플리케이션은 수신 버퍼에 더 이상 사용 가능한 바이트가 없을 때까지(일반적으로 원격(피어) MTU 크기까지)l2cap_recvinto를 계속 호출해야 합니다.수신 버퍼가 비워질 때까지 원격 장치에는 더 많은 채널 크레딧이 부여되지 않으며 더 이상 데이터를 보낼 수 없습니다.
페어링 및 본딩
페어링을 통해 비밀(secret) 교환을 통해 연결을 암호화하고 인증할 수 있습니다(패스키 인증을 통한 선택적 MITM 보호 포함).
본딩은 그러한 비밀을 비휘발성 저장소에 저장하는 과정입니다. 본딩되면 장치는 저장된 identity resolving key(IRK)를 기반으로 다른 장치의 resolvable private address(RPA)를 확인할 수 있습니다. 본딩을 지원하려면 애플리케이션이
_IRQ_GET_SECRET과_IRQ_SET_SECRET이벤트를 구현해야 합니다.- gap_pair(conn_handle: int, /) None¶
원격 장치와 페어링을 시작합니다.
이를 호출하기 전에
io,mitm,le_secure,bond설정 옵션이 설정되어 있는지 확인하세요(config를 통해).페어링에 성공하면
_IRQ_ENCRYPTION_UPDATE이벤트가 발생합니다.
- gap_passkey(conn_handle: int, action: int, passkey: int, /) None¶
지정된 conn_handle과 action에 대한
_IRQ_PASSKEY_ACTION이벤트에 응답합니다. passkey의 의미는 action에 따라 다릅니다(이는 다시 설정된 I/O 기능에 따라 다릅니다):작업
필요한 passkey 응답
_PASSKEY_ACTION_INPUT사용자가 원격 장치에서 읽은 패스키.
_PASSKEY_ACTION_DISPLAY사용자에게 표시되는 로컬에서 생성된 무작위 6자리 패스키.
_PASSKEY_ACTION_NUMERIC_COMPARISON_IRQ_PASSKEY_ACTION이벤트에 표시된 패스키를 수락하려면1, 페어링을 취소하려면0.
class UUID¶
- class bluetooth.UUID(value: int | bytes | str, /)¶
지정된
value로 UUID 인스턴스를 생성합니다. Bluetooth는 세 가지 UUID 폭을 사용하며,UUID는 그중 어느 것이든 받습니다:UUID 폭
허용되는
value유형예시
16비트
int또는 2바이트 버퍼(little-endian)UUID(0x2908)또는UUID(b'\x08\x29')32비트
4바이트 버퍼(little-endian)
UUID(b'\x08\x29\x00\x00')128비트
16바이트 버퍼 또는 하이픈으로 구분된 문자열
UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')16비트 및 32비트 UUID는 일반적으로 SIG가 할당한 식별자입니다(Bluetooth assigned numbers 참고). 128비트 UUID는 일반적으로 벤더가 정의합니다.