aioble — Async BLE#

aioble is een asyncio-vriendelijke wrapper op hoog niveau rond de bluetooth-module. Het biedt overzichtelijke coroutines voor scannen, verbinden, adverteren, GATT-services en L2CAP-kanalen.

Alle bewerkingen op afstand (connect, disconnect, client read/write, server indicate, l2cap recv/send, pair) zijn awaitable en ondersteunen time-outs.

Ondersteunde rollen:

  • Broadcaster (advertiser) — genereert advertising- en scan-response-payloads voor veelvoorkomende velden, splitst de payload automatisch over advertising en scan response, adverteert onbeperkt of gedurende een vaste tijd.

  • Peripheral — wacht op een verbinding van een central, wacht op MTU-uitwisseling.

  • Observer (scanner) — passief en actief scannen, advertising- en scan-response-payloads voor hetzelfde apparaat combineren, veelvoorkomende velden uit advertising-payloads parsen.

  • Central — verbinden met een peripheral, MTU-uitwisseling starten.

  • GATT Client — services / characteristics / descriptors ontdekken (optioneel op UUID); read / write / write-with-response op characteristics en descriptors; abonneren op notifications en indications (via de CCCD); wachten op notifications en indications.

  • GATT Server — services / characteristics / descriptors registreren; wachten op writes op characteristics en descriptors; read-requests onderscheppen; notifications en indications versturen (en op antwoord wachten).

  • L2CAP — L2CAP connection-oriented kanalen accepteren en verbinden, flow control van het kanaal beheren.

  • Security — JSON-gebaseerd beheer van sleutels/geheimen, pairing starten, status van encryptie / authenticatie opvragen.

Voorbeelden#

Scan naar nabije BLE-apparaten en print elk apparaat zodra het wordt gezien:

import aioble
import asyncio

async def find_devices():
    async with aioble.scan(duration_ms=5000, active=True) as scanner:
        async for result in scanner:
            print(result.device.addr_hex(), result.rssi, result.name())

asyncio.run(find_devices())

Verbind als central met een peripheral die de Heart Rate-service adverteert en abonneer op de bijbehorende meet-notifications:

import aioble
import asyncio
import bluetooth

_HR_SERVICE = bluetooth.UUID(0x180D)
_HR_MEASUREMENT = bluetooth.UUID(0x2A37)

async def connect_and_read():
    device = None
    async with aioble.scan(duration_ms=5000, active=True) as scanner:
        async for result in scanner:
            if _HR_SERVICE in result.services():
                device = result.device
                break
    if device is None:
        return

    async with await device.connect() as conn:
        service = await conn.service(_HR_SERVICE)
        char = await service.characteristic(_HR_MEASUREMENT)
        await char.subscribe(notify=True)
        while True:
            data = await char.notified()
            print("notify:", data)

asyncio.run(connect_and_read())

Treed op als peripheral: registreer een GATT-service, adverteer deze en stuur notifications naar iedereen die verbinding maakt:

import aioble
import asyncio
import bluetooth
import struct

_ENV_SERVICE = bluetooth.UUID(0x181A)
_TEMP_CHAR = bluetooth.UUID(0x2A6E)

def encode_temperature(deg_c):
    # Bluetooth Temperature (0x2A6E) is sint16 little-endian, 0.01 degC units.
    return struct.pack("<h", round(deg_c * 100))

service = aioble.Service(_ENV_SERVICE)
temp_char = aioble.Characteristic(service, _TEMP_CHAR, read=True, notify=True)
aioble.register_services(service)

async def peripheral_task():
    while True:
        connection = await aioble.advertise(
            interval_us=250000,
            name="openmv-sensor",
            services=[_ENV_SERVICE],
            appearance=0x0300,
        )
        print("connected:", connection.device.addr_hex())
        async with connection:
            while connection.is_connected():
                temp_char.write(encode_temperature(23.68), send_update=True)
                await asyncio.sleep(1)

asyncio.run(peripheral_task())

Functies op moduleniveau#

