aioble — BLE asynchrone¶
aioble est un encapsuleur de haut niveau compatible asyncio autour du module bluetooth. Il fournit des coroutines claires pour la recherche, la connexion, la diffusion (advertising), les services GATT et les canaux L2CAP.
Toutes les opérations distantes (connexion, déconnexion, lecture/écriture client, indication serveur, recv/send l2cap, appairage) sont awaitables et prennent en charge les délais d’expiration.
Rôles pris en charge :
Broadcaster (diffuseur) — génère les charges utiles de diffusion (advertising) et de réponse de scan pour les champs courants, répartit automatiquement la charge utile entre la diffusion et la réponse de scan, diffuse indéfiniment ou pendant une durée fixe.
Peripheral — attend une connexion provenant d’un central, attend l’échange de MTU.
Observer (scanner) — recherche passive et active, combine les charges utiles de diffusion et de réponse de scan pour le même appareil, analyse les champs courants des charges utiles de diffusion.
Central — se connecte à un périphérique, initie l’échange de MTU.
Client GATT — découvre les services / caractéristiques / descripteurs (éventuellement par UUID) ; lecture / écriture / écriture-avec-réponse sur les caractéristiques et les descripteurs ; s’abonne aux notifications et aux indications (via le CCCD) ; attend les notifications et les indications.
Serveur GATT — enregistre les services / caractéristiques / descripteurs ; attend les écritures sur les caractéristiques et les descripteurs ; intercepte les requêtes de lecture ; envoie les notifications et les indications (et attend la réponse).
L2CAP — accepte et établit des canaux L2CAP orientés connexion, gère le contrôle de flux des canaux.
Sécurité — gestion des clés/secrets appuyée sur du JSON, initiation de l’appairage, interrogation de l’état de chiffrement / d’authentification.
Exemples¶
Recherche les appareils BLE à proximité et affiche chacun d’eux dès qu’il est détecté
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())
Se connecter en tant que central à un périphérique diffusant le service Heart Rate et s’abonner à ses notifications de mesure
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())
Agir comme un peripheral : enregistrer un service GATT, le diffuser et envoyer des notifications à quiconque se connecte
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())
Fonctions au niveau du module¶
- aioble.config(*args, **kwargs) Any¶
Transmet vers
bluetooth.BLE.config(), en s’assurant d’abord que la radio BLE est active.- args
Nom de paramètre unique optionnel à interroger.
- kwargs
Arguments nommés pour définir les valeurs de configuration.
- aioble.stop() None¶
Désactive la radio BLE sous-jacente et exécute tous les gestionnaires d’arrêt de sous-module enregistrés. Après cet appel, les scanners, les diffuseurs, les connexions et les canaux L2CAP sont tous démantelés.
- aioble.scan(duration_ms: int, interval_us: int | None = None, window_us: int | None = None, active: bool = False) scan¶
Renvoie un gestionnaire de contexte asynchrone / itérateur asynchrone
scanqui produit des instancesScanResultpour chaque appareil unique découvert (ou pour chaque nouvelle donnée de diffusion provenant d’un appareil connu).- duration_ms
Durée de la recherche, en millisecondes. Passez
0pour rechercher indéfiniment jusqu’à la sortie du gestionnaire de contexte.- interval_us
Intervalle de recherche en microsecondes. Par défaut 1 280 000.
- window_us
Fenêtre de recherche en microsecondes (doit être inférieure ou égale à interval_us). Par défaut 11 250.
- active
Si
True, effectue une recherche active (demande les données de réponse de scan). Par défautFalse.
- 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 asynchrone qui commence à diffuser et attend une connexion entrante d’un central. Renvoie un
DeviceConnectionreprésentant le central connecté, ou lèveasyncio.TimeoutErroren cas de délai dépassé.- interval_us
Intervalle de diffusion, en microsecondes.
- adv_data
Charge utile de diffusion brute. Si non définie, adv_data est construite à partir des arguments nommés restants.
- resp_data
Charge utile de réponse de scan brute. Renseignée automatiquement pour absorber le débordement d”adv_data si nécessaire.
- connectable
Si
True, il s’agit d’une diffusion connectable.- limited_disc
Utiliser l’indicateur de découverte limitée au lieu de générale.
- br_edr
Définit l’indicateur de prise en charge BR/EDR.
- name
Nom local complet optionnel à intégrer.
- services
Itérable de
bluetooth.UUIDà diffuser.- appearance
Valeur d’apparence sur 16 bits (voir les numéros assignés Bluetooth).
- manufacturer
Tuple
(company_id, data_bytes)à diffuser comme données spécifiques au fabricant.- timeout_ms
Arrête la diffusion après ce nombre de millisecondes sans connexion.
Nonesignifie diffuser jusqu’à connexion.
- aioble.register_services(*services: Service) None¶
Enregistre un ou plusieurs objets
Service(ainsi que leurs caractéristiques et descripteurs) auprès du serveur GATT. Doit être appelé une fois avant de démarreradvertise. Les appels suivants remplacent l’enregistrement précédent.- services
Une ou plusieurs instances
Service.
Constantes au niveau du module¶
- aioble.ADDR_PUBLIC¶
Type d’adresse d’appareil BLE publique (
0).
- aioble.ADDR_RANDOM¶
Type d’adresse d’appareil BLE aléatoire (
1).
Exceptions¶
- exception aioble.GattError¶
Levée lorsqu’une opération GATT distante (lecture / écriture / indication) se termine avec un statut non nul. Le code de statut est disponible dans l’attribut
_status.
- exception aioble.DeviceDisconnectedError¶
Levée à l’intérieur d’une opération asynchrone (par ex. read, write, notified) lorsque la connexion sous-jacente tombe pendant l’attente.
- exception aioble.L2CAPDisconnectedError¶
Levée lorsqu’une opération send/recv/flush sur un canal L2CAP est tentée sur (ou interrompue par) un canal déconnecté.
- exception aioble.L2CAPConnectionError¶
Levée par
DeviceConnection.l2cap_connectlorsque l’établissement du canal échoue. Le code de statut Bluetooth est le premier argument.
Classes¶
- class aioble.Device(addr_type: int, addr: bytes | str)¶
Représente un appareil BLE distant par son adresse. Deux instances
Devicesont considérées égales si addr_type et addr correspondent toutes deux. Utilisé comme identifiant pour initier les connexions.- addr_type
Soit
ADDR_PUBLIC, soitADDR_RANDOM.- addr
Adresse de six octets sous forme de
bytes, ou chaîne hexadécimale séparée par des deux-points (par ex."aa:bb:cc:dd:ee:ff").
- addr_type¶
Le type d’adresse avec lequel l’appareil a été construit.
- addr¶
L’adresse brute de six octets de l’appareil.
- addr_hex() str¶
Renvoie l’adresse formatée sous forme de chaîne hexadécimale séparée par des deux-points.
- 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]¶
Asynchrone. Initie une connexion GAP vers cet appareil et renvoie le
DeviceConnectionrésultant. Annule toute recherche en cours.- timeout_ms
Durée d’attente pour que la connexion s’établisse.
- scan_duration_ms
Durée de recherche initiale avant la connexion (spécifique au contrôleur).
- min_conn_interval_us / max_conn_interval_us
Bornes optionnelles de l’intervalle de connexion, en microsecondes.
- class aioble.DeviceConnection¶
Une connexion GAP active vers un
Device. Renvoyée parDevice.connect()ouadvertise. Peut être utilisée comme gestionnaire de contexteasync withqui se déconnecte automatiquement à la sortie.Ne construisez pas directement.
- encrypted¶
Trueune fois la liaison chiffrée (par ex. après l’appairage).
- authenticated¶
Truesi la liaison a été authentifiée (appairage protégé contre les attaques MITM).
- bonded¶
Truesi l’appairage a produit des clés de liaison (bonding).
- key_size¶
Taille de la clé de chiffrement négociée en octets, ou
Falsesi non chiffrée.
- mtu¶
MTU ATT négocié après
exchange_mtu, ouNonejusqu’à ce qu’il soit défini.
- disconnect(timeout_ms: int = 2000) Awaitable[None]¶
Asynchrone. Déconnecte et attend l’IRQ de déconnexion.
- timeout_ms
Temps maximal d’attente de la déconnexion.
- disconnected(timeout_ms: int | None = None, disconnect: bool = False) Awaitable[None]¶
Asynchrone. Attend que la connexion soit terminée par l’une ou l’autre des parties. Si disconnect vaut
True, déconnecte activement au préalable.- timeout_ms
Temps maximal d’attente.
Nonesignifie attendre indéfiniment.- disconnect
Si
True, initie la déconnexion.
- timeout(timeout_ms: int | None) DeviceTimeout¶
Renvoie un gestionnaire de contexte qui annule son corps si le délai expire (en levant
asyncio.TimeoutError) ou si l’appareil se déconnecte (en levantDeviceDisconnectedError).- timeout_ms
Délai d’expiration en millisecondes, ou
Nonepour aucun délai.
- exchange_mtu(mtu: int | None = None, timeout_ms: int = 1000) Awaitable[int]¶
Asynchrone. Initie un échange de MTU ATT et renvoie le MTU négocié.
- mtu
MTU préféré optionnel à définir sur l’interface BLE sous-jacente avant l’échange.
- timeout_ms
Délai d’expiration pour l’échange.
- service(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientService | None]¶
Asynchrone. Découvre un unique service distant correspondant à uuid, ou
Nonesi introuvable.
- services(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
Renvoie un itérateur asynchrone d’objets
ClientServicedistants. À utiliser avecasync foren exécutant la boucle jusqu’à son terme.- uuid
Filtre UUID optionnel.
Nonerenvoie tous les services.- timeout_ms
Délai d’expiration par découverte.
- pair(bond: bool = True, le_secure: bool = True, mitm: bool = False, io: int = 3, timeout_ms: int = 20000) Awaitable[None]¶
Asynchrone. Initie l’appairage sur cette connexion. Met à jour les attributs
encrypted/authenticated/bonded/key_sizeune fois terminé.- bond
Conserver les clés d’appairage.
- le_secure
Utiliser LE Secure Connections.
- mitm
Exiger une protection contre les attaques de l’homme du milieu.
- io
Constante de capacité d’E/S (par ex.
3pour aucune entrée/sortie).- timeout_ms
Délai d’expiration de l’appairage.
- l2cap_accept(psm: int, mtu: int, timeout_ms: int | None = None) Awaitable[L2CAPChannel]¶
Asynchrone. Écoute sur le PSM donné et renvoie un
L2CAPChanneldès que le distant l’ouvre.- psm
Multiplexeur de protocole/service sur lequel écouter.
- mtu
Taille de réception maximale, en octets.
- timeout_ms
Temps maximal d’attente de la connexion du distant.
- l2cap_connect(psm: int, mtu: int, timeout_ms: int = 1000) Awaitable[L2CAPChannel]¶
Asynchrone. Ouvre un canal L2CAP vers le distant sur le PSM donné.
- psm
Multiplexeur de protocole/service auquel se connecter.
- mtu
Taille de réception maximale, en octets.
- timeout_ms
Délai d’expiration de la connexion.
- class aioble.ScanResult¶
Un appareil unique découvert pendant
scan. La même instance est de nouveau produite à mesure que de nouvelles données de diffusion arrivent.Ne construisez pas directement.
- rssi¶
Dernier RSSI rapporté, en dBm.
- adv_data¶
Charge utile de diffusion brute (
bytesouNone).
- resp_data¶
Charge utile de réponse de scan brute (
bytesouNone), si la recherche active est activée.
- connectable¶
Truesi la diffusion la plus récente était connectable.
- name() str | None¶
Décode le nom local diffusé complet (ou abrégé) depuis la charge utile, ou
Nones’il est absent.
- services() Iterator[bluetooth.UUID]¶
Générateur produisant chaque
bluetooth.UUIDdiffusé dans les champs de liste de services 16/32/128 bits.
- class aioble.Service(uuid: bluetooth.UUID)¶
Un service GATT local. Construisez un service avec une ou plusieurs instances
Characteristic, puis passez-le àregister_services.- uuid
L’UUID du service.
- uuid¶
L’UUID du service.
- characteristics¶
Liste des objets
Characteristicliés à ce service.
- 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)¶
Une caractéristique GATT locale. En construire une l’ajoute automatiquement à service.
- service
Le
Servicepropriétaire.- uuid
L’UUID de la caractéristique.
- read, write, write_no_response, notify, indicate
Booléens sélectionnant les opérations GATT prises en charge.
- initial
Valeur initiale optionnelle (
bytes).- capture
Si
True, les valeurs écrites sont mises en file (jusqu’à 10 de profondeur) afin que les écritures rapides successives ne soient pas perdues. Chaque appel àwrittenrenvoie alors un tuple(connection, data).
- uuid¶
L’UUID de la caractéristique.
- flags¶
Masque de bits des indicateurs de propriété GATT construit à partir du constructeur.
- descriptors¶
Liste des objets
Descriptorliés à cette caractéristique.
- write(data: bytes, send_update: bool = False) None¶
Met à jour la valeur dans la base de données GATT locale.
- data
Octets de la nouvelle valeur.
- send_update
Si
True, notifie/indique également chaque connexion abonnée.
- notify(connection: DeviceConnection, data: bytes | None = None) None¶
Envoie un GATT Notify vers connection.
- connection
La connexion client cible.
- data
Charge utile à envoyer. Si
None, la valeur locale courante est envoyée.
- indicate(connection: DeviceConnection, data: bytes | None = None, timeout_ms: int = 1000) Awaitable[None]¶
Asynchrone. Envoie un GATT Indicate vers connection et attend la confirmation du client. Lève
GattErroren cas de statut non nul.- connection
La connexion client cible.
- data
Charge utile à indiquer, ou
Nonepour envoyer la valeur locale.- timeout_ms
Temps maximal d’attente de la confirmation.
- written(timeout_ms: int | None = None) Awaitable[DeviceConnection | tuple[DeviceConnection, bytes]]¶
Asynchrone. Attend une écriture distante. Renvoie le
DeviceConnectionayant écrit, ou(connection, data)si la caractéristique a été créée aveccapture=True.- timeout_ms
Temps maximal d’attente.
Noneattend indéfiniment.
- on_read(connection: DeviceConnection) int¶
Point d’extension (hook) à surcharger, invoqué de manière synchrone à la réception d’une lecture distante. Renvoyez
0pour autoriser la lecture ou un code d’erreur ATT non nul pour la rejeter. L’implémentation par défaut renvoie0.
- class aioble.BufferedCharacteristic(service: Service, uuid: bluetooth.UUID, max_len: int = 20, append: bool = False, **kwargs)¶
Une
Characteristicdont le tampon GATT sous-jacent peut être configuré. Utile pour recevoir des valeurs plus grandes que la taille d’attribut par défaut, ou pour mettre en file des écritures successives.- max_len
Taille du tampon, en octets.
- append
Si
True, les écritures séquentielles s’ajoutent dans le tampon au lieu de l’écraser.
Les autres arguments sont transmis à
Characteristic.
- class aioble.Descriptor(characteristic: Characteristic, uuid: bluetooth.UUID, read: bool = False, write: bool = False, initial: bytes | None = None)¶
Un descripteur GATT local. En construire un l’ajoute automatiquement à characteristic. Hérite de
read,writeetwrittendeCharacteristic.- characteristic
La
Characteristicpropriétaire.- uuid
L’UUID du descripteur.
- read, write
Booléens sélectionnant les opérations GATT prises en charge.
- initial
Valeur initiale optionnelle (
bytes).
- class aioble.ClientService¶
Un service GATT distant découvert sur un pair. Renvoyé par
DeviceConnection.service()ou parcouru depuisDeviceConnection.services().Ne construisez pas directement.
- connection¶
Le
DeviceConnectionpropriétaire.
- uuid¶
L’UUID du service distant.
- characteristic(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientCharacteristic | None]¶
Asynchrone. Découvre une unique caractéristique par UUID, ou
Nonesi introuvable.
- characteristics(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
Renvoie un itérateur asynchrone d’objets
ClientCharacteristic. À utiliser avecasync foren exécutant la boucle jusqu’à son terme.- uuid
Filtre UUID optionnel.
- timeout_ms
Délai d’expiration par découverte.
- class aioble.ClientCharacteristic¶
Une caractéristique GATT distante découverte sur un pair. Renvoyée par
ClientService.characteristic()ou parcourue depuisClientService.characteristics().Ne construisez pas directement.
- service¶
Le
ClientServicepropriétaire.
- uuid¶
L’UUID de la caractéristique.
- properties¶
Masque de bits des opérations GATT prises en charge tel que rapporté par le pair.
- read(timeout_ms: int = 1000) Awaitable[bytes]¶
Asynchrone. Émet un GATT Read et renvoie la valeur. Lève
GattErroren cas de statut non nul.- timeout_ms
Délai d’expiration de lecture.
- write(data: bytes, response: bool | None = None, timeout_ms: int = 1000) Awaitable[None]¶
Asynchrone. Émet un GATT Write.
- data
Valeur à écrire.
- response
Truepour exiger une réponse d’écriture (et leverGattErroren cas d’échec).Falsepour une écriture-sans-réponse.None(par défaut) sélectionne automatiquement selon ce que le pair annonce.- timeout_ms
Délai d’expiration d’écriture (pertinent uniquement si response vaut
True).
- notified(timeout_ms: int | None = None) Awaitable[bytes]¶
Asynchrone. Attend la prochaine notification sur cette caractéristique et renvoie sa charge utile. Renvoie immédiatement si une notification est déjà en file.
- timeout_ms
Temps maximal d’attente.
Noneattend indéfiniment.
- indicated(timeout_ms: int | None = None) Awaitable[bytes]¶
Asynchrone. Attend la prochaine indication sur cette caractéristique et renvoie sa charge utile.
- timeout_ms
Temps maximal d’attente.
- subscribe(notify: bool = True, indicate: bool = False) Awaitable[None]¶
Asynchrone. Écrit le Client Characteristic Configuration Descriptor (CCCD) pour s’abonner (ou se désabonner) aux notifications et/ou aux indications.
- notify
Activer les notifications.
- indicate
Activer les indications.
- descriptor(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientDescriptor | None]¶
Asynchrone. Découvre un unique descripteur par UUID, ou
Nonesi introuvable.
- descriptors(timeout_ms: int = 2000) ClientDiscover¶
Renvoie un itérateur asynchrone d’objets
ClientDescriptor. À utiliser avecasync foren exécutant la boucle jusqu’à son terme.
- class aioble.ClientDescriptor¶
Un descripteur GATT distant découvert sur un pair. Hérite de
readetwritedeClientCharacteristic.Ne construisez pas directement.
- characteristic¶
La
ClientCharacteristicpropriétaire.
- uuid¶
L’UUID du descripteur.
- class aioble.L2CAPChannel¶
Un canal L2CAP orienté connexion actif. Renvoyé par
DeviceConnection.l2cap_accept()ouDeviceConnection.l2cap_connect(). Peut être utilisé comme gestionnaire de contexteasync withqui se déconnecte automatiquement à la sortie.Ne construisez pas directement.
- our_mtu¶
Taille maximale, en octets, que le pair peut nous envoyer dans une seule SDU.
- peer_mtu¶
Taille maximale, en octets, que nous pouvons envoyer au pair dans une seule SDU.
- available() bool¶
Renvoie de manière synchrone
Truesi des données de réception sont prêtes en tampon (c.-à-d. querecvintone bloquera pas).
- recvinto(buf: bytearray, timeout_ms: int | None = None) Awaitable[int]¶
Asynchrone. Reçoit dans buf et renvoie le nombre d’octets lus. Attend de nouvelles données si le canal est vide.
- buf
Tampon préalloué à remplir.
- timeout_ms
Temps maximal d’attente.
Noneattend indéfiniment.
- send(buf: bytes, timeout_ms: int | None = None, chunk_size: int | None = None) Awaitable[None]¶
Asynchrone. Envoie buf sur le canal, en fragmentant les charges utiles plus grandes en morceaux de la taille du MTU. Attend les crédits de contrôle de flux selon les besoins.
- buf
Objet de type bytes à envoyer.
- timeout_ms
Temps maximal d’attente par morceau.
- chunk_size
Surcharge optionnelle de la taille de morceau par appel. Plafonnée à
min(our_mtu * 2, peer_mtu).
- flush(timeout_ms: int | None = None) Awaitable[None]¶
Asynchrone. Attend que tout
sendbloqué ait été vidé par le contrôleur.- timeout_ms
Temps maximal d’attente.