11.6. Služby a charakteristiky¶
Jakmile GAP dostane dvě zařízení do otevřeného spojení, vrstva nad ním – Generic Attribute Profile, GATT – musí bajtům proudícím tímto spojením dát význam. Volba BLE je zde neobvyklá. Zatímco TCP poskytuje surový proud bajtů a ponechává na aplikaci, aby si vymyslela vlastní rámcování, GATT poskytuje malou databázi klíč/hodnota, kterou jedna strana hostuje a druhá z ní čte, zapisuje do ní nebo se k ní přihlašuje k odběru.
Tato databáze je to, čím návrháři aplikací stráví nad BLE většinu času. Co kamera publikuje do telefonu, co sleduje na vzdáleném senzoru, jak Bluetooth klávesnice sděluje svému hostiteli, která klávesa byla stisknuta – to všechno jsou hodnoty charakteristik v nějaké GATT databázi.
11.6.1. Dvě osy rolí, ne jedna¶
Častý zdroj nejasností: peripheral / central a server / client jsou dvě nezávislé osy, nikoli synonyma.
Peripheral a central jsou role GAP, nastavené při navázání spojení. Peripheral inzeruje a je k němu navázáno spojení; central skenuje a spojení iniciuje. To je dáno v okamžiku, kdy spojení vznikne, a nemění se.
Server a client jsou role GATT, nastavené pro každou operaci s charakteristikou. Server hostuje charakteristiku; client z ní čte, zapisuje do ní nebo se k ní přihlašuje k odběru.
Tyto dvě osy jsou specifikací oddělené. Peripheral je obvykle server (pás na měření srdečního tepu publikuje své údaje) a central je obvykle client (telefon je čte), ale BLE umožňuje libovolnou kombinaci – peripheral může objevit charakteristiku na centralu, ke kterému se právě připojil, nebo jediné spojení může hostovat služby na obou stranách najednou.
Většina kamerových aplikací se drží konvenčního párování (peripheral + server, nebo central + client), takže zbytek této části s nimi zachází jako s jednou osou, když je popisován konvenční případ. Když na rozdílu záleží, jsou oba pojmy uvedeny výslovně.
11.6.2. Uvnitř databáze¶
GATT databáze je strom. Listy nesou skutečné bajty. Větve seskupují související listy do lidsky srozumitelných jednotek.
GATT databáze. Služby seskupují charakteristiky; charakteristiky nesou bajty aplikace; deskriptory nesou metadata o charakteristice.¶
Existují tři druhy uzlů:
Služba je logická skupina souvisejících hodnot. Bluetooth SIG publikuje standardní definice služeb pro běžné případy použití – Battery Service pro úroveň nabití baterie, Environmental Sensing pro teplotu / vlhkost / tlak, Heart Rate pro monitory srdečního tepu – takže obecná aplikace v telefonu dokáže rozpoznat službu, kterou nikdy předtím neviděla. Aplikace si také může definovat vlastní služby pro věci, které SIG nestandardizoval.
Charakteristika je jedna pojmenovaná hodnota uvnitř služby. Služba Battery má jedinou charakteristiku – Battery Level, jednobajtové procento. Environmental Sensing má samostatné charakteristiky pro teplotu, vlhkost, tlak a tak dále. Charakteristika je jednotkou operací GATT – charakteristiku čtete, charakteristiku zapisujete, k charakteristice se přihlašujete k odběru.
Deskriptor jsou metadata připojená k charakteristice. Některé deskriptory jsou standardizované – Client Characteristic Configuration Descriptor (CCCD) je ten nejznámější, protože zápis do něj je způsob, jakým client sděluje serveru „posílej mi notifikace o této charakteristice“. Jiné jsou definované uživatelem a nesou věci jako formát prezentace nebo rozšířené vlastnosti.
GATT server (typicky peripheral) deklaruje svou databázi jednou při startu a databáze se za běhu nemění. GATT client (typicky central) objevuje, co je v databázi, po připojení – prochází strom, čte UUID služeb, které najde, a poté charakteristiky uvnitř každé z nich.
11.6.3. UUID¶
Každá služba, charakteristika a deskriptor má UUID (Universally Unique IDentifier), které identifikuje, o jaký druh věci jde. UUID se vyskytují ve třech šířkách:
16bitové. Vyhrazeno pro standardy definované Bluetooth SIG. Battery Service je
0x180F. Battery Level (charakteristika) je0x2A19. Úplný seznam je publikován na stránce přidělených čísel Bluetooth SIG na adrese https://www.bluetooth.com/specifications/assigned-numbers/.32bitové. Zřídka používaný střední stupeň.
128bitové. To, co používají všichni ostatní – dodavatel nebo aplikace jej vygeneruje náhodně a použije pro svou vlastní službu nebo charakteristiku. Sem patří kamery definující vlastní protokol.
Třída bluetooth.UUID přijímá kteroukoli ze tří šířek:
import bluetooth
BATTERY_SERVICE = bluetooth.UUID(0x180F)
CUSTOM_SERVICE = bluetooth.UUID("12345678-1234-5678-9abc-def012345678")
16bitové UUID se zakóduje do malé inzertní zprávy, což je jeden z důvodů, proč jsou standardní služby výhodnější, pokud nějaká existuje – pás na měření srdečního tepu, který inzeruje 0x180D (Heart Rate), stojí dva bajty; vlastní UUID stojí šestnáct. Pro aplikace, které nepotřebují standardní interoperabilitu, je správnou odpovědí vygenerované 128bitové UUID.
11.6.4. Co vám služby standardizované SIG přinášejí¶
Argument pro použití standardní služby je přímočarý: stávající aplikace už s ní umějí komunikovat. Zařízení, které inzeruje službu Heart Rate (0x180D) a poskytuje charakteristiku Heart Rate Measurement (0x2A37), funguje s každou fitness aplikací na planetě, aniž by kdokoli psal nový kód. Zařízení, které stejná data znovu implementuje s vlastními UUID, potřebuje vlastní doprovodnou aplikaci a vlastní dokument protokolu.
Standardy mají svou cenu. Rozložení bajtů uvnitř každé charakteristiky je specifikováno – SIG rozhodl, že Heart Rate Measurement je jednobajtové pole příznaků následované buď 8bitovou, nebo 16bitovou hodnotou srdečního tepu, volitelně následované intervaly R-R – a zařízení odpovídající standardu musí tato rozložení dodržovat. Vlastní služby tímto omezením netrpí.
Pragmatická odpověď pro kamery: použijte standardní službu, pokud nějaká existuje pro druh dat, která máte (Battery Service, Environmental Sensing), a definujte vlastní službu se 128bitovým UUID pro cokoli specifického pro vaši aplikaci.
11.6.5. Objekty na straně serveru a na straně clienta¶
Pro stejné koncepční stavební bloky (služba, charakteristika, deskriptor) každá GATT knihovna poskytuje dvě paralelní sady objektů:
Objekty na straně serveru – to, co peripheral deklaruje, že hostuje. V
aioble:aioble.Service,aioble.Characteristic,aioble.Descriptor. Tyto se konstruují před zahájením inzerce a registrují se pomocíaioble.register_services().Objekty na straně clienta – to, co central objeví na protějšku po připojení. V
aioble:aioble.ClientService,aioble.ClientCharacteristic,aioble.ClientDescriptor. Tyto se procházejí pomocíaioble.DeviceConnection.service()/services()po připojení.