ubluepy — Bluetooth LE 주변장치 및 센트럴

ubluepy 모듈은 MicroPython nRF 포트에 함께 제공되는 레거시 Bluetooth LE API입니다. 이는 Linux의 bluepy Python 라이브러리를 느슨하게 본떠 만들어졌으며 Nordic SoftDevice 위에 직접 올라갑니다. 이식 가능한 백엔드가 없으므로 이 모듈은 Nordic 타겟(OpenMV 제품군에서는 Arduino Nano 33 BLE Sense)에서만 사용할 수 있습니다. 더 새로운 bluetooth / aioble API는 이 빌드에서 활성화되어 있지 않으므로, ubluepy가 온다이 라디오를 구동하는 유일한 방법입니다.

사용 가능한 기능 집합은 펌웨어가 플래시한 SoftDevice에 따라 달라집니다:

  • s140 (Nano 33 BLE Sense) — 주변장치 센트럴(스캐너) 역할을 모두 지원합니다. OpenMV 펌웨어가 제공하는 것이 이것입니다.

  • s132 — 주변장치 및 센트럴 모두를 지원합니다.

  • s110 — 주변장치만 지원하며, 스캐너 / 연결 메서드는 컴파일에서 제외됩니다.

주변장치 예제

단일 환경 감지 서비스를 갖는 Bluetooth LE 주변장치로 광고하고, 그 Client Characteristic Configuration Descriptor(CCCD)에 쓰기가 발생할 때마다 온도 특성을 통지합니다:

from ubluepy import Service, Characteristic, UUID, Peripheral, constants
from machine import LED

notif_enabled = False

def event_handler(event_id, handle, data):
    global notif_enabled
    if event_id == constants.EVT_GAP_CONNECTED:
        LED("LED_GREEN").on()
    elif event_id == constants.EVT_GAP_DISCONNECTED:
        LED("LED_GREEN").off()
        periph.advertise(device_name="Nano 33", services=[svc])
    elif event_id == constants.EVT_GATTS_WRITE:
        notif_enabled = bool(data[0])

svc = Service(UUID("181A"))            # Environmental Sensing
char = Characteristic(UUID("2A6E"),
                      props=Characteristic.PROP_NOTIFY | Characteristic.PROP_READ,
                      attrs=Characteristic.ATTR_CCCD)
svc.addCharacteristic(char)

periph = Peripheral()
periph.addService(svc)
periph.setConnectionHandler(event_handler)
periph.advertise(device_name="Nano 33", services=[svc])

센트럴 예제

주변의 광고 중인 장치를 100 ms 동안 스캔하고 각 ScanEntry의 광고 데이터를 디코딩합니다:

from ubluepy import Scanner, constants

s = Scanner()
for entry in s.scan(100):
    print(entry.addr(), entry.rssi(), "dBm")
    for ad_type, name, value in entry.getScanData():
        print(" ", ad_type, name, bytes(value))

모듈 내용

클래스

class ubluepy.UUID(value)

16비트 또는 128비트 Bluetooth UUID를 생성합니다.

value

다음 중 하나:

  • int — 16비트 숫자 UUID(UUID(0x180A)).

  • 6문자 "0xXXXX" 문자열 — 16비트 UUID, 예: UUID("0x181A").

  • 36문자 "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 문자열 — 완전한 128비트 UUID. 벤더 고유 부분은 생성 시 SoftDevice에 등록됩니다.

  • 다른 UUID 인스턴스 — 복사를 수행합니다.

그 외의 길이는 ValueError("Invalid UUID string length")를 발생시킵니다.

binVal() int

UUID의 하위 16비트를 int로 반환합니다. 128비트 UUID의 경우 벤더 고유 UUID 내부에 포함된 16비트 필드만 반환됩니다(완전한 128비트 값은 SoftDevice의 벤더 고유 인덱스를 통해서만 접근할 수 있습니다).

class ubluepy.Service(uuid: UUID, type: int = Service.PRIMARY)

Peripheral에 추가될 때 SoftDevice에 등록될 GATT 서비스를 정의합니다.

uuid

UUID 인스턴스입니다. UUID가 아닌 객체를 전달하면 ValueError가 발생합니다.

type

Service.PRIMARY(기본값) 또는 Service.SECONDARY 중 하나입니다. 다른 값은 ValueError를 발생시킵니다.

uuid() UUID

서비스의 UUID 인스턴스를 반환합니다.

addCharacteristic(characteristic: Characteristic) None

Characteristic을 서비스에 등록합니다. 특성의 GATT 핸들은 이 호출 중에 할당됩니다.

getCharacteristic(uuid: UUID) Characteristic | None

이전에 추가된 Characteristic을 UUID로 조회합니다. 특성 인스턴스를 반환하거나, 일치하는 것이 없으면 None을 반환합니다.

getCharacteristics() list

서비스에 추가된 모든 특성의 목록을 반환합니다.

PRIMARY: int

기본(primary) 서비스에 대한 서비스 타입 상수(1).

SECONDARY: int

보조(secondary) 서비스에 대한 서비스 타입 상수(2).

class ubluepy.Characteristic(uuid: UUID, *, props: int = PROP_READ | PROP_WRITE, attrs: int = 0)

GATT 특성을 정의합니다. 상위 Peripheral이 광고를 시작하기 전에 Service.addCharacteristic()으로 Service에 추가하세요.

uuid

UUID 인스턴스입니다.

props (키워드 전용)

특성이 지원하는 작업을 설명하는 하나 이상의 Characteristic.PROP_* 값의 비트마스크입니다.

attrs (키워드 전용)

추가 GATT 속성의 비트마스크입니다. Client Characteristic Configuration Descriptor를 부착하려면 Characteristic.ATTR_CCCD를 사용하세요 — PROP_NOTIFY / PROP_INDICATE 특성이 동작하려면 필요합니다.

uuid() UUID

특성의 UUID 인스턴스를 반환합니다.

properties() int

생성 시 설정된 props 비트마스크를 반환합니다.

read() bytearray

센트럴 역할 전용. 연결된 피어로부터 특성의 값을 읽습니다. 최신 값을 담은 bytearray를 반환합니다. 주변장치에서는 아무 작업도 하지 않으며 None을 반환합니다.

write(data, *, with_response: bool = False) None

특성에 값을 씁니다.

  • 주변장치에서는 특성의 속성에 PROP_NOTIFY가 설정되어 있으면 값이 연결된 센트럴에 GATT 통지로 전송됩니다. 그렇지 않으면 로컬 속성 값이 업데이트됩니다.

  • 센트럴에서는 값이 원격 피어에 기록됩니다. write 명령 대신 write 요청을 발행하고 피어의 확인 응답을 기다리려면 with_response=True를 설정하세요.

data는 버퍼 프로토콜을 따르는 임의의 객체(bytes, bytearray, memoryview)입니다.

PROP_BROADCAST: int

특성이 값을 브로드캐스트할 수 있습니다(0x01).

PROP_READ: int

특성이 읽기를 지원합니다(0x02).

PROP_WRITE_WO_RESP: int

특성이 응답 없는 쓰기를 지원합니다(0x04).

PROP_WRITE: int

특성이 응답 있는 쓰기를 지원합니다(0x08).

PROP_NOTIFY: int

특성이 구독 중인 센트럴에 통지를 푸시할 수 있습니다(0x10).

PROP_INDICATE: int

특성이 구독 중인 센트럴에 표시(확인 응답이 있는 통지)를 푸시할 수 있습니다(0x20).

PROP_AUTH_SIGNED_WR: int

특성이 인증된 서명 쓰기를 지원합니다(0x40).

ATTR_CCCD: int

특성에 Client Characteristic Configuration Descriptor를 추가합니다(0x01). 클라이언트가 통지/표시를 구독할 수 있으려면 필요합니다.

class ubluepy.Descriptor(uuid: UUID)

GATT 디스크립터를 표현하기 위한 스텁 클래스입니다. 현재 구현은 UUID만 저장하며 메서드를 노출하지 않습니다 — 이 모듈의 향후 개정판과의 상위 호환성을 위해 제공됩니다.

class ubluepy.Peripheral

로컬 Bluetooth LE 장치입니다. 동일한 클래스가 주변장치와 센트럴 역할 모두에 사용됩니다. 역할은 어떤 메서드를 호출하느냐에 따라 선택됩니다(advertise()는 주변장치를, connect()는 센트럴을 선택합니다).

addService(service: Service) None

Service(및 이전에 추가된 모든 특성)를 로컬 GATT 서버에 등록합니다.

getServices() list

현재 이 Peripheral에 등록된 서비스 목록을 반환합니다.

advertise(*, device_name: str | None = None, services: list | None = None, data: bytes | None = None, connectable: bool = True) None

주변장치 역할로 광고를 시작합니다.

device_name

GAP 페이로드에 광고되는 완전한 로컬 이름입니다.

services

광고할 Service 인스턴스의 목록입니다. 각 서비스의 UUID가 광고에 포함됩니다.

data

자동 생성된 헤더에 추가되는 선택적 원시 광고 페이로드(bytes / bytearray)입니다. Eddystone 같은 벤더 고유 또는 비콘 페이로드에 사용하세요.

connectable

True(기본값)이면 연결 가능한 장치로 광고하고 GAP / GATTS 이벤트 핸들러를 등록하여 구성된 setConnectionHandler() 콜백이 연결, 연결 해제, CCCD 쓰기 시 호출되도록 합니다. False이면 비콘으로 광고하며, 핸들러가 연결되지 않고 장치에 연결할 수 없습니다.

advertise_stop() None

진행 중인 광고를 중지합니다.

setConnectionHandler(func) None

GAP 및 GATTS 이벤트에서 호출되는 콜백을 등록합니다. 콜백은 func(event_id, conn_handle, data)로 호출되며, 여기서 event_idconstants.EVT_GAP_CONNECTED, constants.EVT_GAP_DISCONNECTED, constants.EVT_GATTS_WRITE 값 중 하나이고, conn_handle은 SoftDevice 연결 핸들(또는 GATTS 쓰기의 경우 속성 핸들)이며, databytearray 형태의 원시 이벤트 페이로드(또는 연결 / 연결 해제의 경우 None)입니다.

setNotificationHandler(func) None

센트럴 역할에서 수신되는 통지 이벤트에 대한 콜백을 등록합니다.

withDelegate(delegate: DefaultDelegate) None

디코딩된 GATT 이벤트를 수신하도록 DefaultDelegate 인스턴스를 부착합니다.

disconnect() None

활성 연결을 끊습니다(이 빌드에서는 현재 아무 작업도 하지 않는 스텁입니다).

connect(addr, *, addr_type: int = constants.ADDR_TYPE_PUBLIC) None

센트럴 역할 전용. 주어진 주소의 피어에 연결하고 해당 피어의 기본 서비스와 특성을 동기적으로 검색합니다. 연결이 수립되고 검색이 완료될 때까지 블록됩니다. 검색된 서비스는 그 후 getServices()를 통해 사용할 수 있습니다.

addr

17문자 "xx:xx:xx:xx:xx:xx" 문자열 형태의 피어 주소(예: ScanEntry.addr()에서 가져온 것)입니다.

addr_type (키워드 전용)

constants.ADDR_TYPE_PUBLIC(기본값) 또는 constants.ADDR_TYPE_RANDOM_STATIC 중 하나입니다.

class ubluepy.Scanner

주변의 광고 중인 장치를 검색하는 GAP 옵저버입니다. 펌웨어가 센트럴을 지원하는 SoftDevice(s132 / s140)로 빌드된 경우에만 사용할 수 있습니다.

scan(timeout: int) list

timeout 밀리초 동안 수동 스캔을 실행하고 ScanEntry 인스턴스의 목록을 반환합니다 — 윈도우 동안 수신된 광고 보고마다 하나씩입니다.

class ubluepy.ScanEntry

Scanner.scan()이 캡처한 단일 광고 보고입니다. 인스턴스는 스캐너에서 반환되며 — 공개 생성자는 없습니다.

addr() str

피어 주소를 17문자 "xx:xx:xx:xx:xx:xx" 문자열로 반환합니다.

addr_type() int

피어 주소 타입(constants.ADDR_TYPE_PUBLIC 또는 constants.ADDR_TYPE_RANDOM_STATIC)을 반환합니다.

rssi() int

