[Python] Python Bluetooth unable to connect

Discussão em 'Python' iniciado por Stack, Março 3, 2025.

  1. Stack

    Stack Membro Participativo

    I am facing a problem using pybluez2 for searching via bluetooth my device. So I used bleak and find it automatically, but I am not able to connect. Why?

    I try to find my device and connect using only bleak, but it doesn't.

    Main class that manages the connectio, open, searching the device,...

    Everything is working, but not the connection with the device. s you can see in the print, the program tries many times to connect unsuccessfully.

    # Import necessary libraries for Bluetooth scanning and communication
    from bleak import BleakScanner, BleakClient
    from bleak.exc import BleakDeviceNotFoundError, BleakError

    # Import custom classes for Bluetooth communication and exceptions
    import ...bluetooth_communication.bluetooth_interface as bti
    import ...bluetooth_communication.bluetooth_exceptions as bte


    class BluetoothWrapper(bti.BluetoothInterface):
    # Constants for device connection attempts and device identification prefix
    BT_TENTATIVE: int = 3
    START_ID: str = "BM..."

    def __init__(self, mac_address: str = "", notify_characteristic: str = "", notify_callback=None):
    # Initialize instance variables
    self._mac_address: str = mac_address # MAC address of the target device
    self._id: str = "" # Device identification string
    self._devices_list: list = [] # List to hold discovered devices
    self._is_open: bool = False # Connection status
    self._client: None | BleakClient = None # Client for communicating with the device
    self.loop = asyncio.new_event_loop() # Set up the asyncio event loop
    asyncio.set_event_loop(self.loop) # Set the current event loop
    self.connection_enabled: bool = True # Flag to enable/disable connection attempts
    self.connected: bool = False # Indicates if the device is connected
    self.notify_characteristic: str = notify_characteristic # Characteristic for notifications
    self.notify_callback = notify_callback # Callback function for notifications

    def _find_ff_id(self):
    # Method to search for the target device in the discovered devices
    if not self._devices_list: # Check if devices have been discovered
    raise bte.BTNoDevices() # Raise exception if no devices found
    for ble_dev in self._devices_list: # Iterate over discovered devices
    mac_adr: str = ble_dev.address # Get MAC address of the device
    id: str = ble_dev.name if ble_dev.name else "" # Get device name (if available)
    # Check if the MAC address matches or if the device name contains the START_ID prefix
    if (mac_adr == self._mac_address) or (self.START_ID in id):
    print(f"[Device found] Adr = {mac_adr}, id = {id}") # Print found device info
    self._mac_address, self._id = mac_adr, id # Store MAC address and device ID
    return
    print(f"Devices found, but not Faast Flex:\\n{self._devices_list}") # Log devices found
    if self._mac_address: # If a MAC address was specified but not found
    raise bte.BTDeviceNoFound(self._mac_address) # Raise device not found exception
    raise bte.BTNoDevices() # Raise exception if no devices were discovered

    def discover_devices(self) -> list:
    # Method to discover Bluetooth devices
    async def run():
    return await BleakScanner.discover() # Use Bleak to scan for devices
    return self.loop.run_until_complete(run()) # Run the scanning coroutine until complete

    def on_disconnect(self, client):
    # Callback for when the device disconnects
    print("Disconnected from device") # Log disconnection
    self.connected = False # Update connection status

    async def connect_to_device(self):
    # Method to connect to the specified Bluetooth device
    while True:
    if self.connection_enabled:
    try:
    self._client = BleakClient(self._mac_address) # Create a BleakClient with the device MAC address
    await self._client.connect() # Attempt to connect to the device
    self.connected = await self._client.is_connected() # Check if connected
    if self.connected:
    print("Connected to Device") # Log successful connection
    self._client.set_disconnected_callback(self.on_disconnect) # Set the disconnect callback
    # Start notifications from the specified characteristic
    await self._client.start_notify(
    self.notify_characteristic, self.notify_callback,
    )
    while True: # Loop to keep the connection open
    if not self.connected: # Break if not connected
    break
    await asyncio.sleep(1.0) # Sleep to avoid busy waiting
    else:
    print("Failed to connect to Device") # Log failure to connect
    except Exception as e:
    print(f"Connection error: {e}") # Log any exceptions during connection
    else:
    await asyncio.sleep(1.0) # Sleep if connection is not enabled

    def _set_ff_address(self):
    # Method to determine the MAC address of the target device
    for tent in range(1, self.BT_TENTATIVE + 1): # Loop for a number of attempts
    print(f"Tentative {tent}") # Log the current attempt number
    self._devices_list = self.discover_devices() # Discover devices
    try:
    self._find_ff_id() # Attempt to find the target device
    if self._mac_address: # If the MAC address was found
    break
    except (bte.BTNoDevices, bte.BTDeviceNoFound) as err:
    print(str(err)) # Log any errors encountered

    def open(self) -> None:
    # Method to open a connection to the target device
    if self._is_open and self._client: # If connection is already open
    raise bte.BTAlreadyOpen() # Raise an exception

    self._set_ff_address() # Attempt to find and set the target device's MAC address

    # Attempt to connect to the device
    for tent in range(1, self.BT_TENTATIVE + 1):
    print(f"Tentative {tent}") # Log the current attempt
    try:
    self.loop.run_until_complete(self.connect_to_device()) # Attempt to connect
    self._is_open = True # Update connection status
    except (bte.BTNoDevices, BleakDeviceNotFoundError, BleakError) as btnd:
    self._is_open = False # Update connection status to closed
    print(str(btnd)) # Log any connection errors
    finally:
    print(f"Bluetooth is {'correctly' if self._is_open else 'not'} connected!") # Log connection status


    Errors:

    Tentative 1
    Devices found, but not Faast Flex:
    [BLEDevice(2C:C8:BA:6A:06:6B, None), BLEDevice(66:E0:97:D6:D5:B0, None), BLEDevice(01:10:65:E7:C4:87, None), BLEDevice(21:D6:03:A9:B6:7D, None), BLEDevice(DF:62:A9:65:79:A6, None), BLEDevice(2D:BF:86:53:38:FD, None), BLEDevice(1A:CC:C5:58:C0:B7, None), BLEDevice(11:3A:EB:25:8D:B6, None), BLEDevice(37:61:4A:C4:9B:0A, None), BLEDevice(37:5F:E0:20:C7:EE, None), BLEDevice(B8:A2:5D:A3:9F:91, None), BLEDevice(03:22:DB:F7:60:52, None), BLEDevice(1C:43:FB:4D:14:30, None), BLEDevice(24:4B:03:F9:9E:C1, None), BLEDevice(7C:FD:EA:99:4A:F2, None), BLEDevice(46:EA:98:12:1B:0C, None), BLEDevice(61:B1:77:A0:AB:BC, None), BLEDevice(74:45:AF:00:0F:7C, None)]
    No devices found!
    Tentative 2
    Devices found, but not Faast Flex:
    [BLEDevice(21:D6:03:A9:B6:7D, None), BLEDevice(1A:CC:C5:58:C0:B7, None), BLEDevice(2C:C8:BA:6A:06:6B, None), BLEDevice(01:10:65:E7:C4:87, None), BLEDevice(D1:68:42:77:F8:23, None), BLEDevice(1C:43:FB:4D:14:30, None), BLEDevice(0C:2F:D1:02:9A:1F, None), BLEDevice(26:3D:2E:F7:E4:22, None), BLEDevice(24:4B:03:F9:9E:C1, None), BLEDevice(11:3A:EB:25:8D:B6, None), BLEDevice(E8:52:3D:00:E6:ED, None), BLEDevice(03:22:DB:F7:60:52, None), BLEDevice(2D:BF:86:53:38:FD, None), BLEDevice(37:5F:E0:20:C7:EE, None), BLEDevice(7C:FD:EA:99:4A:F2, None), BLEDevice(1E:25:40:FA:8D:95, None), BLEDevice(66:E0:97:D6:D5:B0, None), BLEDevice(B8:A2:5D:A3:9F:91, None), BLEDevice(61:B1:77:A0:AB:BC, None)]
    No devices found!
    Tentative 3
    [Device found] Adr = 00:21:7E:BF:D2:DF, id = BMxxxx
    Tentative 1
    C:\...\lib\common\communication_protocols\bluetooth_communication\bluetooth_wrapper.py:58: FutureWarning: is_connected has been changed to a property. Calling it as an async method will be removed in a future version
    self.connected = await self._client.is_connected()
    C:\...\lib\common\communication_protocols\bluetooth_communication\bluetooth_wrapper.py:61: FutureWarning: This method will be removed future version, pass the callback to the BleakClient constructor instead.
    self._client.set_disconnected_callback(self.on_disconnect)
    Connected to Device
    Connection error: badly formed hexadecimal UUID string
    Connection error: Device with address 00:21:7E:BF:D2:DF was not found.
    Connection error: Device with address 00:21:7E:BF:D2:DF was not found.
    Connection error: Device with address 00:21:7E:BF:D2:DF was not found.
    Connection error: Device with address 00:21:7E:BF:D2:DF was not found.
    Connection error: Device with address 00:21:7E:BF:D2:DF was not found.


    Below I tried to connect to my smartphone (a motorola). Using this simple program below, I am not able to find my phone that starts with "moto":

    import asyncio
    from bleak import BleakScanner, BleakClient


    BATTERY_SERVICE_UUID = "0000180F-0000-1000-8000-00805f9b34fb"
    BATTERY_LEVEL_UUID = "00002A19-0000-1000-8000-00805f9b34fb"


    async def battery_handler(address):
    async with BleakClient(address) as client:
    battery_level = await client.read_gatt_char(BATTERY_LEVEL_UUID)
    print(f"Bactery charge: {battery_level[0]}%")


    async def main():
    selected_device = None
    while selected_device is None:
    print("\nSanning the Bluetooth devices...")
    devices = await BleakScanner.discover()
    for device in devices:
    print(f"Device found: {device.name} ({device.address})")
    if device.name and ("moto" in device.name):
    selected_device = device

    # Scegli un dispositivo a cui connettersi (puoi anche usare un input dell'utente qui)
    # selected_device = devices[0] # Ad esempio, prendi il primo dispositivo trovato
    print(f"Linking with {selected_device.name} ({selected_device.address})...")
    await battery_handler(selected_device.address)

    if __name__ == "__main__":
    asyncio.run(main())


    Is it a problem of my computer bt module? Because I used another smartphone to check if mine was available and it worked.

    Continue reading...

Compartilhe esta Página