bluetooth — Bluetooth de nivel jos

Acest modul oferă o interfață către controlerul Bluetooth integrat. Acceptă Bluetooth Low Energy (BLE) în rolurile Central, Peripheral, Broadcaster și Observer, precum și GATT Server și Client și canale L2CAP orientate pe conexiune. Un dispozitiv poate funcționa simultan în mai multe roluri. Sunt acceptate de asemenea împerecherea (pairing) și legarea (bonding).

Acest API este conceput pentru a corespunde protocolului Bluetooth de nivel jos și pentru a oferi blocuri de construcție pentru abstractizări de nivel superior, cum ar fi tipuri specifice de dispozitive.

Sfat

Pentru majoritatea aplicațiilor, preferați biblioteca de nivel superior aioble, care oferă un wrapper bazat pe asyncio în jurul acestui modul. Vedeți aioble — BLE asincron.

class BLE

class bluetooth.BLE

Returnează obiectul singleton BLE.

Configurare

active(active: bool | None = None, /) bool

Schimbă opțional starea activă a radioului BLE și returnează starea curentă.

Radioul trebuie făcut activ înainte de a utiliza orice altă metodă din această clasă.

config(param: str, /) Any
config(*, **kwargs: Any) None

Obține sau setează valorile de configurare ale interfeței BLE. Pentru a obține o valoare, numele parametrului trebuie indicat ca șir între ghilimele și se interoghează un singur parametru o dată. Pentru a seta valori, folosiți sintaxa de cuvinte-cheie, putând fi setați unul sau mai mulți parametri o dată.

Valorile acceptate în prezent sunt:

  • 'mac': Adresa utilizată în prezent, în funcție de modul de adresă curent. Aceasta returnează un tuplu de forma (addr_type, addr).

    Vedeți gap_scan pentru detalii despre tipul de adresă.

    Aceasta poate fi interogată doar cât timp interfața este activă.

  • 'addr_mode': Setează modul de adresă. Valorile sunt:

    Valoare

    Nume

    Comportament

    0x00

    PUBLIC

    Folosește adresa publică a controlerului.

    0x01

    RANDOM

    Folosește o adresă statică generată.

    0x02

    RPA

    Folosește adrese private rezolvabile.

    0x03

    NRPA

    Folosește adrese private nerezolvabile.

    În mod implicit, interfața va folosi o adresă PUBLIC dacă este disponibilă, în caz contrar va folosi o adresă RANDOM.

  • 'gap_name': Obține/setează numele dispozitivului GAP utilizat de serviciul Generic Access (UUID 0x1800), caracteristica Device Name (UUID 0x2a00). Acesta poate fi setat oricând și schimbat de mai multe ori.

  • 'rxbuf': Obține/setează dimensiunea în octeți a tamponului (buffer) intern utilizat pentru stocarea evenimentelor primite. Acest tampon este global pentru întregul driver BLE și deci gestionează datele primite pentru toate evenimentele, inclusiv toate caracteristicile. Mărirea acestuia permite o gestionare mai bună a datelor primite în rafale (de exemplu rezultatele scanării) și posibilitatea de a primi valori mai mari ale caracteristicilor.

  • 'mtu': Obține/setează MTU-ul care va fi utilizat în timpul unui schimb de MTU ATT. MTU-ul rezultat va fi minimul dintre acesta și MTU-ul dispozitivului la distanță. Schimbul de MTU ATT nu se va realiza automat (cu excepția cazului în care dispozitivul la distanță îl inițiază) și trebuie inițiat manual cu gattc_exchange_mtu. Folosiți evenimentul _IRQ_MTU_EXCHANGED pentru a afla MTU-ul pentru o anumită conexiune.

  • 'bond': Setează dacă legarea (bonding) va fi activată în timpul împerecherii. Când este activată, cererile de împerechere vor seta indicatorul „bond”, iar cheile vor fi stocate de ambele dispozitive.

  • 'mitm': Setează dacă protecția MITM este necesară pentru împerechere.

  • 'io': Setează capacitățile de I/O ale acestui dispozitiv.

    Opțiunile disponibile sunt:

    Constantă

    Valoare

    Capacitate

    _IO_CAPABILITY_DISPLAY_ONLY

    0

    Doar afișaj

    _IO_CAPABILITY_DISPLAY_YESNO

    1

    Afișaj cu intrare da/nu

    _IO_CAPABILITY_KEYBOARD_ONLY

    2

    Doar tastatură

    _IO_CAPABILITY_NO_INPUT_OUTPUT

    3

    Fără intrare sau ieșire

    _IO_CAPABILITY_KEYBOARD_DISPLAY

    4

    Tastatură și afișaj

  • 'le_secure': Setează dacă împerecherea „LE Secure” este necesară. Valoarea implicită este false (adică se permite „Legacy Pairing”).

