2016-06-13 7 views
0

経由のQtを使用して:を設定し、システムの時間を、私は次のようにQtの<a href="https://www.freedesktop.org/wiki/Software/systemd/timedated/" rel="nofollow">through DBus</a>を使用して、システムの時刻を設定しようとするDバス

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

しかし、私は持っている:DBus interface validation: falseを。

私はコンソールに呼び出す場合:ソースコード

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

GitLabで入手可能なスクリプトを作成:

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

私はいくつかの関連出力を得る(それは環境に問題がないように見えますので)。

+2

オブジェクトをインスタンス化する必要があるように見えます。私が「d-feet」で見ると、そこにはありません。次に、terminal-timedate1から '$ gdbus introspect --system --dest org.freedesktop.timedate1 --object-path/org/freedesktop/timedate1'が起動します(Qtアプリケーションはそれを有効と報告します)。 – Velkan

+0

@Velkan、 'オブジェクトをインスタンス化する必要があるように見えます.''私はD-Busに慣れていません。あなたは私が何をすべきか説明できますか? – Gluttton

答えて

1

いくつかの問題があります。

  1. 間違ったD-Busコマンドが使用されます。 Qtプログラムを書く前に、コンソールでコマンドをデバッグする必要があります。だから、正しいコマンドは次のとおりです。

    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. NTPサービスが使用されているコマンドはエラーで実行されます:Automatic time synchronization is enabled。だから、(hereが示唆したように)同期を無効にする必要があります。

    timedatectl set-ntp 0 
    
  3. @Velcan timedatedサービスで述べたように、非アクティブな状態にあります。

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

    私の環境では(KUbuntu 15.10 x86_64)サービスがアクティブな状態にあります最後の呼び出し後30秒。Qt documentationによれば

  4. 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. でもQDBusAbstractInterface::isValid()なら戻りfalsecall関数は成功した結果を用いて行います。

  6. だから最終的には、正しいコードは非常に短く、シンプルです:

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

    このコマンドは、先に2分までの時間を設定します。

    質問を投稿したり、役に立つ情報を提供してくれてありがとう@Velkanありがとうございました!

1

要するに、QDBusInterfaceのリトライループがジョブを実行します。

もう少し詳しく調べました。そのdbusオブジェクトはsystemd-timedatedサービスによって提供されます。 /lib/systemd/system/systemd-timedated.service

sudo systemctl status systemd-timedated 

サービスの設定は次のとおりです:その状態を知るために

[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 

BusName設定は、いわゆる「サービスのD-バス活性化」を担当しています。したがって、誰かがorg.freedesktop.timedate1という名前にアクセスしようとすると、サービスが開始されます。

しかし、明らかに開始には時間がかかります。どのように正常に処理されるのかわかりませんが、QDBusInterfaceを作成する再試行ループを作成できます。 sudo systemctl status systemd-timedatedがアクティブになり、Qtが有効なインターフェイスを取得することがわかります。私が試した

オブジェクト名とパス:

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

私のために非常に便利なあなたの答えをありがとう!しかし、私の意見では、提案された解決策は十分ではありません。 – Gluttton

関連する問題