11.11. L2CAP kanali¶
GATT je model ključ/vrijednost. Operacije koje nudi (čitanje, pisanje, obavještavanje, indiciranje) premještaju jednu kratku vrijednost odjednom, a najveći pojedinačni sadržaj koji mogu prenijeti je onaj koji dopušta dogovoreni MTU – u najboljem slučaju nekoliko stotina bajtova. To dobro funkcionira za očitanja senzora, naredbene registre i statusne zastavice. Raspada se na kilobajtima ili megabajtima: dijeljenje duge mrlje podataka na stotine malih zapisivanja košta povratnih putovanja od kojih je radio mnogo brži.
Za tokove velikih količina podataka – snimljenu sličicu koju kamera prenosi telefonu, sliku ažuriranja preko zraka, skupni izvoz mjerenja – BLE nudi alternativni put: Logical Link Control and Adaptation Protocol, L2CAP. L2CAP se nalazi između sloja veze i GATT-a i omogućuje aplikaciji da zatraži vlastiti kanal orijentiran na vezu povrh iste radijske veze. Kanal je bajtni put s kontrolom protoka putem kredita s mnogo većim MTU-om po paketu i bez GATT uokvirivanja u sredini.
11.11.1. Kada koristiti L2CAP¶
L2CAP kanali su pravi alat kada:
Prijenos je veći od nekoliko stotina bajtova.
Oba kraja znaju da će se koristiti L2CAP kanal (nije izložen u sadržaju oglašavanja; klijent mora znati protocol/service multiplexer kanala, odnosno PSM, broj izvan opsega).
Aplikacija je spremna odreći se GATT pogodnosti: nema ugrađene adresabilnosti putem UUID-a, nema otkrivanja klijenta putem standardnih aplikacija, nema obavijesti.
Najčešći slučaj u aplikacijama temeljenim na aioble je premještanje binarne mrlje između dva softvera koji oba znaju za PSM konvenciju – prilagođeni protokol kamera-prema-telefonu, par openmv kamera koje međusobno razgovaraju, interni put ažuriranja firmvera ispod GATT usluge periferije.
Za sve ostalo ostanite na GATT-u. Kratki status, kontrolni registar, očitanje senzora – sve to pripada u karakteristiku.
11.11.2. Uspostavljanje kanala¶
L2CAP se izvodi povrh postojeće aioble.DeviceConnection, pa je tijek otkrivanja / oglašavanja / povezivanja na GAP strani potpuno isti kao za GATT. Kada obje strane drže vezu, jedna strana sluša na PSM-u, a druga se na njega povezuje.
PSM je samo mali cijeli broj. Bluetooth SIG rezervira donji dio raspona za standardiziranu upotrebu (0x0001-0x007F); za kanale specifične za aplikaciju koristite broj iz dinamičkog raspona (0x0080-0x00FF za fiksne PSM-ove, 0x0040 nadalje obično slobodno za prilagođenu upotrebu). Obje strane moraju se unaprijed dogovoriti oko vrijednosti.
MTU na L2CAP kanalu je najveća pojedinačna SDU (Service Data Unit) koju će bilo koja strana isporučiti u jednom send() – ne MTU BLE veze. Aioble automatski fragmentira veće sadržaje. BLE host kamere ograničava L2CAP MTU na 1017 bajtova; 512 je razumna zadana vrijednost koja ostavlja prostora na obje strane bez trošenja RAM-a.
Na strani slušatelja (npr. kamera kao periferija):
async def serve_l2cap(connection, image_bytes):
channel = await connection.l2cap_accept(psm=0x80, mtu=512)
async with channel:
# image_bytes is a bytearray -- e.g. csi0.snapshot().bytearray()
# or a compressed JPEG buffer. send() fragments into MTU-sized
# chunks automatically and awaits flow-control credits between.
await channel.send(image_bytes)
await channel.flush()
Na strani povezivača (npr. telefon ili centralni uređaj):
async def open_l2cap(connection, total_bytes):
channel = await connection.l2cap_connect(psm=0x80, mtu=512)
async with channel:
image_bytes = bytearray(total_bytes)
view = memoryview(image_bytes)
received = 0
while received < total_bytes:
n = await channel.recvinto(view[received:])
if n == 0:
break
received += n
return image_bytes
l2cap_accept() blokira dok se ravnopravni uređaj ne poveže (ili dok ne istekne timeout_ms); l2cap_connect() blokira dok slušatelj ne prihvati (ili ne uspije). Oboje vraćaju aioble.L2CAPChannel – koji je i sam asinkroni upravitelj konteksta koji pri izlasku zatvara kanal.
11.11.3. Slanje i primanje¶
Dvije glavne operacije na kanalu su send() (zapisuje bajtove ravnopravnom uređaju) i recvinto() (čita u unaprijed dodijeljeni međuspremnik). Oboje su korutine.
send()fragmentira međuspremnik u dijelove veličine MTU-a i čeka kredite kontrole protoka sloja veze između njih. Dugo slanje je jedanawaitiz perspektive aplikacije; interno može staviti u red mnogo paketa i pauzirati kad god ponestane primateljskih kredita ravnopravnog uređaja.recvinto()puni predani međuspremnik onim što je dostupno (do MTU-a kanala) i vraća broj bajtova. Čeka ako ništa nije dostupno.available()sinkrono vraćaTrueako su međuspremljeni podaci spremni – korisno za ispitivanje bez obustave.flush()čeka dok bilo koje neizvršeno slanje ne bude potpuno preneseno kontroleru.
L2CAP kanali nalik su tokovima u smislu da bajtovi stižu po redu i bez gubitka, ali granice pojedinačnog send su očuvane – svaka SDU izlazi iz jednog recvinto. To je za razliku od TCP-a, gdje se granice jednog send() mogu razmazati preko više recv() poziva.
11.11.4. Rukovanje prekidom veze¶
Kanal nestaje u tri uvjeta: bilo koja strana pozove disconnect(), prekine se temeljna GAP veza, ili stigne prekid na razini L2CAP-a. Aktivne operacije podižu aioble.L2CAPDisconnectedError. Kao i na GATT strani, ovo se pojavljuje kao iznimka u korutini koja je čekala, a blok async with channel izlazi čisto.
Ako kanal postane nedostupan zbog prekida na razini GAP-a, aplikacija se vraća na oglašavanje ili skeniranje na isti način kao što bi to učinila za GATT prekid.
11.11.5. Troškovi memorije¶
Veći MTU-ovi i dulji redovi koriste više RAM-a na obje strane. MTU od 512 bajtova plus primateljski međuspremnik po kanalu iznosi oko 1 KB po kanalu – ne besplatno na maloj kameri ako je istovremeno otvoreno nekoliko kanala. Držite se jednog kanala po vezi i odaberite MTU koji odgovara očekivanoj veličini poruke; zadani jedan L2CAPChannel po DeviceConnection dovoljan je za većinu aplikacija.
L2CAP je BLE-ov sigurnosni ventil. GATT je ono za čim gotovo svaka aplikacija prvo poseže, a ostali primjeri centralnog uređaja / periferije u ovom odjeljku drže se GATT-a. API u stilu kanala je odgovor kada aplikacija preraste model ključ/vrijednost.