11.7. GATT műveletek¶
Egy karakterisztika csak egy névvel ellátott értékként ücsörög a GATT adatbázisban. Attól válik hasznossá, hogy egy kliens egy kicsi, jól meghatározott műveletkészletet futtathat rajta. Minden karakterisztika egy tulajdonság-bitmaszkban (property bitmask) deklarálja, hogy mely műveleteket támogatja – egy kiszolgáló, amelynek nincs mit közzétennie, csak olvasható értéket publikálhat, egy vezérlőregiszter lehet csak írható, egy frissítéseket közvetítő érzékelő pedig beállítaná a notify bitet. A kliens a felfedezés során megismeri a bitmaszkot, és tiszteletben tartja azt.
Az öt művelet a read, write, write without response, notify és indicate. Két csoportra oszlanak – pull (a kliens kérdez) és push (a kiszolgáló küld).
11.7.1. Pull: olvasás és írás¶
Ez a kettő a legegyszerűbb, és pontosan úgy néz ki, mint a függvényhívások.
Read. A kliens elkéri az aktuális értéket, a kiszolgáló pedig visszaküldi. Egy oda-vissza forduló, a kliens megkapja azokat a bájtokat, amelyeket a kiszolgáló az adott karakterisztikához beállított, a kiszolgáló pedig semmit sem tud meg arról, ki olvasott.
Write. A kliens új bájtokat küld, a kiszolgáló pedig eltárolja azokat (és opcionálisan alkalmazáslogikát futtat az új értéken). Két változata létezik:
Write with response – a kiszolgáló nyugtáz, és nem nulla állapot esetén bármilyen alkalmazáshibát kivált. Megbízható, egy oda-vissza forduló.
Write without response – a kiszolgáló csendben eltárolja a bájtokat; a kliens egyáltalán nem kap nyugtázást. Gyorsabb (nincs a nyugtára váró oda-vissza forduló) és hasznos közvetítéshez, cserébe a hibákról csak mellékcsatornás visszaolvasással lehet tudomást szerezni.
Az aioble-ben a kliensoldali API egyetlen aioble.ClientCharacteristic.write() metódus mögé rejti a választást egy response kulcsszóval (True / False / None az automatikus kiválasztáshoz aszerint, amit a társ hirdet).
11.7.2. Push: notify és indicate¶
A pull modell nem megfelelő érzékelőadatokhoz. Egy pulzusmérő öv, amelyet a telefonnak másodpercenként le kell kérdeznie, akkumulátort égetne száz felesleges rádióeseményen; az viszont, amelyik csak akkor küld értéket, ha új mérése van, eleve a BLE lényege.
A GATT ezt kiszolgáló-kezdeményezésű (server-initiated) műveletekkel oldja meg. A kliens feliratkozik egy karakterisztikára; ettől a ponttól kezdve minden alkalommal, amikor a kiszolgáló frissíti az értéket, az új érték áttolódik a kapcsolaton a kliensnek. Két változat:
Notify. Küldd-és-felejtsd. A kiszolgáló sorba állít egy értesítést, a link réteg a következő kapcsolati esemény alatt elküldi, a kliens pedig megkapja. GATT szinten nincs nyugtázás; a link réteg szokásos újraküldése kezeli a veszteséget a rádió oldalán, de az alkalmazás nem lát megerősítést arról, hogy az értéket feldolgozták.
Indicate. A kiszolgáló küld egy értesítést, és megvárja a kliens GATT szintű megerősítését, mielőtt a következőt elküldené. Egyszerre egy jelzés. Akkor használatos, amikor a kiszolgálónak tudnia kell, hogy a kliens valóban látta az értéket – egy kritikus-riasztás karakterisztika, egy konfigurációs nyugtázás.
Pull (read) kontra push (notify). Értesítések esetén a kliens egyszer feliratkozik, a kiszolgáló pedig új értékeket tol át, valahányszor azok megváltoznak.¶
A feliratkozás úgy történik, hogy a kliens ír egy, a karakterisztikához csatolt leíróba – a Client Characteristic Configuration Descriptor-ba (CCCD, 0x2902). A 0x0001 írása engedélyezi az értesítéseket, a 0x0002 engedélyezi a jelzéseket, a 0x0000 mindkettőt letiltja. A aioble.ClientCharacteristic.subscribe() metódus elvégzi helyetted az írást, notify=True és indicate=True kulcsszavas jelzőkkel.
A feliratkozás után a kliens a notified() és indicated() metódusokkal várja a beérkező tolásokat – mindkettő olyan aszinkron korutin, amely a következő tolás megérkezéséig felfüggeszt.
11.7.3. Az MTU szabályozza a hasznos adat méretét¶
Minden műveletet korlátoz a kapcsolat által a felépüléskor beállított, megtárgyalt MTU. Az alapértelmezett MTU 23 bájt, ami a GATT fejléc után 20 bájtot hagy a karakterisztika értékbájtjainak. Bármi, ami ennél nagyobb, vagy be kell, hogy férjen egy nagyobb MTU-ba (a aioble.DeviceConnection.exchange_mtu() segítségével felfelé tárgyalva, a kamerán akár 512 bájtig), vagy több karakterisztikára vagy több értesítésre kell felosztani.
Az MTU-nál nagyobb értékek kliens-kezdeményezésű olvasásait és írásait a GATT long eljárásai kezelik a háttérben (Read Long / Prepare-Write + Execute-Write); az aioble ezeket átláthatóan futtatja, így a read() / write() túlméretes értékkel való hívása csak több oda-vissza fordulóba kerül. A kiszolgáló-kezdeményezésű értesítéseket és jelzéseket nem darabolja fel – egy tolást az MTU korlátoz, és az alkalmazás bármit, ami ennél nagyobb, több értesítésre bont, vagy teljesen elhagyja a GATT-ot.
Valóban nagy átvitelekhez – egy rögzített képkockához, egy mérési kötegekhez, egy firmware-bloblhoz – a helyes válasz általában az, hogy teljesen elhagyjuk a GATT-ot, és helyette egy L2CAP csatornát használunk (lásd L2CAP-csatornák).
11.7.4. A két oldal egy pillantásra¶
Az öt művelet a kapcsolat mindkét oldalán másképp jelenik meg:
A kiszolgáló (server) oldalán (a periféria, a szokásos elrendezésben):
aioble.Characteristic.read()– az aktuális helyi érték kiolvasása a GATT adatbázisból (annak a kiszolgáló oldala, hogy „mit látna a kliens”).aioble.Characteristic.write()– a helyi érték frissítése, opcionálisan a frissítés áttolása minden feliratkozott kliensre.aioble.Characteristic.notify()/indicate()– tolás küldése egy adott kliensnek.aioble.Characteristic.written()– a következő beérkező írás bevárása bármely klienstől.aioble.Characteristic.on_read()– szinkron módon meghívott visszahívás, amikor egy kliens olvas, hasznos egy érték igény szerinti kiszámításához.
A kliens (central) oldalán (a központ, a szokásos elrendezésben):
aioble.ClientCharacteristic.read()– az aktuális érték elkérése a kiszolgálótól.aioble.ClientCharacteristic.write()– új érték küldése, válasszal vagy anélkül.aioble.ClientCharacteristic.subscribe()– értesítések és jelzések engedélyezése / letiltása.aioble.ClientCharacteristic.notified()/indicated()– a következő tolás bevárása.