bleak
bleak copied to clipboard
bleak.exc.BleakError: Could not pair with device: 19: FAILED
- bleak version: Latest
- Python version: Latest
- Operating System: windows
- BlueZ version (
bluetoothctl -v
) in case of Linux:
Description
there is a GATT server defined in STM32WB55RG i want to connect to a stm32WB55RG via ble and read values from characteristics (to read the values you have to bond with the device)
What I Did
i wrote the script below and i tried all level of authentication but the error still the same
import asyncio
import sys
from asyncore import loop
from bleak import BleakScanner, BleakClient
deviceName = "ETO"
global scanned_device
async def findaddress():
found = False
tentative = 1
while not found:
devices = await BleakScanner.discover(timeout=8)
i = 0
for d in devices:
i = i + 1
print("device {0} name is '{1}'".format(i, d.name))
if (d.name is not None) and (d.name == deviceName):
scanned_device = d
found = True
if not found:
print("device not found in tentative {0} \n\n ".format(tentative))
tentative = tentative + 1
return scanned_device.address
ADDRESS = asyncio.run(findaddress())
async def main(address: str):
client = BleakClient(address, loop=loop)
print("g")
await client.connect()
print("gjm")
await client.unpair()
print("gj")
await client.pair(3)
print("ma taadech")
svcs = await client.get_services()
for service in svcs:
print("\tService: {0}".format(service))
for char in service.characteristics:
print("\t\tcharacteristic:")
print(char)
print(char.description)
print(char.properties)
if "read" in char.properties:
try:
value = bytes(await client.read_gatt_char(char))
print(" value of read charac '{0}'".format(value))
except:
print("not enough authentication")
if __name__ == "__main__":
asyncio.run(main(ADDRESS))
bleak version: Latest Python version: Latest
Latest is ambiguous since it can change when there is a new release. What are the exact version numbers?
Can you give the full stack trace of the crash? Have you tried following the troubleshooting tips in the docs?
Traceback (most recent call last):
File "C:\Users\gjallouli\PycharmProjects\pythonProject\ETO.py", line 60, in <module>
Exception ignored in: <function BleakClientWinRT.connect.<locals>.session_status_changed_event_handler at 0x000001F9C81990D0>
Traceback (most recent call last):
File "C:\Users\gjallouli\PycharmProjects\pythonProject\testble\lib\site-packages\bleak\backends\winrt\client.py", line 241, in session_status_changed_event_handler
asyncio.run(main(ADDRESS))
File "C:\Users\gjallouli\AppData\Local\Programs\Python\Python39\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Users\gjallouli\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete
loop.call_soon_threadsafe(handle_session_status_changed, args)
File "C:\Users\gjallouli\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 791, in call_soon_threadsafe
return future.result()self._check_closed()
File "C:\Users\gjallouli\PycharmProjects\pythonProject\ETO.py", line 39, in main
File "C:\Users\gjallouli\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 510, in _check_closed
paired = await client.pair(protection_level=2)
File "C:\Users\gjallouli\PycharmProjects\pythonProject\testble\lib\site-packages\bleak\backends\winrt\client.py", line 384, in pair
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
raise BleakError(
bleak.exc.BleakError: Could not pair with device: 19: FAILED
bleak version: 0.14.2 python version: 3.9
RuntimeError: Event loop is closed
It think the problem is that your program uses two different run loops.
ADDRESS = asyncio.run(findaddress())
if __name__ == "__main__": asyncio.run(main(ADDRESS))
Try rewriting the program to only use one run loop.
this is what i get after rewriting the program using one run loop, the problem is not there because the connexion is ensured even with two different run loops but pairing is not even after using one run loop
Traceback (most recent call last):
File "C:\Users\gjallouli\PycharmProjects\pythonProject\ETO.py", line 61, in <module>
asyncio.run(main())
File "C:\Users\gjallouli\AppData\Local\Programs\Python\Python39\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Users\gjallouli\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete
return future.result()
File "C:\Users\gjallouli\PycharmProjects\pythonProject\ETO.py", line 40, in main
paired = await client.pair(protection_level=0)
File "C:\Users\gjallouli\PycharmProjects\pythonProject\testble\lib\site-packages\bleak\backends\winrt\client.py", line 384, in pair
raise BleakError(
bleak.exc.BleakError: Could not pair with device: 19: FAILED
A quick web search of this error gives: https://docs.microsoft.com/en-us/answers/questions/36820/bluetoothledevice-pairasync-intermittantly-fails.html
So I would suggested doing a Bluetooth packet capture as detailed in the Bleak troubleshooting docs.
after some research i think the option pairing is available only when you work with linux because it requires BlueZ and it's available only in linux
Having the same issue.
When a phone issues the pairing request I see it uses the IO capability 0x04
and the request is accepted by the STM32 board
When doing it with bleak (windows 10):
and the request is rejected by the STM32 board (reasoncode = 0x03 auth requirements):
from ble spec:
Where/how can i set that iocapability in winrt?
Okay even after changing the ceremony in winrt\client.py to: ceremony = DevicePairingKinds.PROVIDE_PIN | DevicePairingKinds.DISPLAY_PIN
I get the same error. Now the only difference is the LTK key field is not present from BLEAK:
Thanks for the detailed analysis. FYI, there is some work-in-progress improvements in #1100 that will effectively allow selecting the DevicePairingKinds. However, I'm not aware of a way to affect the Encryption Key bit.
Alright. In the meantime I switched off the MITM attack detection on the embedded stm32 side and it works with pairing mode "ceremony = DevicePairingKinds.CONFIRM_ONLY" only. When I set any other pairing mode the pairing fails with error code 0x0c (numeric comparision failed). I guess this is reasonable given there is no way to present/confirm the pin on python side at the moment.
For STM32WB55 users #define CFG_MITM_PROTECTION CFG_MITM_PROTECTION_NOT_REQUIRED
You could also try passing protection_level
to see if it makes a difference.