ukBaz / python-bluezero

A simple Python interface to Bluez
MIT License
395 stars 112 forks source link

Unhandled Exception In Device Properties #367

Closed chadrockey closed 2 years ago

chadrockey commented 2 years ago

I'm seeing an incomplete solution with an uncaught exception from https://github.com/ukBaz/python-bluezero/pull/286

  File "/home/root/./onboardlibs/bluezero/device.py", line 75, in name
    return dbus_tools.get(
  File "/home/root/./onboardlibs/bluezero/dbus_tools.py", line 395, in get
    raise dbus_exception
  File "/home/root/./onboardlibs/bluezero/dbus_tools.py", line 390, in get
    return dbus_prop_obj.Get(dbus_iface, prop_name)
  File "/usr/lib64/python3.8/site-packages/dbus/proxies.py", line 72, in __call__
    return self._proxy_method(*args, **keywords)
  File "/usr/lib64/python3.8/site-packages/dbus/proxies.py", line 141, in __call__
    return self._connection.call_blocking(self._named_service,
  File "/usr/lib64/python3.8/site-packages/dbus/connection.py", line 652, in call_blocking
    reply_message = self.send_message_with_reply_and_block(
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.InvalidArgs: No such property 'Name'

I'm seeing the issue caused by this line: https://github.com/ukBaz/python-bluezero/blob/main/bluezero/dbus_tools.py#L392

The issue could be resolved by changing the function similar to the following, but I don't understand why I'm seeing a different type of dbus exception. Is it worth catching all of the dbus exceptions and returning the default if there's any error?

    try:
        return dbus_prop_obj.Get(dbus_iface, prop_name)
    except dbus.exceptions.DBusException as dbus_exception:
        if 'UnknownProperty' in dbus_exception.get_dbus_name() or 'InvalidArgs' in dbus_exception.get_dbus_name():
            return default
        else:
            raise dbus_exception
ukBaz commented 2 years ago

I think I would like to better understand the issue before I start making changes.

The exception this code was trying to catch (UnknownProperty) is when you request a property but it is not on the interface. This was necessary because some values are optional on BlueZ D-Bus interfaces and this was a simple way to query those values.

The exception you are getting (InvalidArgs) is reporting something different I believe. dbus_prop_obj.Get(dbus_iface, prop_name) is reporting that one of the values passed to it is not of the type it expects. If my hypothesis is correct then I believe it is correct to throw an exception. Could you please report back what the value and type of the two values being passed to dbus_prop_obj.Get are.

chadrockey commented 2 years ago

Ah sorry for forgetting that. I’m actually getting it when I try to print device.name in an on_connect function. That’s how I found that original issue via search.

It’s a little line like: print(device.name connected and has device.address), but the .name member is what is causing the issue.

chadrockey commented 2 years ago

I believe this is the line with the information you requested:

https://github.com/ukBaz/python-bluezero/blob/main/bluezero/device.py#L75

ukBaz commented 2 years ago

@chadrockey I've done a fix. Did you want to check it. If it is OK I'll merge and do a new release.

chadrockey commented 2 years ago

Looks like it works! Thanks!

I see this now when the situation happens:

print("Connected to " + str(ble_device.name) + " (" + str(ble_device.address) + ")")

Connected to None (MAC:MAC:MAC:MAC)
ukBaz commented 2 years ago

Thanks for checking.

FYI: Often ble_device.alias is a better property to look at rather than name as BlueZ tends to do a better job of making sure that is a somewhat useful value.

ukBaz commented 2 years ago

This looks to have been resolved and released so closing