Python : Script minimal pour lister et lire les caractéristiques d'un périphérique BLE avec Python (Bleak)
Ce script liste les périphériques Bluetooth Low Energy (BLE) et lit leurs caractéristiques à l’aide de la bibliothèque Bleak en Python. Il s’agit d’un exemple minimal pour démontrer comment se connecter à un périphérique BLE et lire ses caractéristiques.
connect_ble_device.py
#!/usr/bin/env python3
"""
Connexion à un périphérique BLE et exploration des services
Ce script se connecte à un périphérique BLE spécifique par adresse MAC et liste
tous les services disponibles ainsi que leurs caractéristiques/attributs.
Prérequis :
- bibliothèque bleak : pip install bleak
Utilisation :
python connect_ble_device.py [ADRESSE_MAC]
Exemple :
python connect_ble_device.py 24:EC:4A:76:00:32
"""
import asyncio
import sys
import argparse
from bleak import BleakClient
from bleak.exc import BleakError
from datetime import datetime
async def explore_device_services(client, show_descriptors=False):
"""
Explorer tous les services et caractéristiques d'un périphérique BLE connecté.
Args:
client (BleakClient): Client BLE connecté
"""
try:
# Récupérer tous les services sous forme de liste
services = list(client.services)
if not services:
print("Aucun service trouvé sur ce périphérique.")
return
print(f"{len(services)} service(s) trouvé(s) :")
print("=" * 80)
for service in services:
print(f"\nService : {service.uuid}")
print(f"Description : {service.description}")
print(f"Handle : {service.handle}")
# Récupérer les caractéristiques de ce service
characteristics = service.characteristics
if characteristics:
print(f" Caractéristiques ({len(characteristics)}) :")
print(" " + "-" * 76)
for char in characteristics:
print(f" UUID : {char.uuid}")
print(f" Description : {char.description}")
print(f" Handle : {char.handle}")
print(f" Propriétés : {', '.join(char.properties)}")
# Essayer de lire la caractéristique si elle est lisible
if "read" in char.properties:
try:
value = await client.read_gatt_char(char.uuid)
# Essayer de décoder en chaîne, sinon afficher en hexadécimal
try:
decoded_value = value.decode('utf-8')
print(f" Valeur (chaîne) : {decoded_value}")
except UnicodeDecodeError:
hex_value = ' '.join(f'{b:02x}' for b in value)
print(f" Valeur (hex) : {hex_value}")
print(f" Valeur (octets bruts) : {value}")
except Exception as e:
print(f" Valeur : <Lecture impossible - {e}>")
# Afficher les descripteurs uniquement si demandé
if show_descriptors:
descriptors = char.descriptors
if descriptors:
print(f" Descripteurs ({len(descriptors)}) :")
for desc in descriptors:
print(f" UUID : {desc.uuid}")
print(f" Description : {desc.description}")
print(f" Handle : {desc.handle}")
# Essayer de lire le descripteur si possible
try:
desc_value = await client.read_gatt_descriptor(desc.handle)
try:
decoded_desc = desc_value.decode('utf-8')
print(f" Valeur (chaîne) : {decoded_desc}")
except UnicodeDecodeError:
hex_desc = ' '.join(f'{b:02x}' for b in desc_value)
print(f" Valeur (hex) : {hex_desc}")
except Exception as e:
print(f" Valeur : <Lecture impossible - {e}>")
print() # Ligne vide entre les caractéristiques
else:
print()
else:
print(" Aucune caractéristique trouvée pour ce service.")
print("-" * 80)
except Exception as e:
print(f"Erreur lors de l'exploration des services : {e}")
async def connect_and_explore(mac_address, show_descriptors=False):
"""
Se connecter à un périphérique BLE et explorer ses services.
Args:
mac_address (str): Adresse MAC du périphérique auquel se connecter
scan_time (int): Durée de recherche du périphérique
"""
print(f"\nTentative de connexion à {mac_address} ...")
try:
async with BleakClient(mac_address) as client:
if client.is_connected:
print(f"Connexion réussie à {mac_address}")
print(f"Connecté à : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
# Explorer tous les services et caractéristiques
await explore_device_services(client, show_descriptors=show_descriptors)
print(f"\nDéconnecté de {mac_address}")
return True
else:
print(f"Échec de la connexion à {mac_address}")
return False
except BleakError as e:
print(f"Erreur Bluetooth : {e}")
return False
except Exception as e:
print(f"Erreur inattendue : {e}")
return False
async def main():
"""
Fonction principale exécutant le connecteur et l'explorateur de périphérique BLE.
"""
print("Connexion à un périphérique BLE et exploration des services")
print(f"Démarré à : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
parser = argparse.ArgumentParser(description="Se connecter à un périphérique BLE et lister tous les services et attributs.")
parser.add_argument("mac_address", nargs="?", default="24:EC:4A:76:00:32", help="Adresse MAC du périphérique BLE (par défaut : 24:EC:4A:76:00:32)")
parser.add_argument("-d", "--descriptors", action="store_true", help="Afficher les descripteurs individuels pour chaque caractéristique")
args = parser.parse_args()
mac_address = args.mac_address
show_descriptors = args.descriptors
print(f"Utilisation de l'adresse MAC : {mac_address}")
if show_descriptors:
print("Affichage des descripteurs activé.")
# Valider le format de l'adresse MAC (vérification basique)
if len(mac_address.replace(":", "").replace("-", "")) != 12:
print(f"Format d'adresse MAC invalide : {mac_address}")
print("Format attendu : XX:XX:XX:XX:XX:XX ou XX-XX-XX-XX-XX-XX")
return
print()
# Se connecter et explorer le périphérique
success = await connect_and_explore(mac_address, show_descriptors=show_descriptors)
if success:
print("\nExploration du périphérique terminée avec succès.")
else:
print("\nÉchec de l'exploration du périphérique.")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\nOpération interrompue par l'utilisateur.")
except Exception as e:
print(f"Une erreur s'est produite : {e}")
sys.exit(1)If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow