D-Bus signal/slot mechanism not functioning
-
Hi,
This is my first foray into using D-Bus within Qt, so please excuse the basic question. I'm looking to monitor network connectivity using the connman connection manager, through the use of its various D-Bus APIs (e.g. Manager, Technology, Services, etc.).
At the moment I'm getting my head around the D-Bus process with the connman Manager 'ServicesChanged' signal:
ServicesChanged(array{object, dict}, array{object}) Signals a list of services that have been changed via the first array. And a list of service that have been removed via the second array. The list of added services is sorted. The dictionary with the properties might be empty in case none of the properties have changed. Or only contains the properties that have changed. For newly added services the whole set of properties will be present. The list of removed services can be empty. This signal will only be triggered when the sort order of the service list or the number of services changes. It will not be emitted if only a property of the service object changes. For that it is required to watch the PropertyChanged signal of the service object.
I've setup the below code (snippets shown for simplicity), and am toggling on/off the ethernet interface using the connmanctl CLI. I have a second terminal open with dbus-monitor --system running, and can see the Manager 'ServicesChanged' signal being emitted as expected. The issue I'm having, is that despite seeing the expected D-Bus signal emitted in dbus-monitor, the configured slot in my Qt application is not being called.
The below code is based on similar functionality I've found online, including libconnman-qt.
wifi.h:
struct ConnmanObject { QDBusObjectPath objectPath; QVariantMap propertyMap; }; Q_DECLARE_METATYPE(ConnmanObject) typedef QList<ConnmanObject> ConnmanObjectList; class wifi : public QObject { Q_OBJECT public: explicit wifi(QObject *parent = nullptr); signals: public slots: void servicesChanged(const ConnmanObjectList&, const QList<QDBusObjectPath>&); private: QDBusInterface *managerInterface;
wifi.c
wifi::wifi(QObject *parent) : QObject(parent) { managerInterface = new QDBusInterface("net.connman", "/", "net.connman.Manager", QDBusConnection::systemBus(), this); managerInterface->connection().connect("net.connman", "/", "net.connman.Manager", "ServicesChanged", this, SLOT(servicesChanged(ConnmanObjectList, QList<QDBusObjectPath>))); } void wifi::servicesChanged(const ConnmanObjectList &changed, const QList<QDBusObjectPath> &removed) { qDebug() << "Services changed!" }
What am I missing?
-
It seems that I've sorted this issue with the help of the qconnmanservice_linux_p class. As suspected, it looks like I hadn't properly registered and configured the ConnmanObject struct and ConnmanObjectList QList with the QtDBus system. I added the QDBusArgument &operator<< and &operator>> templates (per the linked header file above) and their corresponding functions in my wifi.c class, and registered ConnmanObject and ConnmanObjectList via qDBusRegisterMetaType<ConnmanObject>(); and qDBusRegisterMetaType<ConnmanObjectList>(); respectively, and now the 'ServicesChanged' slot is called as expected.
-
I've made some progress on this issue, but I'm still unable to receive the ServicesChanged signal as outlined in the original post. I've configured a second signal/slot, which is based on the Technology 'PropertyChanged' signal for the Ethernet technology type. The signal/slot signature for this D-Bus signal is much simpler:
void ethernetPropertyChanged(QString, QDBusVariant>);
I configure the signal/slot using QDBusConnection directly rather than via QDBusInterface as per the original post:
QDBusConnection system = QDBusConnection::systemBus(); system.connect("net.connman", "/net/connman/technology/ethernet", "net.connman.Technology", this, SLOT(ethernetPropertyChanged(QString, QDBusVariant)));
This signal/slot mechanism works as expected; when I enable or disable the ethernet interface using connmanctl, the ethernetPropertyChanged() function is executed.
However, when I replicate the above code for the Manager 'ServicesChanged' signal, the corresponding slot is not executed, even though I can see the ServicesChanged signal firing with dbus-monitor. The only difference I can see is the use of the ConnmanObject struct and Q_DECLARE_METATYPE; have I not done this correctly?
-
It seems that I've sorted this issue with the help of the qconnmanservice_linux_p class. As suspected, it looks like I hadn't properly registered and configured the ConnmanObject struct and ConnmanObjectList QList with the QtDBus system. I added the QDBusArgument &operator<< and &operator>> templates (per the linked header file above) and their corresponding functions in my wifi.c class, and registered ConnmanObject and ConnmanObjectList via qDBusRegisterMetaType<ConnmanObject>(); and qDBusRegisterMetaType<ConnmanObjectList>(); respectively, and now the 'ServicesChanged' slot is called as expected.