I try to set system time using Qt through DBus in the following way:
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDebug>
#include <QDateTime>
#include <cstdlib>
int main (int /*argc*/, char ** /*argv*/)
{
QDBusConnection dbConnection = QDBusConnection::systemBus ();
QDBusInterface dbInterface (
"org.freedesktop.timedate1.set-time"
, "/org/freedesktop/timedate1/set-time/Manager"
, "org.freedesktop.timedate1.set-time.Manager"
, dbConnection);
qDebug () << "DBus interface validation: " << dbInterface.isValid ();
if (dbInterface.isValid () ) {
QDBusMessage dbMessage = dbInterface.call ("SetTime", QDateTime::currentDateTime ().toMSecsSinceEpoch () * 1000, false, false);
qDebug () << "DBus message: " << dbMessage;
}
return EXIT_SUCCESS;
}
But I've got: DBus interface validation: false
.
If I call in the console:
$ gdbus introspect \
--system \
--dest org.freedesktop.timedate1 \
--object-path /org/freedesktop/timedate1
I get some relevant output (so it looks like no problems with environment):
node /org/freedesktop/timedate1 {
interface org.freedesktop.DBus.Peer {
...
};
interface org.freedesktop.DBus.Introspectable {
...
};
interface org.freedesktop.DBus.Properties {
methods:
...
signals:
...
properties:
};
interface org.freedesktop.timedate1 {
methods:
SetTime(in x arg_0,
in b arg_1,
in b arg_2);
...
signals:
properties:
...
};
};
Source code and build script available at GitLab.
There are several problems.
Wrong D-Bus command is used. Before try writing Qt program I must debug the command with console. So correct command is:
dbus-send \
--system \
--print-reply \
--type=method_call \
--dest='org.freedesktop.timedate1' \
'/org/freedesktop/timedate1' \
org.freedesktop.timedate1.SetTime \
int64:120000000 \
boolean:true \
boolean:false
When ntp service is used command will be performed with error: Automatic time synchronization is enabled
. So (as suggested here) synchronization must be disabled:
timedatectl set-ntp 0
As mentioned by @Velcan timedated service is in inactive state:
the service is started when someone tries to access the name
org.freedesktop.timedate1
In my environment (KUbuntu 15.10 x86_64
) the service is in active state 30 seconds after last call.
According to the Qt documentation:
bool QDBusAbstractInterface::isValid() const
Returns true if this is a valid reference to a remote object. It returns false if there was an error during the creation of this interface (for instance, if the remote application does not exist).
Note: when dealing with remote objects, it is not always possible to determine if it exists when creating a QDBusInterface.
Even if QDBusAbstractInterface::isValid()
returns false
the call
function performs with successful result.
So finally, correct code is very short and simple:
QDBusInterface dbInterface (
"org.freedesktop.timedate1"
, "/org/freedesktop/timedate1"
, "org.freedesktop.timedate1"
, QDBusConnection::systemBus () );
qDebug () << dbInterface.call ("SetTime", 120000000ll, true, false);
This command sets time to two minutes ahead.
Thanks @Velkan for help in solving the question and providing useful information!