Gestionarea evenimentelor

irq(handler: Callable[[int, Tuple], Any | None], /) None

Înregistrează o funcție de retroapelare (callback) pentru evenimentele de la stiva BLE. handler-ul primește două argumente, event (care va fi unul dintre codurile de mai jos) și data (care este un tuplu de valori specific evenimentului).

Notă: Ca optimizare pentru a preveni alocările inutile, intrările addr, adv_data, char_data, notify_data și uuid din tupluri sunt instanțe memoryview doar-citire care indică spre ringbuffer-ul intern al bluetooth și sunt valide doar pe durata apelării funcției handler de IRQ. Dacă programul dumneavoastră trebuie să salveze una dintre aceste valori pentru a o accesa după ce handler-ul de IRQ a revenit (de exemplu salvând-o într-o instanță de clasă sau o variabilă globală), atunci trebuie să facă o copie a datelor, fie folosind bytes(), fie bluetooth.UUID(), astfel:

connected_addr = bytes(addr)  # equivalently: adv_data, char_data, or notify_data
matched_uuid = bluetooth.UUID(uuid)

De exemplu, handler-ul de IRQ pentru un rezultat de scanare ar putea inspecta adv_data pentru a decide dacă este dispozitivul corect și abia apoi să copieze datele de adresă pentru a fi folosite în altă parte a programului. Iar pentru a afișa date din interiorul handler-ului de IRQ, va fi nevoie de print(bytes(addr)).

Un handler distribuie de obicei în funcție de codul evenimentului și despachetează tuplul de date specific evenimentului:

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
        ...

Fiecare cod de eveniment, datele pe care le livrează și o scurtă descriere sunt enumerate mai jos. Pentru evenimentele al căror câmp status este menționat, status este 0 la succes și o valoare diferită de zero, specifică implementării, la eșec.

Constantă

Valoare

Eveniment

Tuplu de date

_IRQ_CENTRAL_CONNECT

1

Un dispozitiv central s-a conectat la acest periferic.

(conn_handle, addr_type, addr)

_IRQ_CENTRAL_DISCONNECT

2

Un dispozitiv central s-a deconectat de la acest periferic.

(conn_handle, addr_type, addr)

_IRQ_GATTS_WRITE

3

Un client conectat a scris într-o caracteristică sau un descriptor local. Folosiți gatts_read pentru a prelua noua valoare.

(conn_handle, attr_handle)

_IRQ_GATTS_READ_REQUEST

4

Un client conectat a emis o citire. Returnați un cod de eroare diferit de zero din tabelul de mai jos pentru a refuza citirea, sau 0 / None pentru a o accepta.

(conn_handle, attr_handle)

_IRQ_SCAN_RESULT

5

A fost primit un singur pachet de advertising în timpul unei scanări active.

(addr_type, addr, adv_type, rssi, adv_data)

_IRQ_SCAN_DONE

6

Scanarea curentă s-a încheiat, fie pentru că durata configurată s-a scurs, fie pentru că a fost apelat gap_scan(None).

()

_IRQ_PERIPHERAL_CONNECT

7

Un gap_connect emis anterior a reușit.

(conn_handle, addr_type, addr)

_IRQ_PERIPHERAL_DISCONNECT

8

Un periferic conectat s-a deconectat.

(conn_handle, addr_type, addr)

_IRQ_GATTC_SERVICE_RESULT

9

A fost găsit un serviciu de către gattc_discover_services.

(conn_handle, start_handle, end_handle, uuid)

_IRQ_GATTC_SERVICE_DONE

10

Descoperirea serviciilor s-a încheiat.

(conn_handle, status)

_IRQ_GATTC_CHARACTERISTIC_RESULT

11

A fost găsită o caracteristică de către gattc_discover_characteristics.

