aioble — BLE asincrono¶
aioble è un wrapper di alto livello, compatibile con asyncio, attorno al modulo bluetooth. Fornisce coroutine pulite per la scansione, la connessione, l’advertising, i servizi GATT e i canali L2CAP.
Tutte le operazioni remote (connect, disconnect, lettura/scrittura del client, indicate del server, recv/send L2CAP, pair) sono awaitable e supportano i timeout.
Ruoli supportati:
Broadcaster (advertiser) — genera i payload di advertising e di scan-response per i campi più comuni, suddivide automaticamente il payload tra advertising e scan response, esegue l’advertising indefinitamente o per una durata fissa.
Peripheral — attende una connessione da un central, attende lo scambio MTU.
Observer (scanner) — scansione passiva e attiva, combina i payload di advertising e di scan-response dello stesso dispositivo, analizza i campi più comuni dai payload di advertising.
Central — si connette a un peripheral, avvia lo scambio MTU.
GATT Client — individua servizi / caratteristiche / descrittori (opzionalmente per UUID); legge / scrive / scrive-con-risposta su caratteristiche e descrittori; si iscrive a notifiche e indicazioni (tramite il CCCD); attende notifiche e indicazioni.
GATT Server — registra servizi / caratteristiche / descrittori; attende scritture su caratteristiche e descrittori; intercetta le richieste di lettura; invia notifiche e indicazioni (e attende la risposta).
L2CAP — accetta e connette canali L2CAP orientati alla connessione, gestisce il controllo di flusso del canale.
Security — gestione di chiavi/segreti basata su JSON, avvio del pairing, interrogazione dello stato di cifratura / autenticazione.
Esempi¶
Scansiona i dispositivi BLE nelle vicinanze e stampa ciascuno man mano che viene rilevato:
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())
Connettiti come central a un peripheral che esegue l’advertising del servizio Heart Rate e iscriviti alle sue notifiche di misurazione:
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())
Agisci come peripheral: registra un servizio GATT, eseguine l’advertising e invia notifiche a chiunque si connetta:
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())
Funzioni a livello di modulo¶
- aioble.config(*args, **kwargs) Any¶
Inoltra a
bluetooth.BLE.config(), assicurandosi prima che la radio BLE sia attiva.- args
Nome di un singolo parametro opzionale da interrogare.
- kwargs
Argomenti keyword per impostare i valori di configurazione.
- aioble.stop() None¶
Disattiva la radio BLE sottostante ed esegue gli eventuali handler di spegnimento dei sotto-moduli registrati. Dopo questa chiamata, scanner, advertiser, connessioni e canali L2CAP vengono tutti chiusi.
- aioble.scan(duration_ms: int, interval_us: int | None = None, window_us: int | None = None, active: bool = False) scan¶
Restituisce un context-manager / iteratore asincrono
scanche produce istanze diScanResultper ogni dispositivo univoco rilevato (o per ogni nuovo dato di advertising proveniente da un dispositivo noto).- duration_ms
Durata della scansione, in millisecondi. Passa
0per eseguire la scansione indefinitamente fino all’uscita dal context manager.- interval_us
Intervallo di scansione in microsecondi. Il valore predefinito è 1.280.000.
- window_us
Finestra di scansione in microsecondi (deve essere minore o uguale a interval_us). Il valore predefinito è 11.250.
- active
Se
True, esegue una scansione attiva (richiede i dati di scan response). Il valore predefinito è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¶
Coroutine asincrona che avvia l’advertising e attende una connessione in arrivo da un central. Restituisce un
DeviceConnectionche rappresenta il central connesso, oppure sollevaasyncio.TimeoutErrorin caso di timeout.- interval_us
Intervallo di advertising, in microsecondi.
- adv_data
Payload di advertising grezzo. Se non impostato, adv_data viene costruito a partire dai restanti argomenti keyword.
- resp_data
Payload di scan response grezzo. Popolato automaticamente con i dati eccedenti di adv_data, se necessario.
- connectable
Se
True, si tratta di un advertisement connettibile.- limited_disc
Usa il flag limited-discoverable invece di quello generale.
- br_edr
Imposta il flag BR/EDR-supported.
- name
Nome locale completo opzionale da incorporare.
- services
Iterabile di
bluetooth.UUIDdi cui eseguire l’advertising.- appearance
Valore appearance a 16 bit (vedi i Bluetooth assigned numbers).
- manufacturer
Tupla
(company_id, data_bytes)da pubblicizzare come dati specifici del produttore.- timeout_ms
Interrompe l’advertising dopo questo numero di millisecondi senza una connessione.
Nonesignifica eseguire l’advertising finché non si è connessi.
- aioble.register_services(*services: Service) None¶
Registra uno o più oggetti
Service(e le relative caratteristiche e descrittori) presso il server GATT. Deve essere chiamato una volta prima di avviareadvertise. Le chiamate successive sostituiscono la registrazione precedente.- services
Una o più istanze di
Service.
Costanti a livello di modulo¶
- aioble.ADDR_PUBLIC¶
Tipo di indirizzo del dispositivo BLE pubblico (
0).
- aioble.ADDR_RANDOM¶
Tipo di indirizzo del dispositivo BLE casuale (
1).
Eccezioni¶
- exception aioble.GattError¶
Sollevata quando un’operazione GATT remota (read / write / indicate) si completa con uno stato diverso da zero. Il codice di stato è disponibile nell’attributo
_status.
- exception aioble.DeviceDisconnectedError¶
Sollevata all’interno di un’operazione asincrona (ad esempio read, write, notified) quando la connessione sottostante cade durante l’attesa.
- exception aioble.L2CAPDisconnectedError¶
Sollevata quando si tenta un’operazione di send/recv/flush su un canale L2CAP disconnesso (o quando viene interrotta da esso).
- exception aioble.L2CAPConnectionError¶
Sollevata da
DeviceConnection.l2cap_connectquando la creazione del canale fallisce. Il codice di stato Bluetooth è il primo argomento.
Classi¶
- class aioble.Device(addr_type: int, addr: bytes | str)¶
Rappresenta un dispositivo BLE remoto tramite indirizzo. Due istanze di
Devicerisultano uguali se corrispondono sia addr_type sia addr. Usata come handle per avviare le connessioni.- addr_type
ADDR_PUBLICoppureADDR_RANDOM.- addr
Indirizzo a sei byte come
bytes, oppure una stringa esadecimale separata da due punti (ad esempio"aa:bb:cc:dd:ee:ff").
- addr_type¶
Il tipo di indirizzo con cui è stato costruito il dispositivo.
- addr¶
L’indirizzo grezzo del dispositivo a sei byte.
- 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]¶
Asincrona. Avvia una connessione GAP verso questo dispositivo e restituisce il
DeviceConnectionrisultante. Annulla qualsiasi scansione in corso.- timeout_ms
Quanto attendere il completamento della connessione.
- scan_duration_ms
Durata della scansione iniziale prima della connessione (specifica del controller).
- min_conn_interval_us / max_conn_interval_us
Limiti opzionali dell’intervallo di connessione, in microsecondi.
- class aioble.DeviceConnection¶
Una connessione GAP attiva verso un
Device. Restituita daDevice.connect()o daadvertise. Supporta l’uso come context managerasync withche si disconnette automaticamente all’uscita.Non costruire direttamente.
- encrypted¶
Truequando il collegamento è cifrato (ad esempio dopo il pairing).
- authenticated¶
Truese il collegamento è stato autenticato (pairing protetto da MITM).
- bonded¶
Truese il pairing ha prodotto chiavi di bonding.
- key_size¶
Dimensione della chiave di cifratura negoziata in byte, oppure
Falsese non cifrato.
- mtu¶
MTU ATT negoziato dopo
exchange_mtu, oppureNonefinché non è impostato.
- disconnect(timeout_ms: int = 2000) Awaitable[None]¶
Asincrona. Disconnette e attende l’IRQ di disconnessione.
- timeout_ms
Tempo massimo di attesa per la disconnessione.
- disconnected(timeout_ms: int | None = None, disconnect: bool = False) Awaitable[None]¶
Asincrona. Attende che la connessione venga terminata da una delle due parti. Se disconnect è
True, esegue prima attivamente la disconnessione.- timeout_ms
Tempo massimo di attesa.
Nonesignifica attendere indefinitamente.- disconnect
Se
True, avvia la disconnessione.
- timeout(timeout_ms: int | None) DeviceTimeout¶
Restituisce un context manager che annulla il proprio corpo se trascorre il timeout (sollevando
asyncio.TimeoutError) oppure se il dispositivo si disconnette (sollevandoDeviceDisconnectedError).- timeout_ms
Timeout in millisecondi, oppure
Noneper nessun timeout.
- exchange_mtu(mtu: int | None = None, timeout_ms: int = 1000) Awaitable[int]¶
Asincrona. Avvia uno scambio MTU ATT e restituisce l’MTU negoziato.
- mtu
MTU preferito opzionale da impostare sull’interfaccia BLE sottostante prima dello scambio.
- timeout_ms
Timeout per lo scambio.
- service(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientService | None]¶
Asincrona. Individua un singolo servizio remoto corrispondente a uuid, oppure
Nonese non trovato.
- services(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
Restituisce un iteratore asincrono di oggetti
ClientServiceremoti. Usalo conasync fored esegui il ciclo fino al completamento.- uuid
Filtro UUID opzionale.
Nonerestituisce ogni servizio.- timeout_ms
Timeout per ogni discovery.
- pair(bond: bool = True, le_secure: bool = True, mitm: bool = False, io: int = 3, timeout_ms: int = 20000) Awaitable[None]¶
Asincrona. Avvia il pairing su questa connessione. Aggiorna gli attributi
encrypted/authenticated/bonded/key_sizeal completamento.- bond
Mantiene in modo persistente le chiavi di pairing.
- le_secure
Usa LE Secure Connections.
- mitm
Richiede la protezione man-in-the-middle.
- io
Costante della capacità di IO (ad esempio
3per nessun input/output).- timeout_ms
Timeout del pairing.
- l2cap_accept(psm: int, mtu: int, timeout_ms: int | None = None) Awaitable[L2CAPChannel]¶
Asincrona. Si mette in ascolto sul PSM specificato e restituisce un
L2CAPChannelnon appena il remoto lo apre.- psm
Protocol/Service Multiplexer su cui ascoltare.
- mtu
Dimensione massima di ricezione, in byte.
- timeout_ms
Tempo massimo di attesa per la connessione del remoto.
- l2cap_connect(psm: int, mtu: int, timeout_ms: int = 1000) Awaitable[L2CAPChannel]¶
Asincrona. Apre un canale L2CAP verso il remoto sul PSM specificato.
- psm
Protocol/Service Multiplexer a cui connettersi.
- mtu
Dimensione massima di ricezione, in byte.
- timeout_ms
Timeout di connessione.
- class aioble.ScanResult¶
Un singolo dispositivo rilevato durante
scan. La stessa istanza viene riprodotta man mano che arrivano nuovi dati di advertising.Non costruire direttamente.
- rssi¶
Ultimo RSSI riportato, in dBm.
- adv_data¶
Payload di advertising grezzo (
bytesoppureNone).
- resp_data¶
Payload di scan response grezzo (
bytesoppureNone), se la scansione attiva è abilitata.
- connectable¶
Truese l’advertisement più recente era connettibile.
- name() str | None¶
Decodifica il nome locale pubblicizzato completo (o abbreviato) dal payload, oppure
Nonese assente.
- services() Iterator[bluetooth.UUID]¶
Generatore che produce ogni
bluetooth.UUIDpubblicizzato nei campi service-list a 16/32/128 bit.
- class aioble.Service(uuid: bluetooth.UUID)¶
Un servizio GATT locale. Costruisci un servizio con una o più istanze di
Characteristic, quindi passalo aregister_services.- uuid
L’UUID del servizio.
- uuid¶
L’UUID del servizio.
- characteristics¶
Elenco di oggetti
Characteristicassociati a questo servizio.
- 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)¶
Una caratteristica GATT locale. La sua costruzione la aggiunge automaticamente a service.
- service
Il
Serviceproprietario.- uuid
L’UUID della caratteristica.
- read, write, write_no_response, notify, indicate
Booleani che selezionano le operazioni GATT supportate.
- initial
Valore iniziale opzionale (
bytes).- capture
Se
True, i valori scritti vengono accodati (fino a 10 in profondità) in modo che scritture rapide consecutive non vadano perse. Ogni chiamata awrittenrestituisce quindi una tupla(connection, data).
- uuid¶
L’UUID della caratteristica.
- flags¶
Bitmask dei flag di proprietà GATT costruita a partire dal costruttore.
- descriptors¶
Elenco di oggetti
Descriptorassociati a questa caratteristica.
- write(data: bytes, send_update: bool = False) None¶
Aggiorna il valore nel database GATT locale.
- data
Nuovi byte di valore.
- send_update
Se
True, notifica/indica anche a ogni connessione iscritta.
- notify(connection: DeviceConnection, data: bytes | None = None) None¶
Invia un GATT Notify a connection.
- connection
La connessione client di destinazione.
- data
Payload da inviare. Se
None, viene inviato il valore locale corrente.
- indicate(connection: DeviceConnection, data: bytes | None = None, timeout_ms: int = 1000) Awaitable[None]¶
Asincrona. Invia un GATT Indicate a connection e attende la conferma del client. Solleva
GattErrorin caso di stato diverso da zero.- connection
La connessione client di destinazione.
- data
Payload da indicare, oppure
Noneper inviare il valore locale.- timeout_ms
Tempo massimo di attesa per la conferma.
- written(timeout_ms: int | None = None) Awaitable[DeviceConnection | tuple[DeviceConnection, bytes]]¶
Asincrona. Attende una scrittura remota. Restituisce il
DeviceConnectionche scrive, oppure(connection, data)se la caratteristica è stata creata concapture=True.- timeout_ms
Tempo massimo di attesa.
Noneattende indefinitamente.
- on_read(connection: DeviceConnection) int¶
Hook di override invocato in modo sincrono quando viene ricevuta una lettura remota. Restituisce
0per consentire la lettura oppure un codice di errore ATT diverso da zero per rifiutarla. L’implementazione predefinita restituisce0.
- class aioble.BufferedCharacteristic(service: Service, uuid: bluetooth.UUID, max_len: int = 20, append: bool = False, **kwargs)¶
Una
Characteristicil cui buffer GATT di supporto può essere configurato. Utile per ricevere valori più grandi della dimensione predefinita dell’attributo, o per accodare scritture consecutive.- max_len
Dimensione del buffer, in byte.
- append
Se
True, le scritture sequenziali vengono accodate nel buffer invece di sovrascriverlo.
Gli altri argomenti vengono inoltrati a
Characteristic.
- class aioble.Descriptor(characteristic: Characteristic, uuid: bluetooth.UUID, read: bool = False, write: bool = False, initial: bytes | None = None)¶
Un descrittore GATT locale. La sua costruzione lo aggiunge automaticamente a characteristic. Eredita
read,writeewrittendaCharacteristic.- characteristic
La
Characteristicproprietaria.- uuid
L’UUID del descrittore.
- read, write
Booleani che selezionano le operazioni GATT supportate.
- initial
Valore iniziale opzionale (
bytes).
- class aioble.ClientService¶
Un servizio GATT remoto individuato su un peer. Restituito da
DeviceConnection.service()o iterato daDeviceConnection.services().Non costruire direttamente.
- connection¶
Il
DeviceConnectionproprietario.
- uuid¶
L’UUID del servizio remoto.
- characteristic(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientCharacteristic | None]¶
Asincrona. Individua una singola caratteristica per UUID, oppure
Nonese non trovata.
- characteristics(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
Restituisce un iteratore asincrono di oggetti
ClientCharacteristic. Usalo conasync fored esegui il ciclo fino al completamento.- uuid
Filtro UUID opzionale.
- timeout_ms
Timeout per ogni discovery.
- class aioble.ClientCharacteristic¶
Una caratteristica GATT remota individuata su un peer. Restituita da
ClientService.characteristic()o iterata daClientService.characteristics().Non costruire direttamente.
- service¶
Il
ClientServiceproprietario.
- uuid¶
L’UUID della caratteristica.
- properties¶
Bitmask delle operazioni GATT supportate come riportato dal peer.
- read(timeout_ms: int = 1000) Awaitable[bytes]¶
Asincrona. Emette un GATT Read e restituisce il valore. Solleva
GattErrorin caso di stato diverso da zero.- timeout_ms
Timeout di lettura.
- write(data: bytes, response: bool | None = None, timeout_ms: int = 1000) Awaitable[None]¶
Asincrona. Emette un GATT Write.
- data
Valore da scrivere.
- response
Trueper richiedere una write-response (e sollevareGattErrorin caso di errore).Falseper la write-without-response.None(predefinito) seleziona automaticamente in base a ciò che il peer pubblicizza.- timeout_ms
Timeout di scrittura (rilevante solo se response è
True).
- notified(timeout_ms: int | None = None) Awaitable[bytes]¶
Asincrona. Attende la prossima notifica su questa caratteristica e ne restituisce il payload. Restituisce immediatamente se una notifica è già in coda.
- timeout_ms
Tempo massimo di attesa.
Noneattende indefinitamente.
- indicated(timeout_ms: int | None = None) Awaitable[bytes]¶
Asincrona. Attende la prossima indicazione su questa caratteristica e ne restituisce il payload.
- timeout_ms
Tempo massimo di attesa.
- subscribe(notify: bool = True, indicate: bool = False) Awaitable[None]¶
Asincrona. Scrive il Client Characteristic Configuration Descriptor (CCCD) per iscriversi (o disiscriversi) a notifiche e/o indicazioni.
- notify
Abilita le notifiche.
- indicate
Abilita le indicazioni.
- descriptor(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientDescriptor | None]¶
Asincrona. Individua un singolo descrittore per UUID, oppure
Nonese non trovato.
- descriptors(timeout_ms: int = 2000) ClientDiscover¶
Restituisce un iteratore asincrono di oggetti
ClientDescriptor. Usalo conasync fored esegui il ciclo fino al completamento.
- class aioble.ClientDescriptor¶
Un descrittore GATT remoto individuato su un peer. Eredita
readewritedaClientCharacteristic.Non costruire direttamente.
- characteristic¶
La
ClientCharacteristicproprietaria.
- uuid¶
L’UUID del descrittore.
- class aioble.L2CAPChannel¶
Un canale L2CAP attivo orientato alla connessione. Restituito da
DeviceConnection.l2cap_accept()oDeviceConnection.l2cap_connect(). Supporta l’uso come context managerasync withche si disconnette automaticamente all’uscita.Non costruire direttamente.
- our_mtu¶
Dimensione massima, in byte, che il peer può inviarci in una singola SDU.
- peer_mtu¶
Dimensione massima, in byte, che possiamo inviare al peer in una singola SDU.
- available() bool¶
Restituisce in modo sincrono
Truese i dati di ricezione bufferizzati sono pronti (cioèrecvintonon si bloccherà).
- recvinto(buf: bytearray, timeout_ms: int | None = None) Awaitable[int]¶
Asincrona. Riceve in buf, restituendo il numero di byte letti. Attende nuovi dati se il canale è vuoto.
- buf
Buffer pre-allocato da riempire.
- timeout_ms
Tempo massimo di attesa.
Noneattende indefinitamente.
- send(buf: bytes, timeout_ms: int | None = None, chunk_size: int | None = None) Awaitable[None]¶
Asincrona. Invia buf sul canale, frammentando i payload più grandi in blocchi di dimensione MTU. Attende i credit di controllo di flusso secondo necessità.
- buf
Oggetto bytes-like da inviare.
- timeout_ms
Tempo massimo di attesa per ogni blocco.
- chunk_size
Override opzionale per la dimensione del blocco per ogni chiamata. Limitato a
min(our_mtu * 2, peer_mtu).
- flush(timeout_ms: int | None = None) Awaitable[None]¶
Asincrona. Attende finché un eventuale
sendin stallo non è stato svuotato dal controller.- timeout_ms
Tempo massimo di attesa.