11.8. aioble modülü

Bluetooth Core belirtimi, iki MicroPython modülüne eşlenen bir sözcük dağarcığı sunar.

  • bluetooth – BLE denetleyicisine düşük düzeyli bağlama. Eşzamanlı, IRQ tarzı bir geri çağırma (callback) aracılığıyla olay güdümlü ve bayt arabellekleri, tutamaçlar ile çıplak GATT ilkelleri etrafında yapılandırılmıştır. Protokolü, Python uygulamalarının tüketmek istediği gibi değil, olduğu gibi açığa çıkarır.

  • aioblebluetooth üzerine Python ile yazılmış, her uzak işlemi bir asyncio eşyordamına ve her BLE nesnesini (hizmetler, karakteristikler, bağlantılar, tarama sonuçları, L2CAP kanalları) ergonomik bir Python sınıfına dönüştüren daha üst düzey bir sarmalayıcı. Taramalar asenkron yineleyiciler olur; bağlantılar asenkron bağlam yöneticileri olur; bildirimler beklenebilir hale gelir.

11.8.1. Düşük düzeyli modüle ne zaman başvurulur

bluetooth, iki dar durum için hâlâ doğru yanıttır:

  • aioble‘ın kendisinin inşa edildiği türden kod yazıyorsunuz – protokol üzerinde IRQ düzeyinde denetim gerektiren yeni bir desen.

  • aioble paketinin mevcut olmadığı bir donanım hedefinde çalışıyorsunuz ve denetleyici etrafında ince bir uyumlaştırma katmanı tek seçenektir.

Her kamera uygulaması için doğru yanıt aioble‘dır.

11.8.2. Bir aioble programının parçaları

aioble tabanlı her uygulama, oynadığı rollerden bağımsız olarak küçük bir hareketli parça kümesine sahiptir.

  • Uzun süre çalışan bir asyncio olay döngüsü. aioble‘daki her şey bir eşyordamdır, dolayısıyla uygulama tek bir olay döngüsünde bir veya daha fazla görev olarak yapılandırılır. Döngü, görevler ve özel durumların ayrıntıları için Asyncio sayfasına bakın.

  • Açık olan bir radyo. aioble, ilk kullanımda BLE radyosunu örtük olarak etkinleştirir, ancak aioble.config() ile (radyonun açık olduğundan emin olduktan sonra bluetooth.BLE.config() çağrısına iletir) açıkça denetlenebilir ve aioble.stop() ile kapatılabilir.

  • Aynı anda işleyen bir veya daha fazla rol. Peripheral tarafında: kayıtlı bir GATT hizmetleri kümesi (bkz. aioble.register_services()) ve çalışan bir aioble.advertise() eşyordamı. Central tarafında: çalışan bir aioble.scan() yineleyicisi veya bekleyen bir aioble.Device.connect(). Radyo işi çoklar; uygulama her rolü bağımsız bir görev olarak görür.

11.8.3. Asgari bir peripheral

En küçük kullanışlı aioble programı – tek bir salt okunur karakteristik yayınlayan bir peripheral – kısadır:

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())

Yalnızca bir kez bağlanıp okuyan bir central da benzer şekilde kısadır:

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())

Her iki program da yaklaşık on beş satırdır ve “radyo kapalı” durumundan “yararlı iş tamamlandı” durumuna kadar tüm akışı kapsar.

11.8.4. Radyoyu kapatma

Pil ile çalışan bir kamerada BLE radyosu, bütçedeki en büyük isteğe bağlı tüketim kalemidir. İki ayar önemlidir.

Birincisi örtüktür: aioble, radyoyu ilk kullanımda etkinleştirir ve radyo, zamanlanmış olaylar (yayın patlamaları, bağlantı olayları, tarama pencereleri) arasında otomatik olarak uyur. aioble.advertise() / aioble.scan() üzerinde daha uzun aralıklar seçmek ve connect() sırasında daha uzun bir bağlantı aralığı üzerinde anlaşmak, radyoyu orantılı olarak daha uzun süre kapalı tutar. Reklam yapma ve tarama sayfasındaki yayın tablosu burada pratik kılavuzdur.

