bleak icon indicating copy to clipboard operation
bleak copied to clipboard

Fail to connect to paired device

Open SimonJonsson1999 opened this issue 7 months ago • 1 comments

Problem: Connecting to a device that is already paired and is private advertising.

python version: 3.11.0 bleak version: 0.22.3 Windows 10

It works fine to connect to the device, pair, and then read from a characteristic that needs a bonding. If i un-pair and disconnects, there is no problem for me to connect again. Here is some sample code.

ble_device = BLEAKDeviceManager()
await ble_device.initilize()
await ble_device.pair()
await asyncio.sleep(2.0)
try:
    raw_data = await ble_device.read_from_characteristic(BATTERY_LEVEL)
    battery_level = parse_battery_data(raw_data)
    print(battery_level)
except Exception as e:
    print(f"Could not read battery level: {e}")

await ble_device.un_pair()
await ble_device.disconnect()

where the initilize basically looks like this:

target_address = "XX:XX:XX:XX"
self.client = BleakClient(device, winrt=dict(use_cached_services=True, address_type="public"), pair=False)
await self.client.connect(winrt=dict(use_cached_services=True))
CHAR_UUID = "00002a00-0000-1000-8000-00805f9b34fb"
            char = self.client.services.get_characteristic(CHAR_UUID)
            async with asyncio.timeout(10):
                while char.max_write_without_response_size == 20:
                    print(char.max_write_without_response_size)
                    await asyncio.sleep(0.5)

And as I said, this works fine, here are the logs:

DEBUG:bleak.backends.winrt.client:Connecting to BLE device @ 70:54:64:D7:C5:86
DEBUG:bleak.backends.winrt.scanner:Received 68:AE:87:11:00:CF: .
DEBUG:bleak.backends.winrt.scanner:49 devices found. Watcher status: <BluetoothLEAdvertisementWatcherStatus.STOPPED: 3>.
DEBUG:bleak.backends.winrt.client:getting services (service_cache_mode=<BluetoothCacheMode.CACHED: 0>, cache_mode=<BluetoothCacheMode.CACHED: 0>)...
DEBUG:bleak.backends.winrt.client:session_status_changed_event_handler: id: BluetoothLE#BluetoothLE68:c6:ac:54:96:23-70:54:64:d7:c5:86, error: <BluetoothError.SUCCESS: 0>,
status: <GattSessionStatus.ACTIVE: 1>
DEBUG:bleak.backends.winrt.client:max_pdu_size_changed_handler: 247
DEBUG:bleak.backends.winrt.client:70:54:64:D7:C5:86: services changed
DEBUG:bleak.backends.winrt.client:70:54:64:D7:C5:86: services changed
DEBUG:bleak.backends.winrt.client:70:54:64:D7:C5:86: services changed
DEBUG:bleak.backends.winrt.client:70:54:64:D7:C5:86: services changed
DEBUG:bleak.backends.winrt.client:70:54:64:D7:C5:86: services changed
DEBUG:bleak.backends.winrt.client:70:54:64:D7:C5:86: services changed
Connected to target
INFO:bleak.backends.winrt.client:Paired to device with protection level <DevicePairingProtectionLevel.ENCRYPTION: 2>.
Successfully paired
Paired with client
DEBUG:bleak.backends.winrt.client:Read Characteristic 001C : bytearray(b'\x00')
0
0
DEBUG:bleak.backends.winrt.client:session_status_changed_event_handler: id: BluetoothLE#BluetoothLE68:c6:ac:54:96:23-70:54:64:d7:c5:86, error: <BluetoothError.SUCCESS: 0>,
status: <GattSessionStatus.CLOSED: 0>
DEBUG:bleak.backends.winrt.client:max_pdu_size_changed_handler: 23
DEBUG:bleak.backends.winrt.client:closing requester
DEBUG:bleak.backends.winrt.client:closing session
INFO:bleak.backends.winrt.client:Unpaired with device.
un-paired with client
DEBUG:bleak.backends.winrt.client:Disconnecting from BLE device...
Disconnected device

successfull_log.pcapng.gz

Now to my problem. I try to run the same code but remove the un-pairing, since i want to find the device when it is private advertising and be able to connect to it.

ble_device = BLEAKDeviceManager()
await ble_device.initilize()
await ble_device.pair()
await asyncio.sleep(2.0)
try:
    raw_data = await ble_device.read_from_characteristic(BATTERY_LEVEL)
    battery_level = parse_battery_data(raw_data)
    print(battery_level)
except Exception as e:
    print(f"Could not read battery level: {e}")

#await ble_device.un_pair()
await ble_device.disconnect()

It works and the device is still paired, but when i try to connect to it now i get the following error (I tried with and without setting pair=True to the BleakClient):

DEBUG:bleak.backends.winrt.client:Connecting to BLE device @ 70:54:64:D7:C5:86
DEBUG:bleak.backends.winrt.client:getting services (service_cache_mode=<BluetoothCacheMode.CACHED: 0>, cache_mode=<BluetoothCacheMode.CACHED: 0>)...
DEBUG:bleak.backends.winrt.client:session_status_changed_event_handler: id: BluetoothLE#BluetoothLE68:c6:ac:54:96:23-70:54:64:d7:c5:86, error: <BluetoothError.SUCCESS: 0>,
status: <GattSessionStatus.ACTIVE: 1>
Connected to target
20
DEBUG:bleak.backends.winrt.client:session_status_changed_event_handler: id: BluetoothLE#BluetoothLE68:c6:ac:54:96:23-70:54:64:d7:c5:86, error: <BluetoothError.SUCCESS: 0>,
status: <GattSessionStatus.CLOSED: 0>
DEBUG:bleak.backends.winrt.client:closing requester
DEBUG:bleak.backends.winrt.client:closing session
Traceback (most recent call last):
  File "C:\Users\8957\Documents\shuri-tools\ble_test\BLEDeviceManager\BLEAKDeviceManager.py", line 181, in <module>
    asyncio.run(main())
  File "C:\Users\8957\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\8957\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\8957\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 650, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\Users\8957\Documents\shuri-tools\ble_test\BLEDeviceManager\BLEAKDeviceManager.py", line 165, in main
    await ble_device.initilize()
  File "C:\Users\8957\Documents\shuri-tools\ble_test\BLEDeviceManager\BLEAKDeviceManager.py", line 17, in initilize
    await self._connect(target_device)
  File "C:\Users\8957\Documents\shuri-tools\ble_test\BLEDeviceManager\BLEAKDeviceManager.py", line 119, in _connect
    while char.max_write_without_response_size == 20:
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\8957\Documents\tests\venv\Lib\site-packages\bleak\backends\characteristic.py", line 112, in max_write_without_response_size
    return self._max_write_without_response_size()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\8957\Documents\tests\venv\Lib\site-packages\bleak\backends\winrt\client.py", line 770, in <lambda>
    characteristic, lambda: self._session.max_pdu_size - 3
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'max_pdu_size'

unsuccesfull_log.pcapng.gz

I am not sure if the problem is how i use Bleak, or my peripheral device.

SimonJonsson1999 avatar May 27 '25 07:05 SimonJonsson1999

From what I can see in the logs, in the unsuccessful attempt, the connection is actually successful, but as soon as Windows tries to enable encryption, the device disconnects.

Image

So I'm not sure what Bleak could do about this. We don't manage the encryption. That is all handled automatically by Windows. My guess most likely, the device is doing it wrong (e.g. isn't storing the encryption keys) and disconnects because it got an unexpected request from Windows. Or, if this same Bleak program works on other OSes, maybe Windows is doing something wrong.

dlech avatar May 29 '25 01:05 dlech