ubluepy — urządzenie peryferyjne i centralne Bluetooth LE

Moduł ubluepy to starsze API Bluetooth LE dostarczane z portem nRF MicroPython. Jest luźno wzorowany na linuksowej bibliotece Python bluepy i działa bezpośrednio na bazie Nordic SoftDevice — nie ma przenośnego back-endu, więc moduł jest dostępny wyłącznie na docelowych platformach Nordic (Arduino Nano 33 BLE Sense w ofercie OpenMV). Nowsze API bluetooth / aioble nie są włączone w tej kompilacji, więc ubluepy jest jedynym sposobem obsługi wbudowanego radia.

Dostępny zestaw funkcji zależy od SoftDevice zaprogramowanego przez oprogramowanie układowe:

  • s140 (Nano 33 BLE Sense) — zarówno rola urządzenia peryferyjnego, jak i centralnego (skanera). To właśnie jest dostarczane w oprogramowaniu układowym OpenMV.

  • s132 — zarówno urządzenie peryferyjne, jak i centralne.

  • s110 — tylko urządzenie peryferyjne; metody skanera / łączenia są wykluczone z kompilacji.

Przykład urządzenia peryferyjnego

Rozgłasza się jako urządzenie peryferyjne Bluetooth LE z pojedynczą usługą monitorowania środowiska i powiadamia o charakterystyce temperatury przy każdym zapisie do jego 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])

Przykład urządzenia centralnego

Skanuje w poszukiwaniu pobliskich rozgłaszających się urządzeń przez 100 ms i dekoduje dane rozgłoszeniowe każdego 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))

Zawartość modułu

Klasy

class ubluepy.UUID(value)

Konstruuje 16- lub 128-bitowy identyfikator Bluetooth UUID.

value

Jedno z:

  • int — 16-bitowy numeryczny UUID (UUID(0x180A)).

  • 6-znakowy ciąg "0xXXXX" — 16-bitowy UUID, np. UUID("0x181A").

  • 36-znakowy ciąg "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" — pełny 128-bitowy UUID. Część charakterystyczna dla dostawcy jest rejestrowana w SoftDevice podczas konstruowania.

  • Inna instancja UUID — wykonuje kopię.

Każda inna długość wywołuje ValueError("Invalid UUID string length").

binVal() int

Zwraca niskie 16 bitów UUID jako int. W przypadku 128-bitowych UUID zwracane jest tylko 16-bitowe pole osadzone wewnątrz charakterystycznego dla dostawcy UUID (pełna 128-bitowa wartość jest dostępna wyłącznie przez indeks dostawcy w SoftDevice).

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

Definiuje usługę GATT, która zostanie zarejestrowana w SoftDevice po dodaniu do Peripheral.

uuid

Instancja UUID. Przekazanie obiektu niebędącego UUID wywołuje ValueError.

type

Albo Service.PRIMARY (domyślnie), albo Service.SECONDARY. Inne wartości wywołują ValueError.

uuid() UUID

Zwraca instancję UUID usługi.

addCharacteristic(characteristic: Characteristic) None

Rejestruje Characteristic w usłudze. Uchwyt GATT charakterystyki jest przypisywany podczas tego wywołania.

getCharacteristic(uuid: UUID) Characteristic | None

Wyszukuje wcześniej dodaną Characteristic po UUID. Zwraca instancję charakterystyki lub None, jeśli nie znaleziono dopasowania.

getCharacteristics() list

Zwraca listę wszystkich charakterystyk dodanych do usługi.

PRIMARY: int

Stała typu usługi dla usług podstawowych (1).

SECONDARY: int

Stała typu usługi dla usług wtórnych (2).

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

Definiuje charakterystykę GATT. Dodaj ją do Service za pomocą Service.addCharacteristic(), zanim nadrzędne Peripheral rozpocznie rozgłaszanie.

uuid

Instancja UUID.

props (tylko jako argument nazwany)

Maska bitowa jednej lub więcej wartości Characteristic.PROP_* opisująca, jakie operacje obsługuje charakterystyka.

attrs (tylko jako argument nazwany)

Maska bitowa dodatkowych atrybutów GATT. Użyj Characteristic.ATTR_CCCD, aby dołączyć Client Characteristic Configuration Descriptor — wymagany, aby charakterystyki PROP_NOTIFY / PROP_INDICATE działały.

uuid() UUID

Zwraca instancję UUID charakterystyki.

properties() int

Zwraca maskę bitową props ustawioną w czasie konstruowania.

read() bytearray

Tylko rola centralna. Odczytuje wartość charakterystyki od połączonego peera. Zwraca bytearray z najnowszą wartością. Na urządzeniu peryferyjnym jest to operacja pusta i zwraca None.

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

Zapisuje do charakterystyki.

  • Na urządzeniu peryferyjnym, jeśli we właściwościach charakterystyki ustawiono PROP_NOTIFY, wartość jest wysyłana jako powiadomienie GATT do połączonego urządzenia centralnego; w przeciwnym razie aktualizowana jest lokalna wartość atrybutu.

  • Na urządzeniu centralnym wartość jest zapisywana na zdalnym peerze. Ustaw with_response=True, aby wysłać żądanie zapisu i czekać na potwierdzenie peera zamiast polecenia zapisu.

data to dowolny obiekt protokołu bufora (bytes, bytearray, memoryview).

PROP_BROADCAST: int

Charakterystyka może rozgłaszać swoją wartość (0x01).

PROP_READ: int

Charakterystyka obsługuje odczyty (0x02).

PROP_WRITE_WO_RESP: int

Charakterystyka obsługuje zapisy bez odpowiedzi (0x04).

PROP_WRITE: int

Charakterystyka obsługuje zapisy z odpowiedzią (0x08).

PROP_NOTIFY: int

Charakterystyka może wysyłać powiadomienia do subskrybującego urządzenia centralnego (0x10).

PROP_INDICATE: int

Charakterystyka może wysyłać wskazania (potwierdzane powiadomienia) do subskrybującego urządzenia centralnego (0x20).

PROP_AUTH_SIGNED_WR: int

Charakterystyka obsługuje uwierzytelnione podpisane zapisy (0x40).

ATTR_CCCD: int

Dodaje Client Characteristic Configuration Descriptor do charakterystyki (0x01). Wymagany, aby klienci mogli subskrybować powiadomienia/wskazania.

class ubluepy.Descriptor(uuid: UUID)

Klasa-zaślepka reprezentująca deskryptory GATT. Bieżąca implementacja przechowuje jedynie UUID i nie udostępnia żadnych metod — jest dostarczana w celu zachowania zgodności z przyszłymi wersjami modułu.

class ubluepy.Peripheral

Lokalne urządzenie Bluetooth LE. Ta sama klasa jest używana zarówno dla roli urządzenia peryferyjnego, jak i centralnego; rolę wybiera się przez to, które metody się wywołuje (advertise() wybiera urządzenie peryferyjne, connect() wybiera urządzenie centralne).

addService(service: Service) None

Rejestruje Service (i wszystkie jego wcześniej dodane charakterystyki) na lokalnym serwerze GATT.

getServices() list

Zwraca listę usług aktualnie zarejestrowanych w tym Peripheral.

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

Rozpoczyna rozgłaszanie w roli urządzenia peryferyjnego.

device_name

Pełna lokalna nazwa rozgłaszana w ładunku GAP.

services

Lista instancji Service do rozgłaszania. UUID każdej usługi jest dołączany do rozgłoszenia.

data

Opcjonalny surowy ładunek rozgłoszeniowy (bytes / bytearray) dołączany do automatycznie generowanego nagłówka. Użyj go dla ładunków charakterystycznych dla dostawcy lub ładunków beacon, takich jak Eddystone.

connectable

Gdy True (domyślnie), rozgłasza się jako urządzenie umożliwiające połączenie i rejestruje obsługę zdarzeń GAP / GATTS, tak aby skonfigurowane wywołanie zwrotne setConnectionHandler() uruchamiało się przy połączeniu, rozłączeniu i zapisach CCCD. Gdy False, rozgłasza się jako beacon — żadna obsługa nie jest dołączana i nie można się połączyć z urządzeniem.

advertise_stop() None

Zatrzymuje wszelkie trwające rozgłaszanie.

setConnectionHandler(func) None

Rejestruje wywołanie zwrotne uruchamiane przy zdarzeniach GAP i GATTS. Wywołanie zwrotne jest wywoływane jako func(event_id, conn_handle, data), gdzie event_id jest jedną z wartości constants.EVT_GAP_CONNECTED, constants.EVT_GAP_DISCONNECTED lub constants.EVT_GATTS_WRITE, conn_handle jest uchwytem połączenia SoftDevice (lub uchwytem atrybutu dla zapisów GATTS), a data jest surowym ładunkiem zdarzenia jako bytearray (lub None dla połączenia / rozłączenia).

