-
Notifications
You must be signed in to change notification settings - Fork 348
Description
Hi, I'm using a python script to work as client and terminal to send commands to my ESP32C3 through BLE.
Bleak version: 2.0.0
Python version: 3.13
ESP32C3 bluetooth version: 5.0 (according to datasheet)
PC bluetooth dongle version: 5.1 (according to LMP in this site, despite it says it's 5.0)
When running the code it seems to connect the ESP, but then shows this message and disconnects:
Could not get GATT services: Unreachable
I believe it has some relation to the dongle bluetooth version, because of the frames 22 to 25 in these packets:
wiresharkdebug2.txt
I changed the BT dongle to one with 4.2 BT version and the script just worked fine, but I still need to make this work with my 5.1 BT dongle.
Is this some compatibility error in the library version or something else?
Here is the full python script:
import asyncio
from bleak import BleakClient
import sys
# ======================== CONFIGURAÇÕES ========================
# SEU MAC ADDRESS QUE FUNCIONOU (CRÍTICO)
DEVICE_ADDRESS = "A0:85:E3:4A:99:66"
# UUIDs (Mesmos do ESP32)
CHARACTERISTIC_RX = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" # Enviar Comandos
CHARACTERISTIC_TX = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" # Receber Telemetria
def notification_handler(characteristic, data):
"""Callback de Telemetria"""
try:
# Tenta decodificar a string vinda do ESP32
telemetry_data = data.decode('utf-8', errors='ignore').strip()
# Imprime limpando a linha para não ficar uma bagunça se digitar junto
print(f"\r[TELEMETRIA] {telemetry_data} ", end='')
except Exception:
pass
async def send_command(client: BleakClient, command: str):
"""Envia comando para o Hoverboard"""
# Adiciona \n apenas por segurança, converte para bytes
if not command.endswith(';'): command += ';' # Garante terminador
command_bytes = command.encode('utf-8')
try:
# write_gatt_char com response=False é mais rápido e trava menos
await client.write_gatt_char(CHARACTERISTIC_RX, command_bytes, response=False)
# print(f"\n[CMD ENVIADO] {command}")
except Exception as e:
print(f"\n[ERRO ENVIO] {e}")
async def run():
print(f"--- TENTANDO CONECTAR DIRETAMENTE EM {DEVICE_ADDRESS} ---")
print("Certifique-se que o ESP32-C3 está ligado.")
# Timeout de 20s para garantir
async with BleakClient(DEVICE_ADDRESS, timeout=20.0) as client:
print(f"\n>>> CONECTADO COM SUCESSO! Status: {client.is_connected}")
# O SEGREDO DO WINDOWS: PAUSA PARA RESPIRAR
print("Aguardando 3 segundos para estabilização dos serviços...")
await asyncio.sleep(3.0)
# 1. Ativa recebimento de dados
print("Ativando telemetria...")
await client.start_notify(CHARACTERISTIC_TX, notification_handler)
print("\n===================================================")
print(" CONTROLE HOVERBOARD PRONTO")
print(" Comandos: S300 (Speed), P25 (Kp), etc.")
print(" Digite 'sair' para encerrar.")
print("===================================================\n")
# Loop de comandos
while True:
# Input do usuário (bloqueante, mas ok para teste terminal)
# Usamos run_in_executor para não travar o loop de recebimento BLE
user_input = await asyncio.get_event_loop().run_in_executor(None, input, "")
if user_input.lower() == 'sair':
break
if user_input.strip():
# Formata comando simples (ex: usuario digita s300 -> envia S300;)
cmd = user_input.strip().upper()
await send_command(client, cmd)
# Pequeno delay para CPU
await asyncio.sleep(0.05)
print("\n--- Desconectado ---")
if __name__ == "__main__":
if sys.platform.lower() == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
try:
asyncio.run(run())
except KeyboardInterrupt:
print("\nEncerrado.")
except Exception as e:
print(f"\nERRO FATAL: {e}")