(conn_handle, end_handle, value_handle, properties, uuid)

_IRQ_GATTC_CHARACTERISTIC_DONE

12

Descoperirea caracteristicilor s-a încheiat.

(conn_handle, status)

_IRQ_GATTC_DESCRIPTOR_RESULT

13

A fost găsit un descriptor de către gattc_discover_descriptors.

(conn_handle, dsc_handle, uuid)

_IRQ_GATTC_DESCRIPTOR_DONE

14

Descoperirea descriptorilor s-a încheiat.

(conn_handle, status)

_IRQ_GATTC_READ_RESULT

15

Un gattc_read emis anterior a returnat date.

(conn_handle, value_handle, char_data)

_IRQ_GATTC_READ_DONE

16

Un gattc_read emis anterior s-a încheiat.

(conn_handle, value_handle, status)

_IRQ_GATTC_WRITE_DONE

17

Un gattc_write emis anterior a fost confirmat.

(conn_handle, value_handle, status)

_IRQ_GATTC_NOTIFY

18

Un server la distanță a trimis o notificare (neconfirmată).

(conn_handle, value_handle, notify_data)

_IRQ_GATTC_INDICATE

19

Un server la distanță a trimis o indicație (confirmată).

(conn_handle, value_handle, notify_data)

_IRQ_GATTS_INDICATE_DONE

20

O indicație trimisă anterior a fost confirmată de client (sau a expirat).

(conn_handle, value_handle, status)

_IRQ_MTU_EXCHANGED

21

Un schimb de MTU ATT s-a finalizat (inițiat de oricare dintre părți).

(conn_handle, mtu)

_IRQ_L2CAP_ACCEPT

22

Un dispozitiv la distanță a solicitat o conexiune L2CAP pe un PSM pe care acest dispozitiv ascultă. Returnați un întreg diferit de zero pentru a respinge, sau 0 / None pentru a accepta.

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_CONNECT

23

Un canal L2CAP este acum stabilit, fie prin acceptarea unei cereri primite, fie prin finalizarea unui l2cap_connect de ieșire.

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_DISCONNECT

24

Un canal L2CAP a fost deconectat. status este 0 pentru o deconectare curată, sau diferit de zero dacă o încercare de conexiune de ieșire a eșuat.

(conn_handle, cid, psm, status)

_IRQ_L2CAP_RECV

25

Au sosit date pe un canal L2CAP. Apelați l2cap_recvinto pentru a le citi.

(conn_handle, cid)

_IRQ_L2CAP_SEND_READY

26

Un l2cap_send anterior care a returnat False s-a golit, iar canalul este din nou pregătit. Un status diferit de zero înseamnă că tamponul de transmisie a depășit capacitatea, iar aplicația trebuie să retrimită datele.

(conn_handle, cid, status)

_IRQ_CONNECTION_UPDATE

27

Dispozitivul la distanță a actualizat parametrii conexiunii (interval, latență, timeout de supraveghere).

(conn_handle, conn_interval, conn_latency, supervision_timeout, status)

_IRQ_ENCRYPTION_UPDATE

28

Starea de criptare a unei conexiuni s-a schimbat, de obicei după finalizarea împerecherii sau a legării.

(conn_handle, encrypted, authenticated, bonded, key_size)

_IRQ_GET_SECRET

29

Stiva solicită un secret de legare stocat. Dacă key este None, returnați a index-a valoare stocată de tipul sec_type; în caz contrar returnați valoarea asociată cu perechea (sec_type, key) dată. Returnați None dacă nu este stocat nimic.

(sec_type, index, key)

_IRQ_SET_SECRET

30

Stiva cere aplicației să persiste un secret de legare. Returnați True după ce a fost stocat.

(sec_type, key, value)

_IRQ_PASSKEY_ACTION

31

O acțiune de passkey este necesară ca parte a împerecherii. Răspundeți folosind gap_passkey; vedeți tabelul de acțiuni passkey de mai jos pentru posibilele acțiuni.

(conn_handle, action, passkey)

Pentru evenimentul _IRQ_GATTS_READ_REQUEST, codurile de retur disponibile sunt:

Constantă

Valoare

Semnificație

_GATTS_NO_ERROR

0x00

Acceptă citirea.

_GATTS_ERROR_READ_NOT_PERMITTED

0x02

Citirea nu este permisă.

