Contenidos
Resultado de la ejecución (servicio y caracterísica)
Código
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import asyncio from bleak import BleakScanner, BleakClient async def scan_for_devices(): print("Escaneando dispositivos BLE...") devices = await BleakScanner.discover() return devices async def list_writable_characteristics(device): try: async with BleakClient(device) as client: print(f"Conectado a {device.name} ({device.address})") try: services = await client.get_services() for service in services: print(f"Servicio: {service.uuid}") for characteristic in service.characteristics: if "write" in characteristic.properties: print(f" Característica escribible: {characteristic.uuid} - Propiedades: {characteristic.properties}") except Exception as e: print(f"Error al obtener servicios: {e}") except Exception as e: print(f"Error al conectar con el dispositivo {device.name}: {e}") async def main(): devices = await scan_for_devices() if not devices: print("No se encontraron dispositivos BLE.") return for device in devices: if device.name: # Verificar que el dispositivo tenga un nombre print(f"Dispositivo encontrado: {device.name} - {device.address}") await list_writable_characteristics(device) else: print(f"Dispositivo encontrado sin nombre: {device.address}") # Ejecutar el escaneo y listar características escribibles asyncio.run(main()) |
Explicación detallada de cada parte del código
Importaciones
import asyncio
from bleak import BleakScanner, BleakClient
import asyncio
: Importa el móduloasyncio
, que es una biblioteca estándar en Python para escribir código concurrente utilizando corutinas y eventos. Permite la ejecución de operaciones asincrónicas de manera eficiente.from bleak import BleakScanner, BleakClient
: Importa las clasesBleakScanner
yBleakClient
del paquetebleak
. Estas clases permiten escanear dispositivos Bluetooth Low Energy (BLE) y conectarse a ellos, respectivamente.
Función para escanear dispositivos
async def scan_for_devices():
print("Escaneando dispositivos BLE...")
devices = await BleakScanner.discover()
return devices
async def scan_for_devices()
: Define una corutina asincrónica llamadascan_for_devices
. Las corutinas son funciones que pueden ser pausadas y reanudadas, permitiendo operaciones asincrónicas.print("Escaneando dispositivos BLE...")
: Imprime un mensaje en la consola para indicar que se está iniciando el escaneo de dispositivos BLE.devices = await BleakScanner.discover()
: Llama aBleakScanner.discover()
, que es una función asincrónica que realiza el escaneo y devuelve una lista de dispositivos BLE encontrados.await
se usa para esperar a que esta operación termine antes de continuar.return devices
: Devuelve la lista de dispositivos BLE encontrados.
Función para listar características escribibles
async def list_writable_characteristics(device):
try:
async with BleakClient(device) as client:
print(f"Conectado a {device.name} ({device.address})")
try:
services = await client.get_services()
for service in services:
print(f"Servicio: {service.uuid}")
for characteristic in service.characteristics:
if "write" in characteristic.properties:
print(f" Característica escribible: {characteristic.uuid} - Propiedades: {characteristic.properties}")
except Exception as e:
print(f"Error al obtener servicios: {e}")
except Exception as e:
print(f"Error al conectar con el dispositivo {device.name}: {e}")
async def list_writable_characteristics(device)
: Define una corutina asincrónica para conectar a un dispositivo BLE y listar sus características escribibles.try
: Inicia un bloquetry
para manejar posibles excepciones que puedan surgir durante la conexión y obtención de servicios.async with BleakClient(device) as client
: UsaBleakClient
para conectar al dispositivo BLE especificado.async with
asegura que la conexión se maneje correctamente y se cierre al final del bloque.print(f"Conectado a {device.name} ({device.address})")
: Imprime un mensaje indicando que se ha conectado exitosamente al dispositivo, mostrando su nombre y dirección.services = await client.get_services()
: Obtiene los servicios del dispositivo BLE de manera asincrónica.await
espera a que la operación termine.for service in services:
: Itera sobre cada servicio disponible en el dispositivo.print(f"Servicio: {service.uuid}")
: Imprime el UUID del servicio.for characteristic in service.characteristics:
: Itera sobre cada característica del servicio.if "write" in characteristic.properties:
: Verifica si la característica tiene la propiedad «write», indicando que es escribible.print(f" Característica escribible: {characteristic.uuid} - Propiedades: {characteristic.properties}")
: Imprime el UUID y las propiedades de la característica escribible.
except Exception as e
: Maneja cualquier excepción que pueda ocurrir durante la conexión o la obtención de servicios.print(f"Error al obtener servicios: {e}")
: Imprime un mensaje de error si no se pueden obtener los servicios.
except Exception as e
: Maneja cualquier excepción que pueda ocurrir durante la conexión al dispositivo.print(f"Error al conectar con el dispositivo {device.name}: {e}")
: Imprime un mensaje de error si no se puede conectar al dispositivo.
Función principal
async def main():
devices = await scan_for_devices()
if not devices:
print("No se encontraron dispositivos BLE.")
return
for device in devices:
if device.name: # Verificar que el dispositivo tenga un nombre
print(f"Dispositivo encontrado: {device.name} - {device.address}")
await list_writable_characteristics(device)
else:
print(f"Dispositivo encontrado sin nombre: {device.address}")
async def main()
: Define la corutina principalmain
, que coordina el escaneo de dispositivos y la lista de características escribibles.devices = await scan_for_devices()
: Llama a la corutinascan_for_devices
para obtener la lista de dispositivos BLE cercanos.if not devices:
: Verifica si no se encontraron dispositivos.print("No se encontraron dispositivos BLE.")
: Imprime un mensaje si la lista de dispositivos está vacía.return
: Sale de la corutinamain
si no hay dispositivos.
for device in devices:
: Itera sobre cada dispositivo encontrado.if device.name:
: Verifica si el dispositivo tiene un nombre.print(f"Dispositivo encontrado: {device.name} - {device.address}")
: Imprime el nombre y la dirección del dispositivo.await list_writable_characteristics(device)
: Llama a la corutinalist_writable_characteristics
para listar las características escribibles del dispositivo.
else:
: Si el dispositivo no tiene nombre.print(f"Dispositivo encontrado sin nombre: {device.address}")
: Imprime la dirección del dispositivo sin nombre.
Ejecución del programa
asyncio.run(main())
asyncio.run(main())
: Ejecuta la corutina principalmain
utilizando el bucle de eventos deasyncio
. Este método configura el entorno necesario para que las corutinas se ejecuten y se encargue de la ejecución y finalización del bucle de eventos.
Ejemplo de servicio y característica configurado en una aplicación para iPhone (Swift)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
func setupPeripheral() { guard let peripheralManager = peripheralManager else { print("Error: peripheralManager no está disponible.") return } let characteristicUUID = CBUUID(string: "8667556c-9a37-4c91-84ed-54ee27d90049") transferCharacteristic = CBMutableCharacteristic( type: characteristicUUID, properties: [.write, .notify], value: nil, permissions: [.writeable] ) let serviceUUID = CBUUID(string: "d0611e78-bbb4-4591-a5f8-487910ae4366") let transferService = CBMutableService(type: serviceUUID, primary: true) transferService.characteristics = [transferCharacteristic!] peripheralManager.add(transferService) peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [serviceUUID]]) print("Anunciando el servicio con UUID: \(serviceUUID)") } |