setNotificationHandler(func) None

Rejestruje wywołanie zwrotne dla zdarzeń powiadomień odbieranych w roli centralnej.

withDelegate(delegate: DefaultDelegate) None

Dołącza instancję DefaultDelegate do odbierania zdekodowanych zdarzeń GATT.

disconnect() None

Zrywa aktywne połączenie (obecnie pusta zaślepka w tej kompilacji).

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

Tylko rola centralna. Łączy się z peerem o podanym adresie i synchronicznie wykrywa jego usługi podstawowe i charakterystyki. Blokuje, dopóki połączenie nie zostanie nawiązane i wykrywanie nie zostanie ukończone; wykryte usługi są następnie dostępne przez getServices().

addr

Adres peera jako 17-znakowy ciąg "xx:xx:xx:xx:xx:xx" (np. pobrany z ScanEntry.addr()).

addr_type (tylko jako argument nazwany)

Albo constants.ADDR_TYPE_PUBLIC (domyślnie), albo constants.ADDR_TYPE_RANDOM_STATIC.

class ubluepy.Scanner

Obserwator GAP do wykrywania pobliskich rozgłaszających się urządzeń. Dostępny tylko wtedy, gdy oprogramowanie układowe jest skompilowane z SoftDevice obsługującym rolę centralną (s132 / s140).

scan(timeout: int) list

Uruchamia pasywne skanowanie przez timeout milisekund i zwraca listę instancji ScanEntry — po jednej na każdy raport rozgłoszeniowy odebrany w danym oknie.

class ubluepy.ScanEntry

Pojedynczy raport rozgłoszeniowy przechwycony przez Scanner.scan(). Instancje są zwracane przez skaner — nie istnieje publiczny konstruktor.

addr() str

Zwraca adres peera jako 17-znakowy ciąg "xx:xx:xx:xx:xx:xx".

addr_type() int

Zwraca typ adresu peera (constants.ADDR_TYPE_PUBLIC lub constants.ADDR_TYPE_RANDOM_STATIC).

rssi() int

Zwraca wskaźnik siły sygnału w dBm.

getScanData() list

Dekoduje ładunek rozgłoszeniowy na listę krotek (ad_type, description, value). ad_type to numeryczny bajt typu AD (zobacz constants.ad_types), description to nazwa pasującej stałej jako ciąg znaków (lub None, jeśli typ jest nieznany), a value to treść rekordu AD jako bytearray.

class ubluepy.DefaultDelegate

Klasa bazowa dla obiektów przekazywanych do Peripheral.withDelegate(). Utwórz jej podklasę i nadpisz handleConnection() / handleNotification(), aby reagować na zdarzenia GATT.

handleConnection() None

Wywoływana przy zdarzeniach połączenia / rozłączenia GAP. Domyślna implementacja jest pusta.

handleNotification() None

Wywoływana przy przychodzących powiadomieniach GATT. Domyślna implementacja jest pusta.

Stałe

Atrybut constants modułu to przestrzeń nazw zawierająca identyfikatory zdarzeń GAP/GATT, wartości typów adresów oraz zagnieżdżoną przestrzeń nazw ad_types.

ubluepy.constants: type

Kontener udostępniający poniższe stałe.

constants.EVT_GAP_CONNECTED: int

Wartość event_id obsługi połączeń Peripheral dla połączenia GAP (16).

constants.EVT_GAP_DISCONNECTED: int

Wartość event_id obsługi połączeń Peripheral dla rozłączenia GAP (17).

constants.EVT_GATTS_WRITE: int

Wartość event_id obsługi połączeń Peripheral dla zapisu do lokalnego atrybutu GATT, w tym zapisów do CCCD włączających/wyłączających powiadomienia (80).

constants.UUID_CCCD: int

Standardowy UUID Bluetooth dla Client Characteristic Configuration Descriptor (0x2902).

constants.ADDR_TYPE_PUBLIC: int

Publiczny adres urządzenia Bluetooth (0).

constants.ADDR_TYPE_RANDOM_STATIC: int

Statyczny losowy adres urządzenia Bluetooth (1).

constants.ad_types: type

Przestrzeń nazw stałych typów AD danych rozgłoszeniowych z Bluetooth Core Specification Supplement. Każda nazwa odpowiada odpowiedniemu 1-bajtowemu typowi AD:

Nazwa

Wartość

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