11.8. Az aioble modul¶
A Bluetooth Core specifikáció olyan szókészletet ad, amely két MicroPython modulra képeződik le.
bluetooth– az alacsony szintű kötés a BLE-vezérlőhöz. Szinkron, IRQ-stílusú visszahíváson keresztül eseményvezérelt, és bájtpufferek, fogantyúk és a puszta GATT-primitívek köré strukturált. A protokollt úgy teszi elérhetővé, ahogy van, nem úgy, ahogy a Python-alkalmazások szeretnék fogyasztani.aioble– egy magasabb szintű csomagoló, Pythonban írva abluetoothtetejére, amely minden távoli műveletetasynciocoroutine-ná, és minden BLE-objektumot (szolgáltatások, karakterisztikák, kapcsolatok, beolvasási eredmények, L2CAP-csatornák) ergonomikus Python-osztállyá alakít. A beolvasásokból aszinkron iterátorok lesznek; a kapcsolatokból aszinkron kontextuskezelők; az értesítések megvárhatóvá válnak.
11.8.1. Mikor nyúlj az alacsonyabb szintű modulhoz¶
A bluetooth még mindig a helyes válasz két szűk esetben:
Olyan kódot írsz, amilyenből maga az
aiobleépül fel – egy új mintát, amelyhez IRQ-szintű vezérlés szükséges a protokoll felett.Olyan hardvercélon futsz, ahol az
aioblecsomag nem elérhető, és a vezérlő köré épített vékony köztesréteg az egyetlen lehetőség.
Minden kameraalkalmazáshoz az aioble a helyes válasz.
11.8.2. Egy aioble program darabjai¶
Minden aioble-alapú alkalmazásnak van egy kis mozgó alkatrészkészlete, függetlenül attól, hogy milyen szerepeket játszik.
Egy hosszan futó
asyncioeseményhurok. Azaioble-ben minden coroutine, így az alkalmazás egy vagy több feladatként van strukturálva egyetlen eseményhurkon. Lásd a Asyncio oldalt a hurok, a feladatok és a kivételek részletes leírásához.Egy bekapcsolt rádió. Az
aiobleaz első használatkor implicit módon aktiválja a BLE-rádiót, de explicit módon is vezérelhető azaioble.config()hívással (amely abluetooth.BLE.config()hívásnak továbbít, miután biztosította, hogy a rádió fent van), és leállítható azaioble.stop()hívással.Egy vagy több szerep egyszerre folyamatban. A peripheral oldalon: a GATT-szolgáltatások regisztrált készlete (lásd az
aioble.register_services()hívást) és egy futóaioble.advertise()coroutine. A central oldalon: egy futóaioble.scan()iterátor vagy egy függőben lévőaioble.Device.connect(). A rádió multiplexeli a munkát; az alkalmazás minden szerepet független feladatként lát.
11.8.3. Egy minimális peripheral¶
A legkisebb hasznos aioble program – egy peripheral, amely egyetlen csak olvasható karakterisztikát hirdet – rövid:
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())
Egy central, amely nem tesz többet, mint hogy csatlakozik és egyszer olvas, hasonlóan rövid:
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())
Mindkét program körülbelül tizenöt sor, és lefedik a teljes folyamatot a „rádió ki van kapcsolva” állapottól a „hasznos munka elvégezve” állapotig.
11.8.4. A rádió kikapcsolása¶
Egy elemmel táplált kamerán a BLE-rádió a legnagyobb diszkrecionális fogyasztó a keretben. Két szabályozó számít.
Az első implicit: az aioble az első használatkor aktiválja a rádiót, és a rádió automatikusan alszik az ütemezett események (hirdetési kitörések, kapcsolati események, beolvasási ablakok) között. Hosszabb intervallumok választása az aioble.advertise() / aioble.scan() hívásokon, és hosszabb kapcsolati intervallumban való megegyezés a connect() időpontjában arányosan több ideig tartja kikapcsolva a rádiót. A hirdetési táblázat a Hirdetés és pásztázás oldalon a gyakorlati útmutató ehhez.
A második az explicit leállítás:
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
Az aioble.stop() deaktiválja az alatta lévő BLE-rádiót, és lebont mindent, ami folyamatban van – a nyitott kapcsolatok megszakadnak, a beolvasók és hirdetők megszakadnak, az L2CAP-csatornák lezáródnak. Azok a coroutine-ok, amelyek ezekre a műveletekre vártak, kiváltják a szokásos kivételeiket (DeviceDisconnectedError és társai), ami az a takarítási mechanizmus, amelyre a környező async with blokkokat írták. Bármely aioble coroutine ezt követő meghívása hidegről újra aktiválja a rádiót.
A tipikus minta egy időszakos, elemmel táplált érzékelőkamerához:
Ébredés ütemezésre (időzítő, mozgásérzékelő, gomb).
A BLE-munka kitörésének futtatása – hirdetés, kapcsolat elfogadása, érték továbbítása, lekapcsolás.
Az
aioble.stop()meghívása és alvás a következő ébredésig.
11.8.5. Amit az aioble nem csinál¶
Az aioble szándékosan lefedi a GATT-ot, a GAP-ot és az L2CAP-ot – azokat a rétegeket, amelyeket egy alkalmazás használ. Három darab kívül esik a hatókörön:
Bármi a kapcsolati réteg alatt. A csatornaválasztás, a frekvenciaugrás, a csomagnyugtázások és a kapcsolati réteg titkosítása mind a BLE-porton és a vezérlő szilíciumán belül történik; az
aioblenem tesz elérhetővé kapcsolódási pontokat azon a szinten.Klasszikus Bluetooth. Az
aioblecsak BLE. Az audiokapcsolatok, az RFCOMM, az A2DP és más klasszikus profilú funkciók nem részei az API-nak.Bluetooth Mesh. A Bluetooth SIG mesh hálózati rétege (egy különálló stack a BLE-hirdetés tetején) nincs megvalósítva a kamerán. A kamera tud hirdetni és megfigyelni, de nem tud részt venni egy mesh hálózat relay / friend / proxy szerepeiben.
11.8.6. Kivételek¶
Négy kivételtípus jön ki az aioble modulból. Mindegyik egy olyan coroutine belsejéből vált ki, amely egy műveletre várt, amikor valami elromlott; az async with blokkok tisztán visszacsévélődnek, amikor ezek propagálódnak.
aioble.DeviceDisconnectedError– a társhoz vezető BLE-kapcsolat megszakadt, miközben egy GATT-művelet (read,write,notified,indicated,subscribe,exchange_mtu, …) folyamatban volt. Abban a coroutine-ban váltódik ki, amelyik éppen várt. Messze a leggyakoribb kivétel; kapd el minden olyan kódban, amelynek veszteség esetén újra kell csatlakoznia.aioble.GattError– egy GATT-művelet elérte a társat, de nem nulla ATT-állapottal fejeződött be (válasszal történő írás elutasítva, indicate nem nyugtázva, read-not-permitted, …). Az állapotkód a kivétel_statusattribútumán található.aioble.L2CAPDisconnectedError– az L2CAP-csatorna megszakadt, miközben egysend(),recvinto()vagyflush()művelet folyamatban volt. Vagy az egyik oldal zárta le a csatornát, vagy az alatta lévő GAP-kapcsolat szűnt meg.aioble.L2CAPConnectionError– al2cap_connect()váltja ki, amikor a figyelő elutasította, vagy a vezérlő meghiúsította a csatorna beállítását. A Bluetooth-állapotkód az első pozicionális argumentum.
Azok a műveletek, amelyek explicit timeout_ms paramétert fogadnak (a connect / discovery / read / write / pair hívások, plusz a timeout() mint csomagoló), ezenfelül asyncio.TimeoutError kivételt is kiváltanak az asyncio modulból, amikor a határidő letelik, mielőtt a művelet befejeződne.