İkincisi açık kapatmadır:

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(), alttaki BLE radyosunu devre dışı bırakır ve işleyen her şeyi kapatır – açık bağlantılar düşer, tarayıcılar ve yayıncılar iptal edilir, L2CAP kanalları kapanır. Bu işlemleri bekleyen eşyordamlar, çevredeki async with bloklarının yazıldığı temizleme mekanizması olan olağan özel durumlarını (DeviceDisconnectedError ve benzerleri) fırlatır. Sonrasında herhangi bir aioble eşyordamı çağırmak radyoyu soğuktan yeniden etkinleştirir.

Periyodik, pil ile çalışan bir sensör kamerası için tipik desen şudur:

  • Bir zamanlamayla uyan (zamanlayıcı, hareket sensörü, düğme).

  • BLE iş patlamasını çalıştır – yayın yap, bir bağlantı kabul et, değeri gönder, bağlantıyı kes.

  • aioble.stop() çağır ve bir sonraki uyanmaya kadar uyu.

11.8.5. aioble’ın yapmadıkları

aioble, kasıtlı olarak GATT, GAP ve L2CAP’i – bir uygulamanın kullandığı katmanları – kapsar. Üç parça kapsam dışındadır:

  • Bağlantı katmanının altındaki her şey. Kanal seçimi, frekans atlama, paket onaylamaları ve bağlantı katmanı şifrelemesinin tümü BLE portunun ve denetleyici silikonunun içinde gerçekleşir; aioble o düzeyde kancalar açığa çıkarmaz.

  • Klasik Bluetooth. aioble yalnızca BLE’dir. Ses bağlantıları, RFCOMM, A2DP ve diğer klasik profil özellikleri API’nin bir parçası değildir.

  • Bluetooth Mesh. Bluetooth SIG’in mesh ağ katmanı (BLE yayını üzerine ayrı bir yığın) kamerada uygulanmamıştır. Kamera yayın yapabilir ve gözlemleyebilir, ancak bir mesh ağının aktarma / arkadaş / vekil rollerine katılamaz.

11.8.6. Özel durumlar

aioble‘dan dört özel durum türü çıkar. Her biri, bir şeyler ters gittiğinde bir işlemi bekleyen bir eşyordamın içinden fırlar; async with blokları, bu durumlar yayıldığında temiz bir şekilde geri sarılır.

  • aioble.DeviceDisconnectedError – bir GATT işlemi (read, write, notified, indicated, subscribe, exchange_mtu, …) işlerken eşe olan BLE bağlantısı düştü. Bekleyen eşyordamın içinde fırlatılır. Açık ara en yaygın özel durumdur; kayıp durumunda yeniden bağlanması gereken her kodda yakalayın.

  • aioble.GattError – bir GATT işlemi eşe ulaştı ancak sıfırdan farklı bir ATT durumuyla tamamlandı (yanıtlı yazma reddedildi, gösterim onaylanmadı, okumaya izin verilmedi, …). Durum kodu özel durumun _status özniteliğindedir.

  • aioble.L2CAPDisconnectedError – bir send(), recvinto() veya flush() işlerken L2CAP kanalı düştü. İki taraftan biri kanalı kapatmış olabilir veya alttaki GAP bağlantısı ortadan kalkmış olabilir.

  • aioble.L2CAPConnectionError – dinleyici reddettiğinde veya denetleyici kanal kurulumunu başarısız kıldığında l2cap_connect() tarafından fırlatılır. Bluetooth durum kodu ilk konumsal bağımsız değişkendir.

Açık bir timeout_ms alan işlemler (connect / discovery / read / write / pair çağrıları ve bir sarmalayıcı olarak timeout()), işlem tamamlanmadan son tarih geçtiğinde ayrıca asyncio‘dan asyncio.TimeoutError fırlatır.