Embedded Linux Qt Simple Dbus Example II

Embedded Linux Qt Simple Dbus Example II


Here is a simple step by step example of how to use the Qt DBus tools on Ubuntu Linux to create a simple sender / receiver pair of applications. The example also covers exposing Qt Signals as DBus signals.

A simple dbus server can be created susing the Qt Dbus tools by performing the following steps. First we create a server, and then a client.


1.) Open QtCreator and create a new project called dbus-server.


2.) Create a new class for this project named interfacedescription.


3.) Modify the dbus-server.pro file to include "QT += dbus".


4.) In the interfacedescription.h file, include QObject --> #include <QObject> and also define the QOBJECT macro


5.) In the interfacedescription header file, inherit for QObject --> class interfacedescription : public QObject


6.) In the interfacedescription header file, define the following functions as public slots, and a signal:


class interfacedescription : public QObject

{

Q_OBJECT

public:

interfacedescription();

public slots:

QString read();

QString write();

QString SendMessage(const QString &cmd);

Q_SIGNALS:

void somethingHappened(const QString &signalMessage);

};


7.) In the interfacedescription.cpp source file, define the following method bodies:


interfacedescription::interfacedescription() {


new ifadapter(this); // Cleans itself up


QDBusConnection dbus = QDBusConnection::sessionBus(); // Use session bus


dbus.registerObject("/interfacedescription",this); // Register object on the bus


dbus.registerService("com.dbus.example.interface"); // Expose interface to others


}


QString interfacedescription::read() {


qDebug() << "Request to read was received!";


emit somethingHappened("Emitting DBus Signal Now!");


return QString("Request to read was received!");


}


QString interfacedescription::write() {


qDebug() << "Request to write was received!";


emit somethingHappened("Emitting DBus Signal Now!");


return QString("Request to write was received!");


}


QString interfacedescription::SendMessage(const QString &cmd) {


qDebug() << "Message Received by Server!";


emit somethingHappened("Emitting DBus Signal Now!");


return QString("Echoing message received: %1").arg(cmd);


}


8.) Run the qbuscpp2xml tool on the model class you just created like this: qdbuscpp2xml -M -P -S interfacedescription.h -o com.dbus.example.interface.xml


9.) That will result in an xml file ( com.dbus.example.interface.xml ) in the working directory that looks like this:


<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">

<node>

<interface name="local.interfacedescription">

<signal name="somethingHappened">

<arg name="signalMessage" type="s" direction="out"/>

</signal>

<method name="read">

<arg type="s" direction="out"/>

</method>

<method name="write">

<arg type="s" direction="out"/>

</method>

<method name="SendMessage">

<arg type="s" direction="out"/>

<arg name="cmd" type="s" direction="in"/>

</method>

</interface>

</node>


10.) Now create an "adaptor" class from the XML file by running the following command: qdbusxml2cpp -c ifadapter -a ifadapter.h:ifadapter.cpp com.dbus.example.interface.xml


11.) Add the auto-generated files from the last step to your .pro file:


SOURCES += main.cpp \

interfacedescription.cpp \

ifadapter.cpp


HEADERS += \

interfacedescription.h \

ifadapter.h


12.) Includ the ifadapter class in your interfacedescription.cpp class implementation file:


/// Include the adapter class

#include "ifadapter.h"


13.) Include <QDbus> and "interfacedescription.h" in your main.cpp file:


/// Include DBus

#include <QtDBus>


/// Include description class

#include "interfacedescription.h"


14.) Instantiate the adapter class and create a connection to your system's DBus session bus in the constructor for the interfacedescription class:


new ifadapter(this); // Cleans itself up


QDBusConnection dbus = QDBusConnection::sessionBus(); // Use session bus


dbus.registerObject("/interfacedescription",this); // Register object on the bus


dbus.registerService("com.dbus.example.interface"); // Expose interface to others


15.) Create a dbus instance in your main.cpp file:


qDebug() << "Initializing DBus Server...";

qDebug() << "Creating interface...";


// Create a dbus instance

new interfacedescription();


qDebug() << "Done creating interface...";

qDebug() << "Waiting for messages...";


16.) The previous steps conclude the work to create a dbus-server, now we move on to creating a dbus-client.


17.) Create a new project name dbus-client.


18.) Copy the com.dbus.example.interface.xml file from the dbus-server directory to the dbus-client directory.


19.) Create a client interface by running: qdbusxml2cpp -v -c clientIf -p clientIf.h:clientIf.cpp com.dbus.example.interface.xml


20.) Include the clientIf.h file in your main.cpp: #include "clientIf.h"


21.) Include dbus in your .pro file: "QT += dbus"


22.) In your main.cpp file, setup the client interface instance and call some methods ( Note there is a Slot on a Class named "SignalReceiver" not shown to hook up with the DBus generated signal ):


clientIf* client = new clientIf("com.dbus.example.interface", "/interfacedescription", QDBusConnection::sessionBus(), 0);


// Define a signal receiver and hook up it's slot to the Dbus generated signal

SignalReceiver rx;

QObject::connect(client,SIGNAL(somethingHappened(QString)), &rx, SLOT(receivedSignal(QString)));


qDebug() << "Sending Read() command over Dbus to server...";

client->read();

qDebug() << "Done sending read command...";


qDebug() << "Sending Write() command over Dbus to server...";

client->write();

qDebug() << "Done sending write command...";


QString messageToSend("Hello World!");

client->SendMessage(messageToSend);


23.) Finally, you can build and run the server first, and then the client. You will see output printed to the screen outlining the communication between the 2 processes.


Output of Server:

./dbus-server

Initializing DBus Server...

Creating interface...

Done creating interface...

Waiting for messages...

Request to read was received!

Request to write was received!

Message Received by Server!


Output of client:


./dbus-client

Sending Read() command over Dbus to server...

Done sending read command...

Sending Write() command over Dbus to server...

Done sending write command...

Received DBus Signal - message was: "Emitting DBus Signal Now!"

Received DBus Signal - message was: "Emitting DBus Signal Now!"

Received DBus Signal - message was: "Emitting DBus Signal Now!"




ClassyBits 2016