aioble.config(*args, **kwargs) Any#

Stuurt door naar bluetooth.BLE.config() en zorgt ervoor dat de BLE-radio eerst actief is.

args

Optionele naam van een enkele parameter om op te vragen.

kwargs

Keyword-argumenten om configuratiewaarden in te stellen.

aioble.stop() None#

Deactiveer de onderliggende BLE-radio en voer eventuele geregistreerde shutdown-handlers van submodules uit. Na het aanroepen hiervan worden scanners, advertisers, verbindingen en L2CAP-kanalen allemaal afgebroken.

aioble.scan(duration_ms: int, interval_us: int | None = None, window_us: int | None = None, active: bool = False) scan#

Retourneert een scan async context-manager / async-iterator die ScanResult-instanties oplevert voor elk uniek ontdekt apparaat (of voor elk nieuw stuk advertising-data van een bekend apparaat).

duration_ms

Hoe lang er gescand moet worden, in milliseconden. Geef 0 op om onbeperkt te scannen totdat de context manager wordt afgesloten.

interval_us

Scaninterval in microseconden. Standaard 1.280.000.

window_us

Scanvenster in microseconden (moet kleiner dan of gelijk aan interval_us zijn). Standaard 11.250.

active

Als True, voer een actieve scan uit (vraag scan-response-data aan). Standaard False.

aioble.advertise(interval_us: int, adv_data: bytes | None = None, resp_data: bytes | None = None, connectable: bool = True, limited_disc: bool = False, br_edr: bool = False, name: str | None = None, services: list | None = None, appearance: int = 0, manufacturer: tuple | None = None, timeout_ms: int | None = None) DeviceConnection#

Async coroutine die begint met adverteren en wacht op een inkomende central-verbinding. Retourneert een DeviceConnection die de verbonden central voorstelt, of werpt asyncio.TimeoutError bij een time-out.

interval_us

Advertising-interval, in microseconden.

adv_data

Ruwe advertising-payload. Indien niet ingesteld, wordt adv_data opgebouwd uit de overige keyword-argumenten.

resp_data

Ruwe scan-response-payload. Wordt automatisch gevuld om overloop uit adv_data op te vangen indien nodig.

connectable

Als True, is dit een verbindbare advertentie.

limited_disc

Gebruik de limited-discoverable-vlag in plaats van general.

br_edr

Stel de BR/EDR-supported-vlag in.

name

Optionele volledige lokale naam om in te bedden.

services

Iterable van bluetooth.UUID om te adverteren.

appearance

16-bits appearance-waarde (zie de Bluetooth assigned numbers).

manufacturer

Tuple van (company_id, data_bytes) om te adverteren als manufacturer-specifieke data.

timeout_ms

Stop met adverteren na zoveel milliseconden zonder verbinding. None betekent adverteren totdat er verbinding is.

aioble.register_services(*services: Service) None#

Registreer een of meer Service-objecten (en hun characteristics en descriptors) bij de GATT-server. Moet één keer worden aangeroepen voordat advertise wordt gestart. Volgende aanroepen vervangen de vorige registratie.

services

Een of meer Service-instanties.

Constanten op moduleniveau#

aioble.ADDR_PUBLIC#

Publiek BLE-apparaatadrestype (0).

aioble.ADDR_RANDOM#

Willekeurig BLE-apparaatadrestype (1).

Uitzonderingen#

exception aioble.GattError#

Wordt geworpen wanneer een externe GATT-bewerking (read / write / indicate) wordt voltooid met een status ongelijk aan nul. De statuscode is beschikbaar via het _status-attribuut.

exception aioble.DeviceDisconnectedError#

Wordt geworpen binnen een async-bewerking (bijv. read, write, notified) wanneer de onderliggende verbinding wegvalt tijdens het wachten.

exception aioble.L2CAPDisconnectedError#

Wordt geworpen wanneer een send/recv/flush-bewerking op een L2CAP-kanaal wordt geprobeerd op (of onderbroken door) een verbroken kanaal.

