2016-06-13 5 views
0

Ich versuche Systemzeit einstellen Qt through DBus auf folgende Weise mit:Systemzeit Qt durch DBus mit

#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; 
} 

Aber ich habe: DBus interface validation: false.

Wenn ich in der Konsole aufrufen:

$ gdbus introspect \ 
     --system \ 
     --dest org.freedesktop.timedate1 \ 
     --object-path /org/freedesktop/timedate1 

ich einige relevante Ausgabe zu erhalten (so sieht es aus wie keine Probleme mit Umgebung):

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: 
     ... 
    }; 
}; 

Quellcode und bauen Skript bei GitLab zur Verfügung.

+2

Sieht so aus, als ob das Objekt instanziiert werden muss. Wenn ich mit "d-feet" schaue - ist es nicht da. Dann starte ich '$ gdbus introspect --system --dest org.freedesktop.timedate1 --object-pfad/org/freedesktop/timedate1' von terminal - timedate1 erscheint (und die Qt-Anwendung meldet es dann als gültig). – Velkan

+0

@Velkan, 'Sieht so aus, als müsste das Objekt instanziiert werden. Ich kenne D-Bus nicht. Kannst du mir erklären, was genau ich tun soll? – Gluttton

Antwort

1

Es gibt mehrere Probleme.

  1. Falscher D-Bus-Befehl wird verwendet. Bevor Sie versuchen, Qt-Programm zu schreiben, muss ich den Befehl mit der Konsole debuggen. So richtig Befehl lautet:

    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 
    
  2. Wenn ntp-Dienst verwendet wird Befehl wird mit Fehler ausgeführt: Automatic time synchronization is enabled. So (wie here vorgeschlagen) Synchronisation muss deaktiviert sein:

    timedatectl set-ntp 0 
    
  3. Wie @Velcan timedated Service erwähnte in inaktivem Zustand ist:

    the service is started when someone tries to access the name org.freedesktop.timedate1

    In meiner Umgebung (KUbuntu 15.10 x86_64) ist der Service im aktiven Zustand 30 Sekunden nach dem letzten Anruf.

  4. Nach den 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.

  5. Auch wenn QDBusAbstractInterface::isValid() kehrt false die call Funktion führt mit erfolgreichem Ergebnis.

  6. So endlich ist eine korrekte Code sehr kurz und einfach:

    QDBusInterface dbInterface (
        "org.freedesktop.timedate1" 
        , "/org/freedesktop/timedate1" 
        , "org.freedesktop.timedate1" 
        , QDBusConnection::systemBus()); 
    qDebug() << dbInterface.call ("SetTime", 120000000ll, true, false); 
    

    Dieser Befehl voraus Zeit bis zwei Minuten setzt.

    Dank @Velkan für Hilfe bei der Lösung der Frage und die Bereitstellung nützlicher Informationen!

1

Kurz gesagt: Eine Wiederholungsschleife auf QDBusInterface Erstellung macht den Job.

Ich erforschte ein bisschen mehr. Dieses dbus-Objekt wird vom Dienst systemd-timedated bereitgestellt. Um zu wissen, seinen Status:

sudo systemctl status systemd-timedated 

Die Konfiguration des Dienstes ist in /lib/systemd/system/systemd-timedated.service:

[Unit] 
Description=Time & Date Service 
Documentation=man:systemd-timedated.service(8) man:localtime(5) 
Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated 

[Service] 
ExecStart=/lib/systemd/systemd-timedated 
BusName=org.freedesktop.timedate1 
CapabilityBoundingSet=CAP_SYS_TIME 
WatchdogSec=1min 
PrivateTmp=yes 
ProtectSystem=yes 
ProtectHome=yes 

Die BusName Einstellung für die so genannte 'D-Bus Aktivierung eines Dienstes' verantwortlich ist. Der Dienst wird also gestartet, wenn jemand versucht, auf den Namen org.freedesktop.timedate1 zuzugreifen.

Aber anscheinend braucht es Zeit, um zu beginnen. Ich weiß nicht, wie es sauber gemacht werden soll, aber Sie können eine Wiederholungsschleife erstellen, die QDBusInterface erstellt. Sie werden sehen, dass sudo systemctl status systemd-timedated aktiv wird und Qt eine gültige Schnittstelle abruft.

Objektnamen und den Pfad, den ich versucht habe:

QDBusInterface dbInterface (
    "org.freedesktop.timedate1" 
    , "/org/freedesktop/timedate1" 
    , "org.freedesktop.timedate1" 
    , dbConnection); 
+0

Vielen Dank für Ihre Antwort, die sehr nützlich für mich ist! Aber meiner Meinung nach ist die vorgeschlagene Lösung nicht gut genug. – Gluttton