_GATTS_ERROR_WRITE_NOT_PERMITTED

0x03

Scrierea nu este permisă.

_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION

0x05

Clientul nu este autentificat.

_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION

0x08

Clientul nu este autorizat.

_GATTS_ERROR_INSUFFICIENT_ENCRYPTION

0x0f

Legătura nu este criptată.

Pentru evenimentul _IRQ_PASSKEY_ACTION, acțiunile disponibile sunt:

Constantă

Valoare

Semnificație

_PASSKEY_ACTION_NONE

0

Nu este necesară nicio acțiune.

_PASSKEY_ACTION_INPUT

2

Solicită utilizatorului să introducă passkey-ul afișat pe dispozitivul la distanță.

_PASSKEY_ACTION_DISPLAY

3

Afișează un passkey de 6 cifre pe care dispozitivul la distanță să îl introducă.

_PASSKEY_ACTION_NUMERIC_COMPARISON

4

Confirmă că passkey-ul corespunde celui afișat pe dispozitivul la distanță.

Pentru a economisi spațiu în firmware, aceste constante nu sunt incluse în modulul bluetooth. Adăugați în programul dumneavoastră cele de care aveți nevoie din listele de mai sus.

Rolul Broadcaster (Advertiser)

gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None

Începe advertising-ul la intervalul specificat (în microsecunde). Acest interval va fi rotunjit în jos la cel mai apropiat multiplu de 625us. Pentru a opri advertising-ul, setați interval_us la None.

adv_data și resp_data pot fi orice tip care implementează protocolul buffer (de exemplu bytes, bytearray, str). adv_data este inclus în toate transmisiile, iar resp_data este trimis ca răspuns la o scanare activă.

Notă: dacă adv_data (sau resp_data) este None, atunci datele transmise la apelul anterior al gap_advertise vor fi reutilizate. Aceasta permite unui broadcaster să reia advertising-ul doar cu gap_advertise(interval_us). Pentru a șterge datele de advertising, transmiteți un bytes gol, adică b''.

Rolul Observer (Scanner)

gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None

Execută o operație de scanare care durează intervalul specificat (în milisecunde).

Pentru a scana la nesfârșit, setați duration_ms la 0.

Pentru a opri scanarea, setați duration_ms la None.

Folosiți interval_us și window_us pentru a configura opțional ciclul de funcționare (duty cycle). Scannerul va funcționa timp de window_us microsecunde la fiecare interval_us microsecunde, pentru un total de duration_ms milisecunde. Intervalul și fereastra implicite sunt 1,28 secunde și respectiv 11,25 milisecunde (scanare în fundal).

Pentru fiecare rezultat de scanare va fi generat evenimentul _IRQ_SCAN_RESULT, cu datele de eveniment (addr_type, addr, adv_type, rssi, adv_data).

Valorile addr_type indică adrese publice sau aleatorii:

Valoare

Nume

Semnificație

0x00

PUBLIC

Adresă publică de dispozitiv.

0x01

RANDOM

Adresă aleatorie (statică, RPA sau NRPA; tipul este codificat în adresa însăși).

Valorile adv_type corespund Specificației Bluetooth:

Valoare

Nume

Semnificație

0x00

ADV_IND

Advertising nedirecționat, conectabil și scanabil.

0x01

ADV_DIRECT_IND

Advertising direcționat, conectabil.

0x02

ADV_SCAN_IND

Advertising nedirecționat, scanabil.

0x03

ADV_NONCONN_IND

Advertising nedirecționat, neconectabil.

0x04

SCAN_RSP

Răspuns la scanare.

active poate fi setat la True dacă doriți să primiți răspunsuri la scanare în rezultate.

Când scanarea este oprită (fie din cauza încheierii duratei, fie când este oprită explicit), va fi generat evenimentul _IRQ_SCAN_DONE.

Rolul Central

Un dispozitiv central se poate conecta la perifericele pe care le-a descoperit folosind rolul observer (vedeți gap_scan) sau cu o adresă cunoscută.

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

Conectează-te la un periferic.

Vedeți gap_scan pentru detalii despre tipurile de adresă.

Pentru a anula din timp o încercare de conexiune în așteptare, apelați gap_connect(None).

