11.5. Conexiuni

Odată ce un dispozitiv central alege un periferic din fluxul de advertising și îi trimite o cerere de conectare, ambele părți ies din modul advertising / scanare și intră într-o conexiune. Radioul își programează acum activitatea pe canalele de date ale stratului de legătură (link layer), sărind pseudo-aleatoriu între ele după secvența convenită la momentul conectării. Tot ce se află deasupra stratului de legătură – GATT, securitate, L2CAP – rulează peste conexiunea stabilită aici.

11.5.1. Evenimentul de conexiune

Două dispozitive aflate într-o conexiune BLE nu transmit continuu. Ele convin asupra unui interval de conexiune, iar la fiecare interval ambele părți trezesc radioul, schimbă pachetele aflate în coadă, confirmă ce au primit și se întorc la repaus. Fiecare astfel de schimb se numește eveniment de conexiune.

O cronologie cu dispozitivul central pe pista de sus și perifericul pe pista de jos. La fiecare limită de interval de conexiune, ambele piste arată un impuls scurt etichetat "TX/RX". Spațiul dintre impulsuri este etichetat "interval de conexiune"; durata fiecărui impuls este "eveniment de conexiune". Perifericul are câteva evenimente omise etichetate "latență periferic: perifericul poate sări dacă este inactiv".

Radioul de pe fiecare parte este activ doar pe durata scurtelor evenimente de conexiune, restul timpului fiind în repaus. Perifericul poate sări peste evenimente în cadrul latenței periferic.

Valorile care guvernează acest lucru sunt negociate la momentul conectării, iar stratul de legătură le impune. Ele sunt vizibile aplicației atât ca parametri din partea cererii, cât și ca valori rezultate raportate înapoi.

  • Interval de conexiune. De la 7.5 ms la 4 s, în pași de 1.25 ms. Dispozitivul central alege valoarea cerută de periferic, cu excepția cazului în care cererea este nerezonabilă. Intervalele mai scurte livrează datele cu latență mai mică, cu prețul unei activități radio mai mari; cele mai lungi economisesc energie, dar încetinesc fiecare schimb dus-întors.

  • Latență periferic. Un număr întreg nenegativ N. Perifericul are voie să sară peste până la N evenimente de conexiune dacă nu are nimic de trimis, întorcându-se la repaus în loc să trezească radioul pentru un schimb gol. Util pentru senzori care se trezesc să raporteze o dată pe secundă, dar doresc un interval de conexiune receptiv și redus pentru rarul mesaj imediat.

  • Timeout de supraveghere. De la 100 ms la 32 s. Dacă oricare parte nu mai aude nimic de la cealaltă pe această durată, legătura este declarată pierdută și ambele părți revin la advertising / scanare. Timeout-ul trebuie să fie mai lung decât connection_interval * (1 + peripheral_latency) – stratul de legătură respinge valorile care încalcă această condiție.

aioble.Device.connect() primește min_conn_interval_us și max_conn_interval_us astfel încât dispozitivul central să poată cere un anumit interval; valoarea efectivă asupra căreia s-a stabilit radioul poate fi citită înapoi prin configurarea stratului de legătură după ce conexiunea este activă.

11.5.2. Ce înseamnă „central” și „periferic” în interiorul unei conexiuni

Rolurile stabilite la momentul advertising-ului rămân după ce conexiunea este stabilită:

  • Dispozitivul central dictează temporizarea – el deține partea master a secvenței de salt și a evenimentelor de conexiune.

  • Perifericul este reactiv. El poate cere o modificare a parametrilor de conexiune (de exemplu un interval mai lung pentru a economisi energie), dar dispozitivul central decide dacă o acceptă.

Rolurile sunt independente de cine găzduiește baza de date GATT, care este o axă separată. Prin convenție, perifericul este și serverul GATT, iar dispozitivul central este clientul GATT, însă BLE permite oricărei părți să găzduiască servicii GATT. Camerele urmează aproape întotdeauna convenția: periferic + server pentru aplicații de tip „camera publică date” și central + client pentru aplicații de tip „camera citește de la un senzor”.

11.5.3. Unitatea maximă de transmisie (MTU)

Stratul de legătură transportă în mod implicit pachete scurte – 27 de octeți de payload, din care doar 23 sunt disponibili pentru GATT. Este suficient pentru o citire mică sau o comandă scurtă, dar foarte puțin pentru orice depășește câțiva octeți. Ambele părți pot negocia mărirea acestei valori, până la limita pe care o suportă firmware-ul radio (de obicei câteva sute de octeți pe controlerele moderne).

API-ul aioble conduce negocierea prin aioble.DeviceConnection.exchange_mtu(), iar rezultatul devine disponibil pe atributul mtu. Valori MTU mai mari înseamnă mai puține schimburi dus-întors pentru orice valoare mai mare de ~20 de octeți, cu un cost mic în memorie tampon (buffer).

11.5.4. Durata de viață

O conexiune durează până la unul dintre următoarele:

  • oricare parte apelează disconnect(),

  • se declanșează timeout-ul de supraveghere (în afara razei, radio oprit, partener blocat), sau

  • o eroare explicită a stratului de legătură (nepotrivire de criptare, respingerea împerecherii).

Când conexiunea cade, orice operație GATT aflată în coadă sau în curs pe ea ridică aioble.DeviceDisconnectedError, iar orice bloc async with connection în care se află aplicația se închide curat. Un periferic răspunde de obicei revenind la aioble.advertise() și așteptând următorul dispozitiv central; un dispozitiv central răspunde fie scanând din nou, fie expunând deconectarea către aplicație.

Durata de viață este unul dintre motivele pentru care aioble este util. Un API BLE sincron ar trebui să expună funcții de retroapelare (callback) pentru deconectare și măști de evenimente; versiunea asyncio transformă deconectările în excepții în interiorul corutinei care aștepta operația, exact ceea ce pentru care a fost gândită curățarea async with.