-
Notifications
You must be signed in to change notification settings - Fork 339
Description
Summary
After upgrading to Windows 11, a Python BLE client using Bleak (WinRT backend) fails to connect/pair to a Raspberry Pi 4 BLE GATT server (Python Bless / BlueZ). Windows shows a system pairing prompt (“Pair device?”). When the user clicks Allow, Windows immediately shows “Connection failed”. On the client side, Bleak throws:
-
WinError -2147023673 (
0x800704C7) — “The operation was canceled by the user” -
Often followed by WinError -2147483629 (
0x80000013) — “The object has been closed”
This happens even when the user actively clicks Allow on the Windows pairing UI.
Environment
- Client OS: Windows 11
- Client library: Python + Bleak (WinRT)
- Peripheral: Raspberry Pi 4
- Server: Python + Bless (BlueZ backend)
- Transport: BLE GATT
Observed Behavior
- Client calls
await client.connect()(and/or immediately doesawait client.get_services()after connect). - Windows 11 displays a pairing/consent dialog.
- User clicks Allow.
- Windows shows Connection failed immediately.
- Client receives
0x800704C7(“canceled by user”) even though user allowed.
Expected Behavior
- Pairing should complete successfully when user clicks Allow, and Bleak should proceed with a connected GATT session (or return a clear pairing failure reason if the peripheral rejects pairing).
Evidence / Logs
Windows UI
- Dialog: “
<DeviceName>would like to pair… Allow / Cancel” - After Allow: “Connection failed” shown immediately.
Raspberry Pi output (representative)
- BLE advertising starts successfully.
- When attempting to configure pairing agent via scripting:
Bluetooth command agent NoInputNoOutput executed successfully.No agent is registeredSkip: Command '['bluetoothctl', 'default-agent']' returned non-zero exit status 1.
- Then device becomes:
discoverable,pairable,bondable,secure-conn, etc.
…but pairing from Windows still fails.
Reproduction Steps
- Start BLE GATT server on Pi (Bless/BlueZ).
- On Windows 11, run Python Bleak client and attempt connect.
- Observe Windows pairing prompt.
- Click Allow.
- Observe immediate failure and
0x800704C7on client.
Sample Code
A) Raspberry Pi: Recommended bluetoothctl CLI sequence (manual)
Run in a single interactive session and keep it open during pairing:
sudo bluetoothctl
power on
agent NoInputNoOutput
default-agent
pairable on
discoverable onPair device independently using the Bluetooth & devices
B) Raspberry Pi: Persistent bluetoothctl agent example (Python)
This avoids the “agent gets lost because bluetoothctl exits” issue by keeping one bluetoothctl process alive.
import subprocess
import time
class BtCtl:
def __init__(self):
self.p = subprocess.Popen(
["bluetoothctl"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1
)
def cmd(self, s: str, delay: float = 0.2):
assert self.p.stdin is not None
self.p.stdin.write(s + "\n")
self.p.stdin.flush()
time.sleep(delay)
def setup_bluetooth_persistent():
bt = BtCtl()
bt.cmd("power on")
bt.cmd("agent NoInputNoOutput")
bt.cmd("default-agent")
bt.cmd("discoverable on")
bt.cmd("pairable on")
return bt # IMPORTANT: keep this alive while pairing is needed
if __name__ == "__main__":
bt = setup_bluetooth_persistent()
print("Agent is running; keep this process alive while pairing from Windows.")
while True:
time.sleep(5)C) Windows 11: Bleak client connect example
Includes increased timeouts and “discover services after connect”. If pairing is required, you may need to request pairing (depending on Bleak version).
import asyncio
from bleak import BleakScanner, BleakClient
ADDRESS = "D8:3A:DD:AC:C6:5D" # example
async def main():
# Prefer: find BLEDevice via scan (more reliable than address-only)
device = await BleakScanner.find_device_by_address(ADDRESS, timeout=20.0)
if not device:
print("Device not found")
return
client = BleakClient(device, pair=True)
try:
await client.connect(timeout=30.0)
# On Windows, service discovery may trigger pairing if required by permissions
services = await client.get_services()
print("Services:", services)
finally:
try:
await client.disconnect()
except Exception:
pass
asyncio.run(main())-
Is
0x800704C7on Windows 11 commonly returned when the OS pairing prompt fails (even after user clicks Allow)? -
Are there known changes in Windows 11 WinRT BLE pairing that require:
- connecting via
BLEDeviceonly, - explicit
pair()beforeget_services(), - longer timeouts,
- or specific WinRT APIs not currently handled by Bleak?
- connecting via
-
Does Bleak have recommended patterns to avoid triggering pairing during
connect()/get_services()on Windows (especially for Pi/BlueZ peripherals)?
Additional Context
- Windows UI consistently shows pairing prompt, and then immediate “Connection failed” after clicking Allow.
- The client then throws
WinError -2147023673(“operation canceled by user”).