La succes, va fi generat evenimentul _IRQ_PERIPHERAL_CONNECT. Dacă se anulează o încercare de conexiune, va fi generat evenimentul _IRQ_PERIPHERAL_DISCONNECT.

Dispozitivul va aștepta până la scan_duration_ms pentru a primi date de advertising de la dispozitiv.

Intervalul de conexiune poate fi configurat în microsecunde folosind unul sau ambii parametri min_conn_interval_us și max_conn_interval_us. Altfel, va fi ales un interval implicit, de obicei între 30000 și 50000 microsecunde. Un interval mai scurt va crește debitul, în detrimentul consumului de energie.

Rolul Peripheral

Se așteaptă ca un dispozitiv periferic să trimită date de advertising conectabile (vedeți gap_advertise). De obicei va acționa ca server GATT, după ce a înregistrat mai întâi serviciile și caracteristicile folosind gatts_register_services.

Când un dispozitiv central se conectează, va fi generat evenimentul _IRQ_CENTRAL_CONNECT.

Rolurile Central și Peripheral

gap_disconnect(conn_handle: int, /) bool

Deconectează handle-ul de conexiune specificat. Acesta poate fi fie un dispozitiv central care s-a conectat la acest dispozitiv (dacă acționează ca periferic), fie un periferic la care acest dispozitiv s-a conectat anterior (dacă acționează ca dispozitiv central).

La succes, va fi generat evenimentul _IRQ_PERIPHERAL_DISCONNECT sau _IRQ_CENTRAL_DISCONNECT.

Returnează False dacă handle-ul de conexiune nu era conectat și True în caz contrar.

GATT Server

Un server GATT are un set de servicii înregistrate. Fiecare serviciu poate conține caracteristici, fiecare având o valoare. Caracteristicile pot conține de asemenea descriptori, care la rândul lor au valori.

Aceste valori sunt stocate local și sunt accesate prin „value handle”-ul lor, care este generat în timpul înregistrării serviciului. Ele pot fi de asemenea citite sau scrise de un dispozitiv client la distanță. În plus, un server poate „notifica” o caracteristică unui client conectat printr-un handle de conexiune.

Un dispozitiv în rolurile central sau periferic poate funcționa ca server GATT, însă în majoritatea cazurilor va fi mai obișnuit ca un dispozitiv periferic să acționeze ca server.

Caracteristicile și descriptorii au o dimensiune maximă implicită de 20 de octeți (MTU-ul ATT implicit de 23 de octeți minus un antet ATT de 3 octeți; un MTU negociat mai mare nu ridică prin sine însuși această limită). Orice este scris în ele de un client va fi trunchiat la această lungime. Totuși, orice scriere locală va crește dimensiunea maximă, deci dacă doriți să permiteți scrieri mai mari de la un client către o anumită caracteristică, folosiți gatts_write după înregistrare. de ex. gatts_write(char_handle, bytes(100)).

gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]

Configurează serverul cu serviciile specificate, înlocuind orice servicii existente.

services_definition este o listă de servicii, unde fiecare serviciu este un tuplu cu două elemente conținând un UUID și o listă de caracteristici.

Fiecare caracteristică este un tuplu cu două sau trei elemente conținând un UUID, o valoare de flag-uri și, opțional, o listă de descriptori.

Fiecare descriptor este un tuplu cu două elemente conținând un UUID și o valoare de flag-uri.

Flag-urile sunt o combinație OR pe biți a flag-urilor definite mai jos. Acestea setează atât comportamentul caracteristicii (sau descriptorului), cât și cerințele de securitate și confidențialitate.

Valoarea de retur este o listă (un element per serviciu) de tupluri (fiecare element este un value handle). Handle-urile de caracteristici și descriptori sunt aplatizate în același tuplu, în ordinea în care sunt definite.

Exemplul următor înregistrează două servicii (Heart Rate și 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),
)

Cele trei value handle-uri (hr, tx, rx) pot fi utilizate cu gatts_read, gatts_write, gatts_notify și gatts_indicate.

Notă: Advertising-ul trebuie oprit înainte de înregistrarea serviciilor.

Flag-urile disponibile pentru caracteristici și descriptori sunt:

Constantă

Valoare

Semnificație

_FLAG_BROADCAST

0x0001

Caracteristica poate fi difuzată (broadcast).

_FLAG_READ

0x0002

Clientul poate citi valoarea.