exception aioble.L2CAPConnectionError#

Wordt geworpen door DeviceConnection.l2cap_connect wanneer het tot stand brengen van het kanaal mislukt. De Bluetooth-statuscode is het eerste argument.

Klassen#

class aioble.Device(addr_type: int, addr: bytes | str)#

Stelt een extern BLE-apparaat voor op basis van adres. Twee Device-instanties zijn gelijk als zowel addr_type als addr overeenkomen. Wordt gebruikt als handle voor het starten van verbindingen.

addr_type

Ofwel ADDR_PUBLIC of ADDR_RANDOM.

addr

Adres van zes bytes als bytes, of een door dubbele punten gescheiden hex-string (bijv. "aa:bb:cc:dd:ee:ff").

addr_type#

Het adrestype waarmee het apparaat is geconstrueerd.

addr#

Het ruwe apparaatadres van zes bytes.

addr_hex() str#

Retourneert het adres opgemaakt als een door dubbele punten gescheiden hex-string.

connect(timeout_ms: int = 10000, scan_duration_ms: int | None = None, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None) Awaitable[DeviceConnection]#

Async. Start een GAP-verbinding met dit apparaat en retourneert de resulterende DeviceConnection. Annuleert een eventueel lopende scan.

timeout_ms

Hoe lang er gewacht moet worden tot de verbinding voltooid is.

scan_duration_ms

Initiële scanduur voordat er verbinding wordt gemaakt (controllerspecifiek).

min_conn_interval_us / max_conn_interval_us

Optionele grenzen voor het verbindingsinterval, in microseconden.

class aioble.DeviceConnection#

Een actieve GAP-verbinding met een Device. Geretourneerd door Device.connect() of advertise. Ondersteunt gebruik als async with context manager die automatisch ontkoppelt bij het afsluiten.

Niet rechtstreeks construeren.

device#

De onderliggende Device.

encrypted#

True zodra de link versleuteld is (bijv. na pairing).

authenticated#

True als de link geauthenticeerd was (MITM-beschermde pair).

bonded#

True als pairing bonding-sleutels heeft opgeleverd.

key_size#

Onderhandelde encryptiesleutelgrootte in bytes, of False indien niet versleuteld.

mtu#

Onderhandelde ATT-MTU na exchange_mtu, of None totdat deze is ingesteld.

is_connected() bool#

Retourneert of de verbinding nog actief is.

disconnect(timeout_ms: int = 2000) Awaitable[None]#

Async. Verbreek de verbinding en wacht op de disconnection-IRQ.

timeout_ms

Maximale tijd om te wachten op de verbreking.

disconnected(timeout_ms: int | None = None, disconnect: bool = False) Awaitable[None]#

Async. Wacht tot de verbinding door een van beide partijen wordt beëindigd. Als disconnect True is, wordt de verbinding eerst actief verbroken.

timeout_ms

Maximale wachttijd. None betekent oneindig wachten.

disconnect

Als True, initieer het verbreken van de verbinding.

timeout(timeout_ms: int | None) DeviceTimeout#

Retourneert een context manager die zijn body annuleert als ofwel de time-out verstrijkt (waarbij asyncio.TimeoutError wordt geworpen) of het apparaat de verbinding verbreekt (waarbij DeviceDisconnectedError wordt geworpen).

timeout_ms

Time-out in milliseconden, of None voor geen time-out.

exchange_mtu(mtu: int | None = None, timeout_ms: int = 1000) Awaitable[int]#

Async. Start een ATT-MTU-uitwisseling en retourneert de onderhandelde MTU.

mtu

Optionele voorkeurs-MTU om in te stellen op de onderliggende BLE-interface vóór de uitwisseling.

timeout_ms

Time-out voor de uitwisseling.

service(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientService | None]#

Async. Ontdek een enkele externe service die overeenkomt met uuid, of None indien niet gevonden.

