11.8. Modul aioble¶
Specifikace Bluetooth Core poskytuje slovník, který se mapuje na dva moduly MicroPython.
bluetooth– nízkoúrovňová vazba na BLE řadič. Synchronní, řízená událostmi přes callback ve stylu IRQ a strukturovaná kolem bajtových bufferů, handlů a holých GATT primitiv. Vystavuje protokol takový, jaký je, nikoli takový, jak ho chtějí konzumovat aplikace v Pythonu.aioble– vyšší úrovňový obal napsaný v Pythonu nadbluetooth, který každou vzdálenou operaci proměňuje na korutinuasyncioa každý BLE objekt (služby, charakteristiky, připojení, výsledky skenování, kanály L2CAP) na ergonomickou třídu v Pythonu. Skenování se stává asynchronními iterátory; připojení se stávají asynchronními kontextovými správci; oznámení se stávají awaitable.
11.8.1. Kdy sáhnout po nízkoúrovňovém modulu¶
bluetooth je stále tou správnou odpovědí pro dva úzké případy:
Píšete druh kódu, ze kterého je vystavěn sám
aioble– nový vzor, který potřebuje řízení protokolu na úrovni IRQ.Běžíte na hardwarové platformě, kde balíček
aioblenení k dispozici, a tenká mezivrstva kolem řadiče je jedinou možností.
Pro každou kamerovou aplikaci je aioble tou správnou odpovědí.
11.8.2. Části programu aioble¶
Každá aplikace založená na aioble má malou množinu pohyblivých částí, bez ohledu na to, jaké role hraje.
Dlouho běžící smyčka událostí
asyncio. Vše vaiobleje korutina, takže aplikace je strukturována jako jedna nebo více úloh na jediné smyčce událostí. Podrobnosti o smyčce, úlohách a výjimkách viz Asyncio.Zapnuté rádio.
aiobleaktivuje BLE rádio implicitně při prvním použití, ale lze ho také řídit explicitně pomocíaioble.config()(které předává voláníbluetooth.BLE.config()poté, co zajistí, že je rádio v provozu) a vypnout pomocíaioble.stop().Jedna nebo více rolí najednou v běhu. Na straně periferie: registrovaná sada GATT služeb (viz
aioble.register_services()) a běžící korutinaaioble.advertise(). Na straně centrálního zařízení: běžící iterátoraioble.scan()nebo čekajícíaioble.Device.connect(). Rádio práci multiplexuje; aplikace vidí každou roli jako nezávislou úlohu.
11.8.3. Minimální periferie¶
Nejmenší užitečný program aioble – periferie, která inzeruje jedinou charakteristiku pouze pro čtení – je krátký:
import aioble
import asyncio
import bluetooth
SERVICE_UUID = bluetooth.UUID(0x181A) # Environmental Sensing
TEMP_UUID = bluetooth.UUID(0x2A6E) # Temperature
service = aioble.Service(SERVICE_UUID)
temp = aioble.Characteristic(service, TEMP_UUID, read=True)
aioble.register_services(service)
async def main():
while True:
conn = await aioble.advertise(
interval_us=250000,
name="openmv-temp",
services=[SERVICE_UUID],
)
async with conn:
await conn.disconnected()
asyncio.run(main())
Centrální zařízení, které nedělá nic víc než se připojí a jednou přečte, je podobně krátké:
import aioble
import asyncio
import bluetooth
SERVICE_UUID = bluetooth.UUID(0x181A)
TEMP_UUID = bluetooth.UUID(0x2A6E)
async def main():
device = None
async with aioble.scan(duration_ms=5000, active=True) as scanner:
async for result in scanner:
if SERVICE_UUID in result.services():
device = result.device
break
if device is None:
return
async with await device.connect() as conn:
service = await conn.service(SERVICE_UUID)
char = await service.characteristic(TEMP_UUID)
print(await char.read())
asyncio.run(main())
Oba programy mají kolem patnácti řádků a pokrývají celý tok od „rádio je vypnuté“ po „užitečná práce hotova“.
11.8.4. Vypnutí rádia¶
Na kameře napájené z baterie je BLE rádio největším volitelným odběrem z rozpočtu. Záleží na dvou regulátorech.
První je implicitní: aioble aktivuje rádio při prvním použití a rádio mezi naplánovanými událostmi (inzertní dávky, události připojení, skenovací okna) automaticky usíná. Volba delších intervalů u aioble.advertise() / aioble.scan() a dohoda na delším intervalu připojení v čase connect() udržuje rádio vypnuté úměrně více času. Praktickým vodítkem je zde tabulka inzerce v Vysílání (advertising) a skenování.
Druhým je explicitní vypnutí:
import aioble
await do_burst_of_ble_work()
aioble.stop() # radio deactivated; in-flight tasks unwound
await asyncio.sleep(60) # sleep with the radio off
# ... next aioble call brings the radio back up automatically
aioble.stop() deaktivuje podkladové BLE rádio a strhne vše, co je v běhu – otevřená připojení vypadnou, skenery a inzerující se zruší, kanály L2CAP se zavřou. Korutiny, které na tyto operace čekaly, vyvolají své obvyklé výjimky (DeviceDisconnectedError a podobné), což je úklidový mechanismus, pro který byly okolní bloky async with napsány. Volání jakékoli korutiny aioble poté znovu aktivuje rádio ze studeného stavu.
Typický vzor pro periodickou senzorovou kameru napájenou z baterie je:
Probudit se podle plánu (časovač, pohybový senzor, tlačítko).
Spustit dávku BLE práce – inzerovat, přijmout připojení, odeslat hodnotu, odpojit.
Zavolat
aioble.stop()a spát do dalšího probuzení.
11.8.5. Co aioble nedělá¶
aioble záměrně pokrývá GATT, GAP a L2CAP – vrstvy, které aplikace používá. Tři části jsou mimo rozsah:
Cokoli pod linkovou vrstvou. Výběr kanálu, frekvenční skákání, potvrzování paketů a šifrování na linkové vrstvě se vše odehrává uvnitř BLE portu a křemíku řadiče;
aioblena této úrovni nevystavuje žádné háčky.Klasický Bluetooth.
aiobleje pouze pro BLE. Audio spoje, RFCOMM, A2DP a další funkce klasických profilů nejsou součástí API.Bluetooth Mesh. Vrstva síťování typu mesh od Bluetooth SIG (samostatný stack nad BLE inzercí) není na kameře implementována. Kamera může inzerovat a pozorovat, ale nemůže se účastnit rolí relay / friend / proxy v mesh síti.
11.8.6. Výjimky¶
Z aioble vychází čtyři typy výjimek. Každá vystřelí zevnitř korutiny, která čekala na operaci, když se něco pokazilo; bloky async with se při jejich propagaci čistě rozvinou.
aioble.DeviceDisconnectedError– BLE spoj k protějšku vypadl, zatímco byla v běhu GATT operace (read,write,notified,indicated,subscribe,exchange_mtu, …). Vyvolána uvnitř té korutiny, která čekala. Zdaleka nejběžnější výjimka; zachyťte ji v jakémkoli kódu, který se má při ztrátě znovu připojit.aioble.GattError– GATT operace dosáhla protějšku, ale dokončila se s nenulovým ATT stavem (write-with-response odmítnuto, indicate nepotvrzeno, read-not-permitted, …). Stavový kód je na atributu_statusvýjimky.aioble.L2CAPDisconnectedError– kanál L2CAP vypadl, zatímco bylo v běhusend(),recvinto()neboflush(). Kanál mohla zavřít kterákoli ze stran, nebo zaniklo podkladové GAP připojení.aioble.L2CAPConnectionError– vyvolánal2cap_connect(), když naslouchající odmítl nebo řadič selhal při sestavení kanálu. Stavový kód Bluetooth je prvním poziční argumentem.
Operace, které berou explicitní timeout_ms (volání connect / discovery / read / write / pair, plus timeout() jako obal), navíc vyvolají asyncio.TimeoutError z asyncio, když časový limit uplyne dříve, než se operace dokončí.