_FLAG_WRITE_NO_RESPONSE

0x0004

Clientul poate scrie fără a aștepta un răspuns.

_FLAG_WRITE

0x0008

Clientul poate scrie cu un răspuns confirmat.

_FLAG_NOTIFY

0x0010

Serverul poate trimite notificări (neconfirmate).

_FLAG_INDICATE

0x0020

Serverul poate trimite indicații (confirmate).

_FLAG_AUTHENTICATED_SIGNED_WRITE

0x0040

Clientul poate emite scrieri semnate.

_FLAG_AUX_WRITE

0x0100

Proprietăți extinse: scrierile puse în coadă/fiabile sunt permise.

_FLAG_READ_ENCRYPTED

0x0200

Citirea necesită o legătură criptată.

_FLAG_READ_AUTHENTICATED

0x0400

Citirea necesită o legătură autentificată (protejată MITM).

_FLAG_READ_AUTHORIZED

0x0800

Citirea necesită autorizare la nivel de aplicație.

_FLAG_WRITE_ENCRYPTED

0x1000

Scrierea necesită o legătură criptată.

_FLAG_WRITE_AUTHENTICATED

0x2000

Scrierea necesită o legătură autentificată (protejată MITM).

_FLAG_WRITE_AUTHORIZED

0x4000

Scrierea necesită autorizare la nivel de aplicație.

La fel ca în cazul constantelor de evenimente de mai sus, aceste flag-uri nu sunt furnizate de modulul bluetooth; copiați în programul dumneavoastră cele de care aveți nevoie.

gatts_read(value_handle: int, /) bytes

Citește valoarea locală pentru acest handle (care a fost fie scrisă de gatts_write, fie de un client la distanță).

gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None

Scrie valoarea locală pentru acest handle, care poate fi citită de un client.

Dacă send_update este True, atunci toți clienții abonați vor fi notificați (sau li se va indica, în funcție de ceea ce au abonat și de operațiile pe care le acceptă caracteristica) despre această scriere.

gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

Trimite o cerere de notificare către un client conectat.

Dacă data este None (valoarea implicită), atunci va fi trimisă valoarea locală curentă (cea setată cu gatts_write).

În caz contrar, dacă data nu este None, atunci acea valoare este trimisă clientului ca parte a notificării. Valoarea locală nu va fi modificată.

Notă: Notificarea va fi trimisă indiferent de starea de abonare a clientului la această caracteristică.

gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

Trimite o cerere de indicație către un client conectat.

Dacă data este None (valoarea implicită), atunci va fi trimisă valoarea locală curentă (cea setată cu gatts_write).

În caz contrar, dacă data nu este None, atunci acea valoare este trimisă clientului ca parte a indicației. Valoarea locală nu va fi modificată.

La confirmare (sau eșec, de ex. timeout), va fi generat evenimentul _IRQ_GATTS_INDICATE_DONE.

Notă: Indicația va fi trimisă indiferent de starea de abonare a clientului la această caracteristică.

gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None

Setează dimensiunea tamponului (buffer) intern pentru o valoare, în octeți. Aceasta va limita cea mai mare scriere posibilă care poate fi primită. Valoarea implicită este 20 de octeți (MTU-ul ATT implicit de 23 minus antetul ATT de 3 octeți).

Setarea append la True va face ca toate scrierile de la distanță să adauge la valoarea curentă, în loc să o înlocuiască. Cel mult len octeți pot fi tamponați în acest fel. Când folosiți gatts_read, valoarea va fi ștearsă după citire. Această funcție este utilă la implementarea unor lucruri precum Nordic UART Service.

GATT Client

Un client GATT poate descoperi și citi/scrie caracteristici pe un server GATT la distanță.

Este mai obișnuit ca un dispozitiv cu rol central să acționeze ca client GATT, însă este de asemenea posibil ca un periferic să acționeze ca client pentru a descoperi informații despre dispozitivul central care s-a conectat la el (de ex. pentru a citi numele dispozitivului din serviciul de informații al dispozitivului).

gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None

Interoghează un server conectat pentru serviciile sale.

Specificați opțional un uuid de serviciu pentru a interoga doar acel serviciu.

Pentru fiecare serviciu descoperit, va fi generat evenimentul _IRQ_GATTC_SERVICE_RESULT, urmat de _IRQ_GATTC_SERVICE_DONE la finalizare.

gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None

Interoghează un server conectat pentru caracteristicile din intervalul specificat.

Specificați opțional un uuid de caracteristică pentru a interoga doar acea caracteristică.

Transmiterea start_handle=1 și end_handle=0xffff acoperă întreg intervalul de handle-uri de atribute GATT, deci această combinație caută efectiv fiecare serviciu de pe dispozitivul la distanță.

Pentru fiecare caracteristică descoperită, va fi generat evenimentul _IRQ_GATTC_CHARACTERISTIC_RESULT, urmat de _IRQ_GATTC_CHARACTERISTIC_DONE la finalizare.

gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None

Interoghează un server conectat pentru descriptorii din intervalul specificat.

Pentru fiecare descriptor descoperit, va fi generat evenimentul _IRQ_GATTC_DESCRIPTOR_RESULT, urmat de _IRQ_GATTC_DESCRIPTOR_DONE la finalizare.

gattc_read(conn_handle: int, value_handle: int, /) None

Emite o citire la distanță către un server conectat pentru handle-ul de caracteristică sau descriptor specificat.

Când o valoare este disponibilă, va fi generat evenimentul _IRQ_GATTC_READ_RESULT, urmat de _IRQ_GATTC_READ_DONE la finalizare.

gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None

Emite o scriere la distanță către un server conectat pentru handle-ul de caracteristică sau descriptor specificat.

Argumentul mode specifică comportamentul scrierii, valorile acceptate în prezent fiind:

  • mode=0 (implicit) este o scriere fără răspuns: scrierea va fi trimisă serverului la distanță, dar nu va fi returnată nicio confirmare și nu va fi generat niciun eveniment.

  • mode=1 este o scriere cu răspuns: serverului la distanță i se solicită să trimită un răspuns/o confirmare că a primit datele.

Dacă se primește un răspuns de la serverul la distanță, va fi generat evenimentul _IRQ_GATTC_WRITE_DONE.

gattc_exchange_mtu(conn_handle: int, /) None

Inițiază schimbul de MTU cu un server conectat, folosind MTU-ul preferat setat cu BLE.config(mtu=value).

Evenimentul _IRQ_MTU_EXCHANGED va fi generat când schimbul de MTU se finalizează.

Schimbul de MTU este de obicei inițiat de dispozitivul central; NimBLE acceptă ambele roluri.

Canale L2CAP orientate pe conexiune

Această funcție permite schimbul de date în stil socket între două dispozitive BLE. Odată ce dispozitivele sunt conectate prin GAP, oricare dintre ele poate aștepta ca celălalt să se conecteze pe un PSM numeric (Protocol/Service Multiplexer).

Doar un singur canal L2CAP poate fi activ la un moment dat (adică nu vă puteți conecta în timp ce ascultați).

Canalele L2CAP active sunt identificate prin handle-ul de conexiune pe care au fost stabilite și printr-un CID (channel ID).

Canalele orientate pe conexiune au control de flux integrat bazat pe credite. Spre deosebire de ATT, unde dispozitivele negociază un MTU comun, atât dispozitivul care ascultă, cât și cel care se conectează setează fiecare un MTU independent, care limitează cantitatea maximă de date în așteptare pe care dispozitivul la distanță o poate trimite înainte de a fi complet consumată în l2cap_recvinto.

l2cap_listen(psm: int, mtu: int, /) None

Începe să asculte cereri primite de canal L2CAP pe psm-ul specificat, cu MTU-ul local setat la mtu.

Când un dispozitiv la distanță inițiază o conexiune, va fi generat evenimentul _IRQ_L2CAP_ACCEPT, care îi oferă serverului care ascultă șansa de a respinge conexiunea primită (returnând un întreg diferit de zero).

Odată ce conexiunea este acceptată, va fi generat evenimentul _IRQ_L2CAP_CONNECT, permițând serverului să obțină channel ID-ul (CID) și MTU-ul local și cel la distanță.

Notă: În prezent nu este posibilă oprirea ascultării.

l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None

Conectează-te la un partener care ascultă pe psm-ul specificat, cu MTU-ul local setat la mtu.

La conectarea cu succes, va fi generat evenimentul _IRQ_L2CAP_CONNECT, permițând clientului să obțină CID-ul și MTU-ul local și cel la distanță (peer).