services(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover#

Retourneert een async iterator van externe ClientService-objecten. Gebruik met async for en laat de lus tot het einde doorlopen.

uuid

Optioneel UUID-filter. None retourneert elke service.

timeout_ms

Time-out per ontdekking.

pair(bond: bool = True, le_secure: bool = True, mitm: bool = False, io: int = 3, timeout_ms: int = 20000) Awaitable[None]#

Async. Start pairing op deze verbinding. Werkt de attributen encrypted / authenticated / bonded / key_size bij wanneer voltooid.

bond

Bewaar pairing-sleutels.

le_secure

Gebruik LE Secure Connections.

mitm

Vereis man-in-the-middle-bescherming.

io

IO-capability-constante (bijv. 3 voor geen input/output).

timeout_ms

Pairing-time-out.

l2cap_accept(psm: int, mtu: int, timeout_ms: int | None = None) Awaitable[L2CAPChannel]#

Async. Luister op de opgegeven PSM en retourneert een L2CAPChannel zodra de remote deze opent.

psm

Protocol/Service Multiplexer om op te luisteren.

mtu

Maximale ontvangstgrootte, in bytes.

timeout_ms

Maximale tijd om te wachten tot de remote verbinding maakt.

l2cap_connect(psm: int, mtu: int, timeout_ms: int = 1000) Awaitable[L2CAPChannel]#

Async. Open een L2CAP-kanaal naar de remote op de opgegeven PSM.

psm

Protocol/Service Multiplexer om mee te verbinden.

mtu

Maximale ontvangstgrootte, in bytes.

timeout_ms

Verbindings-time-out.

class aioble.ScanResult#

Een enkel apparaat dat tijdens scan is ontdekt. Dezelfde instantie wordt opnieuw opgeleverd wanneer er nieuwe advertising-data binnenkomt.

Niet rechtstreeks construeren.

device#

De onderliggende Device.

rssi#

Laatst gerapporteerde RSSI, in dBm.

adv_data#

Ruwe advertising-payload (bytes of None).

resp_data#

Ruwe scan-response-payload (bytes of None), als actief scannen is ingeschakeld.

connectable#

True als de meest recente advertentie verbindbaar was.

name() str | None#

Decodeer de volledige (of verkorte) geadverteerde lokale naam uit de payload, of None indien niet aanwezig.

services() Iterator[bluetooth.UUID]#

Generator die elke bluetooth.UUID oplevert die geadverteerd wordt in de 16/32/128-bits service-list-velden.

manufacturer(filter: int | None = None) Iterator[tuple[int, bytes]]#

Generator die (company_id, data)-tuples oplevert uit manufacturer-specifieke advertising-velden.

filter

Indien opgegeven, lever alleen entries op waarvan de company-ID overeenkomt.

class aioble.Service(uuid: bluetooth.UUID)#

Een lokale GATT-service. Bouw een service met een of meer Characteristic-instanties en geef deze vervolgens door aan register_services.

uuid

De service-UUID.

uuid#

De service-UUID.

characteristics#

Lijst van Characteristic-objecten die aan deze service zijn gekoppeld.

class aioble.Characteristic(service: Service, uuid: bluetooth.UUID, read: bool = False, write: bool = False, write_no_response: bool = False, notify: bool = False, indicate: bool = False, initial: bytes | None = None, capture: bool = False)#

Een lokale GATT-characteristic. Bij het construeren ervan wordt deze automatisch aan service toegevoegd.

service

De bezittende Service.

uuid

De characteristic-UUID.

read, write, write_no_response, notify, indicate

Booleans die de ondersteunde GATT-bewerkingen selecteren.

initial

Optionele initiële waarde (bytes).

capture

Als True worden geschreven waarden in een wachtrij geplaatst (tot 10 diep) zodat snel opeenvolgende writes niet verloren gaan. Elke written-aanroep retourneert dan een (connection, data)-tuple.

uuid#

De characteristic-UUID.

flags#

Bitmasker van de GATT-property-vlaggen, opgebouwd vanuit de constructor.

descriptors#

Lijst van Descriptor-objecten die aan deze characteristic zijn gekoppeld.

read() bytes#

Lees de huidige waarde uit de lokale GATT-database.

write(data: bytes, send_update: bool = False) None#

Werk de waarde in de lokale GATT-database bij.

data

Nieuwe waardebytes.

send_update

Als True, stuur ook een notify/indicate naar elke geabonneerde verbinding.

notify(connection: DeviceConnection, data: bytes | None = None) None#

Stuur een GATT Notify naar connection.

connection

De doel-clientverbinding.

data

Payload om te versturen. Als None, wordt de huidige lokale waarde verstuurd.

indicate(connection: DeviceConnection, data: bytes | None = None, timeout_ms: int = 1000) Awaitable[None]#

Async. Stuur een GATT Indicate naar connection en wacht op de bevestiging van de client. Werpt GattError bij een status ongelijk aan nul.

connection

De doel-clientverbinding.

data

Payload om te indicaten, of None om de lokale waarde te versturen.

timeout_ms

Maximale tijd om te wachten op bevestiging.

written(timeout_ms: int | None = None) Awaitable[DeviceConnection | tuple[DeviceConnection, bytes]]#

Async. Wacht op een externe write. Retourneert de schrijvende DeviceConnection, of (connection, data) als de characteristic met capture=True is aangemaakt.

timeout_ms

Maximale wachttijd. None wacht oneindig.

on_read(connection: DeviceConnection) int#

Override-hook die synchroon wordt aangeroepen wanneer een externe read wordt ontvangen. Retourneer 0 om de read toe te staan of een ATT-foutcode ongelijk aan nul om deze te weigeren. De standaardimplementatie retourneert 0.

class aioble.BufferedCharacteristic(service: Service, uuid: bluetooth.UUID, max_len: int = 20, append: bool = False, **kwargs)#

Een Characteristic waarvan de onderliggende GATT-buffer kan worden geconfigureerd. Nuttig voor het ontvangen van waarden die groter zijn dan de standaard attribuutgrootte, of voor het in de wachtrij plaatsen van opeenvolgende writes.

max_len

Buffergrootte, in bytes.

append

Als True worden opeenvolgende writes aan de buffer toegevoegd in plaats van overschreven.

Overige argumenten worden doorgegeven aan Characteristic.

class aioble.Descriptor(characteristic: Characteristic, uuid: bluetooth.UUID, read: bool = False, write: bool = False, initial: bytes | None = None)#

Een lokale GATT-descriptor. Bij het construeren ervan wordt deze automatisch aan characteristic toegevoegd. Erft read, write en written van Characteristic.

characteristic

De bezittende Characteristic.

uuid

De descriptor-UUID.

read, write

Booleans die de ondersteunde GATT-bewerkingen selecteren.

initial

Optionele initiële waarde (bytes).

class aioble.ClientService#

Een externe GATT-service die op een peer is ontdekt. Geretourneerd door DeviceConnection.service() of geïtereerd vanuit DeviceConnection.services().

Niet rechtstreeks construeren.

connection#

De bezittende DeviceConnection.

uuid#

De externe service-UUID.

characteristic(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientCharacteristic | None]#

Async. Ontdek een enkele characteristic op UUID, of None indien niet gevonden.

characteristics(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover#

Retourneert een async iterator van ClientCharacteristic-objecten. Gebruik met async for en laat de lus tot het einde doorlopen.

uuid

Optioneel UUID-filter.

timeout_ms

Time-out per ontdekking.

class aioble.ClientCharacteristic#

Een externe GATT-characteristic die op een peer is ontdekt. Geretourneerd door ClientService.characteristic() of geïtereerd vanuit ClientService.characteristics().

Niet rechtstreeks construeren.

service#

De bezittende ClientService.

uuid#

De characteristic-UUID.

properties#

Bitmasker van ondersteunde GATT-bewerkingen zoals gerapporteerd door de peer.

read(timeout_ms: int = 1000) Awaitable[bytes]#

Async. Voer een GATT Read uit en retourneer de waarde. Werpt GattError bij een status ongelijk aan nul.

timeout_ms

Read-time-out.

write(data: bytes, response: bool | None = None, timeout_ms: int = 1000) Awaitable[None]#

Async. Voer een GATT Write uit.

data

Waarde om te schrijven.

response

True om een write-response te vereisen (en GattError te werpen bij mislukking). False voor write-without-response. None (standaard) selecteert automatisch op basis van wat de peer adverteert.

timeout_ms

Write-time-out (alleen relevant als response True is).

notified(timeout_ms: int | None = None) Awaitable[bytes]#

Async. Wacht op de volgende notification op deze characteristic en retourneer de payload ervan. Retourneert onmiddellijk als er al een notification in de wachtrij staat.

timeout_ms

Maximale wachttijd. None wacht oneindig.

indicated(timeout_ms: int | None = None) Awaitable[bytes]#

Async. Wacht op de volgende indication op deze characteristic en retourneer de payload ervan.

timeout_ms

Maximale wachttijd.

subscribe(notify: bool = True, indicate: bool = False) Awaitable[None]#

Async. Schrijf de Client Characteristic Configuration Descriptor (CCCD) om te abonneren (of afmelden) voor notifications en/of indications.

notify

Schakel notifications in.

indicate

Schakel indications in.

descriptor(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientDescriptor | None]#

Async. Ontdek een enkele descriptor op UUID, of None indien niet gevonden.

descriptors(timeout_ms: int = 2000) ClientDiscover#

Retourneert een async iterator van ClientDescriptor-objecten. Gebruik met async for en laat de lus tot het einde doorlopen.

class aioble.ClientDescriptor#

Een externe GATT-descriptor die op een peer is ontdekt. Erft read en write van ClientCharacteristic.

Niet rechtstreeks construeren.

characteristic#

De bezittende ClientCharacteristic.

uuid#

De descriptor-UUID.

class aioble.L2CAPChannel#

Een actief L2CAP connection-oriented kanaal. Geretourneerd door DeviceConnection.l2cap_accept() of DeviceConnection.l2cap_connect(). Ondersteunt gebruik als async with context manager die automatisch ontkoppelt bij het afsluiten.

Niet rechtstreeks construeren.

our_mtu#

Maximale grootte, in bytes, die de peer in een enkele SDU naar ons mag sturen.

peer_mtu#

Maximale grootte, in bytes, die wij in een enkele SDU naar de peer mogen sturen.

available() bool#

Retourneert synchroon True als er gebufferde ontvangstdata klaarstaat (d.w.z. recvinto zal niet blokkeren).

recvinto(buf: bytearray, timeout_ms: int | None = None) Awaitable[int]#

Async. Ontvang in buf en retourneer het aantal gelezen bytes. Wacht op nieuwe data als het kanaal leeg is.

buf

Vooraf toegewezen buffer om te vullen.

timeout_ms

Maximale wachttijd. None wacht oneindig.

send(buf: bytes, timeout_ms: int | None = None, chunk_size: int | None = None) Awaitable[None]#

Async. Stuur buf over het kanaal en fragmenteer grotere payloads in chunks ter grootte van de MTU. Wacht op flow-control-credits indien nodig.

buf

Bytes-achtig object om te versturen.

timeout_ms

Maximale tijd om per chunk te wachten.

chunk_size

Optionele override voor de chunkgrootte per aanroep. Begrensd tot min(our_mtu * 2, peer_mtu).

flush(timeout_ms: int | None = None) Awaitable[None]#

Async. Wacht totdat een eventueel gestokte send door de controller is afgevoerd.

timeout_ms

Maximale wachttijd.

disconnect(timeout_ms: int = 1000) Awaitable[None]#

Async. Verbreek het kanaal en wacht op de disconnection-IRQ.

timeout_ms

Maximale wachttijd.

disconnected(timeout_ms: int = 1000) Awaitable[None]#

Async. Wacht totdat het kanaal door een van beide partijen wordt verbroken.

timeout_ms

Maximale wachttijd.