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