11.8. Modul aioble¶
Spesifikasi Inti Bluetooth memberikan kosakata yang memetakan ke dua modul MicroPython.
bluetooth-- binding tingkat rendah ke controller BLE. Sinkron, berbasis event melalui callback bergaya IRQ, dan terstruktur di sekitar buffer byte, handle, dan primitif GATT dasar. Ia mengekspos protokol sebagaimana adanya, bukan sebagaimana yang diinginkan oleh aplikasi Python untuk dikonsumsi.aioble-- pembungkus tingkat lebih tinggi, ditulis dalam Python di atasbluetooth, yang mengubah setiap operasi jarak jauh menjadi coroutineasynciodan setiap objek BLE (layanan, karakteristik, koneksi, hasil pemindaian, saluran L2CAP) menjadi kelas Python yang ergonomis. Pemindaian menjadi async iterator; koneksi menjadi async context manager; notifikasi menjadi awaitable.
11.8.1. Kapan Menggunakan Modul Tingkat Rendah¶
bluetooth masih merupakan jawaban yang tepat untuk dua kasus sempit:
Anda sedang menulis jenis kode yang menjadi dasar pembangunan
aiobleitu sendiri -- pola baru yang membutuhkan kontrol tingkat IRQ atas protokol.Anda menjalankan pada target hardware di mana paket
aiobletidak tersedia, dan shim tipis di sekitar controller adalah satu-satunya pilihan.
Untuk setiap aplikasi kamera, aioble adalah jawaban yang tepat.
11.8.2. Komponen Program aioble¶
Setiap aplikasi berbasis aioble memiliki sekumpulan komponen yang bergerak, terlepas dari peran apa yang dimainkannya.
Event loop
asyncioyang berjalan lama. Semua yang ada diaiobleadalah coroutine, sehingga aplikasi terstruktur sebagai satu atau lebih task pada satu event loop. Lihat Asyncio untuk detail tentang loop, task, dan pengecualian.Radio yang aktif.
aioblemengaktifkan radio BLE secara implisit saat pertama kali digunakan, tetapi juga dapat dikontrol secara eksplisit denganaioble.config()(yang meneruskan kebluetooth.BLE.config()setelah memastikan radio aktif) dan dimatikan denganaioble.stop().Satu atau lebih peran yang berjalan sekaligus. Di sisi periferal: sekumpulan layanan GATT yang terdaftar (lihat
aioble.register_services()) dan coroutineaioble.advertise()yang berjalan. Di sisi central: iteratoraioble.scan()yang berjalan atauaioble.Device.connect()yang tertunda. Radio memultipleks pekerjaan; aplikasi melihat setiap peran sebagai task yang independen.
11.8.3. Periferal Minimal¶
Program aioble paling sederhana yang berguna -- sebuah periferal yang mengiklankan satu karakteristik hanya-baca -- sangat singkat:
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())
Central yang tidak lebih dari sekadar terhubung dan membaca sekali juga sama singkatnya:
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())
Kedua program terdiri dari sekitar lima belas baris dan mencakup seluruh alur dari "radio mati" hingga "pekerjaan berguna selesai".
11.8.4. Mematikan Radio¶
Pada kamera bertenaga baterai, radio BLE adalah pemakai daya diskresioner terbesar. Dua pengaturan penting.
Yang pertama bersifat implisit: aioble mengaktifkan radio saat pertama kali digunakan, dan radio tidur di antara event yang dijadwalkan (burst periklanan, event koneksi, jendela pemindaian) secara otomatis. Memilih interval yang lebih panjang pada aioble.advertise() / aioble.scan() dan menyepakati interval koneksi yang lebih panjang pada saat connect() membuat radio mati lebih banyak dari waktu ke waktu secara proporsional. Tabel periklanan di Periklanan dan Pemindaian adalah panduan praktisnya.
Yang kedua adalah penonaktifan eksplisit
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() menonaktifkan radio BLE yang mendasarinya dan meruntuhkan semua yang sedang berjalan -- koneksi terbuka terputus, pemindai dan pengiklan dibatalkan, saluran L2CAP ditutup. Coroutine yang menunggu operasi tersebut akan memunculkan pengecualian biasa mereka (DeviceDisconnectedError dan sejenisnya), yang merupakan mekanisme pembersihan untuk blok async with di sekitarnya. Memanggil coroutine aioble mana pun setelahnya akan mengaktifkan radio lagi dari kondisi dingin.
Pola khas untuk kamera sensor bertenaga baterai berkala adalah:
Bangun berdasarkan jadwal (timer, sensor gerak, tombol).
Jalankan rangkaian pekerjaan BLE -- iklankan, terima koneksi, dorong nilai, putuskan koneksi.
Panggil
aioble.stop()dan tidur hingga bangun berikutnya.
11.8.5. Apa yang Tidak Dilakukan aioble¶
aioble secara sengaja mencakup GATT, GAP, dan L2CAP -- lapisan yang digunakan oleh aplikasi. Tiga hal berada di luar cakupan:
Apa pun di bawah lapisan tautan. Pemilihan saluran, frequency hopping, pengakuan paket, dan enkripsi lapisan tautan semuanya terjadi di dalam port BLE dan silicon controller;
aiobletidak mengekspos hook pada tingkat itu.Bluetooth Klasik.
aioblehanya untuk BLE. Tautan audio, RFCOMM, A2DP, dan fitur profil klasik lainnya bukan bagian dari API.Bluetooth Mesh. Lapisan jaringan mesh milik Bluetooth SIG (tumpukan terpisah di atas periklanan BLE) tidak diimplementasikan pada kamera. Kamera dapat mengiklankan dan mengamati, tetapi tidak dapat berpartisipasi dalam peran relay / friend / proxy pada jaringan mesh.
11.8.6. Pengecualian¶
Empat jenis pengecualian berasal dari aioble. Masing-masing dipicu dari dalam coroutine yang sedang menunggu sebuah operasi ketika terjadi kesalahan; blok async with terurai dengan bersih ketika pengecualian merambat.
aioble.DeviceDisconnectedError-- tautan BLE ke peer terputus saat operasi GATT (read,write,notified,indicated,subscribe,exchange_mtu, ...) sedang berlangsung. Dimunculkan di dalam coroutine mana pun yang sedang menunggu. Pengecualian yang paling umum sejauh ini; tangkap di kode mana pun yang harus terhubung kembali saat kehilangan koneksi.aioble.GattError-- operasi GATT berhasil menjangkau peer tetapi selesai dengan status ATT yang tidak nol (write-with-response ditolak, indicate tidak diakui, read-not-permitted, ...). Kode status ada pada atribut_statuspengecualian.aioble.L2CAPDisconnectedError-- saluran L2CAP terputus saatsend(),recvinto(), atauflush()sedang berlangsung. Salah satu sisi mungkin telah menutup saluran, atau koneksi GAP yang mendasarinya menghilang.aioble.L2CAPConnectionError-- dimunculkan olehl2cap_connect()ketika pendengar menolak atau controller gagal dalam pengaturan saluran. Kode status Bluetooth adalah argumen posisional pertama.
Operasi yang mengambil timeout_ms eksplisit (panggilan connect / discovery / read / write / pair, ditambah timeout() sebagai pembungkus) juga memunculkan asyncio.TimeoutError dari asyncio ketika batas waktu habis sebelum operasi selesai.