O conexiune nereușită va genera evenimentul _IRQ_L2CAP_DISCONNECT cu un status diferit de zero.

l2cap_disconnect(conn_handle: int, cid: int, /) None

Deconectează un canal L2CAP activ cu conn_handle-ul și cid-ul specificate.

l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool

Trimite buf-ul specificat (care trebuie să accepte protocolul buffer) pe canalul L2CAP identificat prin conn_handle și cid.

Tamponul trebuie să respecte ambele limite: nu trebuie să depășească MTU-ul la distanță (peer) și nu trebuie să depășească dublul MTU-ului local.

Aceasta va returna False dacă canalul este acum „blocat” (stalled), ceea ce înseamnă că l2cap_send nu trebuie apelat din nou până când nu este primit evenimentul _IRQ_L2CAP_SEND_READY (ceea ce se va întâmpla când dispozitivul la distanță acordă mai multe credite, de obicei după ce a primit și procesat datele).

l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int

Primește date de la conn_handle-ul și cid-ul specificate în buf-ul furnizat (care trebuie să accepte protocolul buffer, de ex. bytearray sau memoryview).

Returnează numărul de octeți citiți de pe canal.

Dacă buf este None, atunci returnează numărul de octeți disponibili.

Notă: După primirea evenimentului _IRQ_L2CAP_RECV, aplicația ar trebui să continue să apeleze l2cap_recvinto până când nu mai sunt octeți disponibili în tamponul de recepție (de obicei până la dimensiunea MTU-ului la distanță (peer)).

Până când tamponul de recepție nu este golit, dispozitivului la distanță nu i se vor acorda mai multe credite de canal și nu va putea trimite mai multe date.

Împerechere și legare (Pairing and Bonding)

Împerecherea permite ca o conexiune să fie criptată și autentificată prin schimbul de secrete (cu protecție MITM opțională prin autentificare cu passkey).

Legarea (bonding) este procesul de stocare a acestor secrete într-o memorie nevolatilă. Când este legat, un dispozitiv poate rezolva o adresă privată rezolvabilă (RPA) de la un alt dispozitiv pe baza cheii de rezolvare a identității (IRK) stocate. Pentru a accepta legarea, o aplicație trebuie să implementeze evenimentele _IRQ_GET_SECRET și _IRQ_SET_SECRET.

gap_pair(conn_handle: int, /) None

Inițiază împerecherea cu dispozitivul la distanță.

Înainte de a apela aceasta, asigurați-vă că opțiunile de configurare io, mitm, le_secure și bond sunt setate (prin config).

La împerecherea reușită, va fi generat evenimentul _IRQ_ENCRYPTION_UPDATE.

gap_passkey(conn_handle: int, action: int, passkey: int, /) None

Răspunde la un eveniment _IRQ_PASSKEY_ACTION pentru conn_handle-ul și action-ul specificate. Semnificația lui passkey depinde de action (care la rândul său depinde de capacitatea de I/O configurată):

Acțiune

Răspunsul passkey necesar

_PASSKEY_ACTION_INPUT

Passkey-ul pe care utilizatorul îl citește de pe dispozitivul la distanță.

_PASSKEY_ACTION_DISPLAY

Un passkey aleatoriu de 6 cifre generat local și afișat utilizatorului.

_PASSKEY_ACTION_NUMERIC_COMPARISON

1 pentru a accepta passkey-ul afișat în evenimentul _IRQ_PASSKEY_ACTION, sau 0 pentru a anula împerecherea.

class UUID

class bluetooth.UUID(value: int | bytes | str, /)

Creează o instanță UUID cu value-ul specificat. Bluetooth folosește trei lățimi de UUID; UUID le acceptă pe oricare dintre ele:

Lățime UUID

Tipuri value acceptate

Exemplu

16 biți

int sau un buffer de 2 octeți (little-endian)

UUID(0x2908) sau UUID(b'\x08\x29')

32 de biți

buffer de 4 octeți (little-endian)

UUID(b'\x08\x29\x00\x00')

128 de biți

buffer de 16 octeți sau un șir cu cratime

UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')

UUID-urile pe 16 și 32 de biți sunt de obicei identificatori alocați de SIG (vedeți numerele Bluetooth alocate); UUID-urile pe 128 de biți sunt în mod normal definite de furnizor.