diff --git a/bleak/backends/bluezdbus/client.py b/bleak/backends/bluezdbus/client.py index 8144b578..e93992e6 100644 --- a/bleak/backends/bluezdbus/client.py +++ b/bleak/backends/bluezdbus/client.py @@ -96,12 +96,9 @@ def __init__(self, address_or_ble_device: Union[BLEDevice, str], **kwargs): # used to override mtu_size property self._mtu_size: Optional[int] = None - if kwargs.get("pairing_callbacks"): - warnings.warn( - "Pairing on connect not yet implemented for BlueZ", - RuntimeWarning, - stacklevel=2, - ) + self._pairing_callbacks: Optional[BaseBleakAgentCallbacks] = kwargs.get( + "pairing_callbacks" + ) def close(self): self._bus.disconnect() @@ -193,6 +190,11 @@ def on_value_changed(char_path: str, value: bytes) -> None: # # For additional details see https://github.com/bluez/bluez/issues/89 # + if self._pairing_callbacks: + # org.bluez.Device1.Pair() will connect to the remote device, initiate + # pairing and then retrieve all SDP records (or GATT primary services). + await self.pair(self._pairing_callbacks) + if not manager.is_connected(self._device_path): logger.debug("Connecting to BlueZ path %s", self._device_path) async with async_timeout(timeout): @@ -400,6 +402,7 @@ async def pair( member="Pair", ) ) + # TODO: Call "CancelPairing" if this task is cancelled try: assert_reply(reply) diff --git a/examples/pairing_agent.py b/examples/pairing_agent.py index 19a0a676..12bd0dbd 100644 --- a/examples/pairing_agent.py +++ b/examples/pairing_agent.py @@ -59,7 +59,7 @@ async def request_pin(self, device: BLEDevice) -> str: return response -async def main(addr: str, unpair: bool) -> None: +async def main(addr: str, unpair: bool, auto: bool) -> None: if unpair: print("unpairing...") try: @@ -76,16 +76,26 @@ async def main(addr: str, unpair: bool) -> None: print("device was not found") return - print("pairing...") + if auto: + print("connecting and pairing...") - async with BleakClient(device) as client, AgentCallbacks() as callbacks: - try: - await client.pair(callbacks) - print("pairing successful") - except BleakPairingCancelledError: - print("paring was canceled") - except BleakPairingFailedError: - print("pairing failed (bad pin?)") + async with AgentCallbacks() as callbacks, BleakClient( + device, pairing_callbacks=callbacks + ) as client: + print(f"connection and pairing to {client.address} successful") + + else: + print("connecting...") + + async with BleakClient(device) as client, AgentCallbacks() as callbacks: + try: + print("pairing...") + await client.pair(callbacks) + print("pairing successful") + except BleakPairingCancelledError: + print("paring was canceled") + except BleakPairingFailedError: + print("pairing failed (bad pin?)") if __name__ == "__main__": @@ -94,6 +104,9 @@ async def main(addr: str, unpair: bool) -> None: parser.add_argument( "--unpair", action="store_true", help="unpair first before pairing" ) + parser.add_argument( + "--auto", action="store_true", help="automatically pair during connect" + ) args = parser.parse_args() - asyncio.run(main(args.address, args.unpair)) + asyncio.run(main(args.address, args.unpair, args.auto))