I'm trying to figure out the Bluez DBus API, and I'm having trouble understanding some of the concepts.
The most thorough Bluez examples I've seen have all used Python's dbus-python library. For example, this python script demonstrates how to create a BLE advertisement. A lot of the content is in the Advertisement class, which extends dbus.service.Object. The Advertisement class implements a GetAll method (from the org.freedesktop.DBus.Properties interface) and a Release method (from the org.bluez.LEAdvertisement1 interface). In order to register that advertisement, it calls RegisterAdvertisement from the org.bluez.LEAdvertisingManager1 interface.
I'm getting tripped up because I'm more used to Qt DBus, so I was thinking about what it would look like if the same thing was done using PyQt instead of dbus-python. I think the biggest hurdles are:
- I can't figure out how the
Advertisementclass in the example would fit into the interface/adaptor model of Qt Dbus - In the example, the
Advertisementclass implements methods from two interfaces. I found this discussion, which implies that it can be done, but I don't think I fully understand the mechanics of it
So, in summary, if I wanted to re-implement this example with Qt DBus, what would the Advertisement class look like? Would it extend QDBusAbstractAdaptor or QDBusAbstractInterface? Would it contain one (or both) of those things? Or is there something else entirely that I'm missing?
Edit:
Based on some info from @ukBaz, I dug a little deeper and tried a few more things, but I've come up empty so far. For reference, I have two scripts in this github repo. The stock-example.py script is pulled directly from the Bluez source tree. The qt-example.py script is my attempt at "translating" it to use QtDBus.
What I have found is that the stock script and the Qt script both work enough that I can see them advertising in nRF Connect on my phone. However, the call to RegisterAdvertisement in the Qt app always times out:
class BleAdManager(QDBusAbstractInterface):
def __init__(self, dbus_obj_path, parent=None):
self._ble_adapter_dbus_path = dbus_obj_path
self._dbus_system_bus = QDBusConnection.systemBus()
super().__init__("org.bluez",
self._ble_adapter_dbus_path,
"org.bluez.LEAdvertisingManager1",
self._dbus_system_bus,
parent)
def RegisterAdvertisement(self, ad_path):
print("Registering {0}...".format(ad_path))
msg = self.call('RegisterAdvertisement', QDBusObjectPath(ad_path), {})
print("Call returned.")
reply = QDBusReply(msg)
if reply.isValid():
print("Valid")
return reply.value()
else:
print(reply.error().message())
return None
When I run this, it hangs on the QDBusAbstractInterface.call() for about 25 seconds, then spits out
Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
Since the stock script works, it can't be a security policy problem. Should the remote application send me a reply to RegisterAdvertisement? If not, how do I handle that gracefully with QtDBus (i.e., without it hanging and giving me an error)? If so, why wouldn't I get a response, and how should I attempt to debug?