Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added BleakDeviceNotFoundError #1022

Merged
merged 1 commit into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Added
-----
* Added support for Python 3.11.
* Added better error message for Bluetooth not authorized on macOS.
* ``BleakDeviceNotFoundError`` which should be raised if a device can not be found by ``connect``, ``pair`` and ``unpair``

Fixed
-----
Expand Down
17 changes: 13 additions & 4 deletions bleak/backends/bluezdbus/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

import async_timeout
from dbus_fast.aio import MessageBus
from dbus_fast.constants import BusType, ErrorType
from dbus_fast.constants import BusType, ErrorType, MessageType
from dbus_fast.message import Message
from dbus_fast.signature import Variant

from ... import BleakScanner
from ...exc import BleakDBusError, BleakError
from ...exc import BleakDBusError, BleakError, BleakDeviceNotFoundError
from ..characteristic import BleakGATTCharacteristic
from ..client import BaseBleakClient, NotifyCallback
from ..device import BLEDevice
Expand Down Expand Up @@ -116,8 +116,8 @@ async def connect(self, dangerous_use_bleak_cache: bool = False, **kwargs) -> bo
self._device_info = device.details.get("props")
self._device_path = device.details["path"]
else:
raise BleakError(
"Device with address {0} was not found.".format(self.address)
raise BleakDeviceNotFoundError(
self.address, f"Device with address {self.address} was not found."
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the messages in there to not break compatibility with programs which check for the text as described in #527 (comment)

)

manager = await get_global_bluez_manager()
Expand Down Expand Up @@ -176,6 +176,15 @@ def on_value_changed(char_path: str, value: bytes) -> None:
member="Connect",
)
)
if (
reply is not None
and reply.message_type == MessageType.ERROR
and reply.error_name == ErrorType.UNKNOWN_OBJECT
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure about the UnknownObject error? The documentation does not mention it:
https://github.com/bluez/bluez/blob/master/doc/device-api.txt

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It is a standard D-Bus error. (Searching the issues in this repo for "UnknownObject" reveals quite a few hits)

):
raise BleakDeviceNotFoundError(
self.address,
f"Device with address {self.address} was not found.",
)
assert_reply(reply)

self._is_connected = True
Expand Down
6 changes: 3 additions & 3 deletions bleak/backends/corebluetooth/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from Foundation import NSArray, NSData

from ... import BleakScanner
from ...exc import BleakError
from ...exc import BleakError, BleakDeviceNotFoundError
from ..characteristic import BleakGATTCharacteristic
from ..client import BaseBleakClient, NotifyCallback
from ..device import BLEDevice
Expand Down Expand Up @@ -80,8 +80,8 @@ async def connect(self, **kwargs) -> bool:
self._peripheral = device.details
self._central_manager_delegate = device.metadata["delegate"]
else:
raise BleakError(
"Device with address {} was not found".format(self.address)
raise BleakDeviceNotFoundError(
self.address, f"Device with address {self.address} was not found"
)

if self._delegate is None:
Expand Down
2 changes: 1 addition & 1 deletion bleak/backends/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class BLEDevice:
- When using macOS backend, ``details`` attribute will be a CBPeripheral object.
"""

def __init__(self, address, name, details=None, rssi=0, **kwargs):
def __init__(self, address, name=None, details=None, rssi=0, **kwargs):
#: The Bluetooth address of the device on this machine.
self.address = address
#: The advertised name of the device.
Expand Down
24 changes: 14 additions & 10 deletions bleak/backends/winrt/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from bleak_winrt.windows.storage.streams import Buffer

from ... import BleakScanner
from ...exc import PROTOCOL_ERROR_CODES, BleakError
from ...exc import PROTOCOL_ERROR_CODES, BleakError, BleakDeviceNotFoundError
from ..characteristic import BleakGATTCharacteristic
from ..client import BaseBleakClient, NotifyCallback
from ..device import BLEDevice
Expand Down Expand Up @@ -197,7 +197,7 @@ def __str__(self):

# Connectivity methods

def _create_requester(self, bluetooth_address: int):
def _create_requester(self, bluetooth_address: int) -> BluetoothLEDevice:
args = [
bluetooth_address,
]
Expand All @@ -207,7 +207,12 @@ def _create_requester(self, bluetooth_address: int):
if self._address_type == "public"
else BluetoothAddressType.RANDOM
)
return BluetoothLEDevice.from_bluetooth_address_async(*args)
requester = BluetoothLEDevice.from_bluetooth_address_async(*args)
if requester is None:
raise BleakDeviceNotFoundError(
self.address, f"Device with address {self.address} was not found."
)
return requester

async def connect(self, **kwargs) -> bool:
"""Connect to the specified GATT server.
Expand All @@ -226,10 +231,12 @@ async def connect(self, **kwargs) -> bool:
self.address, timeout=timeout, backend=BleakScannerWinRT
)

if device:
self._device_info = device.details.adv.bluetooth_address
else:
raise BleakError(f"Device with address {self.address} was not found.")
if device is None:
raise BleakDeviceNotFoundError(
self.address, f"Device with address {self.address} was not found."
)

self._device_info = device.details.adv.bluetooth_address

logger.debug("Connecting to BLE device @ %s", self.address)

Expand Down Expand Up @@ -476,9 +483,6 @@ async def unpair(self) -> bool:
else _address_to_int(self.address)
)

if device is None:
raise BleakError(f"Device with address {self.address} was not found.")

try:
unpairing_result = await device.device_information.pairing.unpair_async()
if unpairing_result.status not in (
Expand Down
17 changes: 17 additions & 0 deletions bleak/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@ class BleakError(Exception):
pass


class BleakDeviceNotFoundError(BleakError):
"""
Exception which is raised if a device can not be found by ``connect``, ``pair`` and ``unpair``.
This is the case if the OS Bluetooth stack has never seen this device or it was removed and forgotten.
"""

identifier: str

def __init__(self, identifier: str, *args: object) -> None:
"""
Args:
identifier (str): device identifier (Bluetooth address or UUID) of the device which was not found
"""
super().__init__(*args)
self.identifier = identifier


class BleakDBusError(BleakError):
"""Specialized exception type for D-Bus errors."""

Expand Down