신호 강도 지표를 dBm 단위로 반환합니다.

getScanData() list

광고 페이로드를 (ad_type, description, value) 튜플의 목록으로 디코딩합니다. ad_type은 숫자 AD 타입 바이트(constants.ad_types 참조)이고, description은 일치하는 상수의 이름을 문자열로 나타낸 것(또는 타입을 알 수 없는 경우 None)이며, value는 AD 레코드 본문을 bytearray로 나타낸 것입니다.

class ubluepy.DefaultDelegate

Peripheral.withDelegate()에 전달되는 객체의 기본 클래스입니다. 이를 서브클래싱하고 handleConnection() / handleNotification()을 오버라이드하여 GATT 이벤트에 반응하세요.

handleConnection() None

GAP 연결 / 연결 해제 이벤트에서 호출됩니다. 기본 구현은 비어 있습니다.

handleNotification() None

수신되는 GATT 통지에서 호출됩니다. 기본 구현은 비어 있습니다.

상수

모듈의 constants 속성은 GAP/GATT 이벤트 식별자, 주소 타입 값, 그리고 중첩된 ad_types 네임스페이스를 담고 있는 네임스페이스입니다.

ubluepy.constants: type

아래 상수들을 노출하는 컨테이너입니다.

constants.EVT_GAP_CONNECTED: int

GAP 연결에 대한 Peripheral 연결 핸들러 event_id 값(16).

constants.EVT_GAP_DISCONNECTED: int

GAP 연결 해제에 대한 Peripheral 연결 핸들러 event_id 값(17).

constants.EVT_GATTS_WRITE: int

로컬 GATT 속성에 대한 쓰기(통지를 활성화/비활성화하는 CCCD에 대한 쓰기 포함)에 대한 Peripheral 연결 핸들러 event_id 값(80).

constants.UUID_CCCD: int

Client Characteristic Configuration Descriptor에 대한 표준 Bluetooth UUID(0x2902).

constants.ADDR_TYPE_PUBLIC: int

공개 Bluetooth 장치 주소(0).

constants.ADDR_TYPE_RANDOM_STATIC: int

정적 랜덤 Bluetooth 장치 주소(1).

constants.ad_types: type

Bluetooth Core Specification Supplement의 광고 데이터 AD 타입 상수의 네임스페이스입니다. 각 이름은 해당하는 1바이트 AD 타입에 매핑됩니다:

이름

AD_TYPE_FLAGS

0x01

AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE

0x02

AD_TYPE_16BIT_SERVICE_UUID_COMPLETE

0x03

AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE

0x04

AD_TYPE_32BIT_SERVICE_UUID_COMPLETE

0x05

AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE

0x06

AD_TYPE_128BIT_SERVICE_UUID_COMPLETE

0x07

AD_TYPE_SHORT_LOCAL_NAME

0x08

AD_TYPE_COMPLETE_LOCAL_NAME

0x09

AD_TYPE_TX_POWER_LEVEL

0x0A

AD_TYPE_CLASS_OF_DEVICE

0x0D

AD_TYPE_SIMPLE_PAIRING_HASH_C

0x0E

AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R

0x0F

AD_TYPE_SECURITY_MANAGER_TK_VALUE

0x10

AD_TYPE_SECURITY_MANAGER_OOB_FLAGS

0x11

AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE

0x12

AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT

0x14

AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT

0x15

AD_TYPE_SERVICE_DATA

0x16

AD_TYPE_PUBLIC_TARGET_ADDRESS

0x17

AD_TYPE_RANDOM_TARGET_ADDRESS

0x18

AD_TYPE_APPEARANCE

0x19

AD_TYPE_ADVERTISING_INTERVAL

0x1A

AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS

0x1B

AD_TYPE_LE_ROLE

0x1C

AD_TYPE_SIMPLE_PAIRING_HASH_C256

0x1D

AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256

0x1E

AD_TYPE_SERVICE_DATA_32BIT_UUID

0x20

AD_TYPE_SERVICE_DATA_128BIT_UUID

0x21

AD_TYPE_URI

0x24

AD_TYPE_3D_INFORMATION_DATA

0x3D

AD_TYPE_MANUFACTURER_SPECIFIC_DATA

0xFF