Bagaimana cara membaca output dbus-monitor?


20

Saya bermain-main dengan dbus-monitor untuk mencoba dan memahami bagaimana dbus bekerja di lingkungan Ubuntu. Saya punya beberapa pertanyaan dalam hal ini:

  1. Bisakah Anda memberi tahu saya cara membaca yang berikut dengan benar? Saya mengerti ide besarnya, tapi tidak detailnya.

    signal sender=:1.1948 -> dest=(null destination) serial=1829990 path=/org/ayatana/menu/DA00003; interface=org.ayatana.dbusmenu; member=ItemPropertyUpdated
    int32 23
    string "enabled"
    variant boolean true
    method call sender=:1.6 -> dest=org.freedesktop.Notifications serial=1399 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications;
    member=GetCapabilities

    Saya mendapatkan bahwa yang pertama adalah sinyal sedangkan yang kedua adalah metode. Apakah tujuan berarti ada penerima / slot tertentu untuk sinyal? Apa itu anggota ? Dan apakah item dari daftar mengikuti sinyal argumen yang diberikan dalam sinyal? Apa itu pengirim dan serial ?

  2. Saya memperhatikan sesuatu tentang hubungan antara kontrol volume dan pemberitahuan. Dari apa yang saya baca dari output dbus-monitor

    method call sender=:1.6 -> dest=org.freedesktop.Notifications serial=1400 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=Notify
    string "gnome-settings-daemon"
    uint32 0
    string "notification-audio-volume-medium"
    string " "
    string ""
    array [
    ]
    array [
    dict entry(
    string "value"
    variant int32 38
    )
    dict entry(
    string "x-canonical-private-synchronous"
    variant string "volume"
    )
    ]
    int32 -1

    Tampaknya notifikasi dipicu oleh metodenya. Saya hanya tidak benar-benar mengerti mengapa ini bekerja seperti ini. Dalam pandangan saya akan lebih masuk akal jika ada sinyal yang dipancarkan "notifikasi-audio-volume-medium" sementara notifikasi akan mendengarkan sinyal ini dan bereaksi sesuai. Jika pengiriman / penerimaan akan bersifat publik daripada pribadi, tidakkah hal itu akan memberikan fleksibilitas dan efisiensi yang lebih? Misalnya jika ada sinyal publik untuk "notifikasi-audio-volume-medium" kemudian beberapa aplikasi dapat mendengarkan sinyal ini (yang akan memungkinkan aplikasi notifikasi yang bersaing muncul) dan pengembang hanya harus peduli dengan pengiriman sinyal, sementara mengambil dan menangani sinyal akan menjadi bisnis aplikasi yang memberi tahu (atau bisnis lainnya yang memberi tahu) program yang membutuhkan sinyal tersebut).

  3. Saya baru mengenal Dbus dan ingin belajar lebih banyak karena saya bekerja dengan Dbus di Python, terutama untuk mengembangkan beberapa applet. Saya telah melihat tutorial dbus-python dan mengajarkan cara mendengarkan semua sinyal (dengan tidak menentukan antarmuka atau jalur dll.) Tetapi bagaimana cara melacak metode ketika mereka dipanggil, seperti dbus-monitor?

Jika Anda memiliki kesabaran untuk mengajarkan cara kerjanya, Anda dipersilakan.

Jawaban:


24

Pengenalan D-Bus

  • D-Bus menyediakan sarana untuk berkomunikasi antar layanan . Layanan dapat anonim (diidentifikasi hanya berdasarkan alamat bus, seperti: 1.6), dan layanan dapat memperoleh nama-nama terkenal , seperti org.freedesktop.Notificationsatau org.freedesktop.NetworkManager. Pengirim dan tujuan yang dapat Anda lihat di log adalah layanan. "Null destination" berarti siaran: pengiriman ke semua layanan.

  • Suatu layanan dapat mengekspor satu atau beberapa objek ke bus. Objek diberi jalur objek , seperti /org/freedesktop/NetworkManager/ActiveConnection/1atau /org/ayatana/menu/DA00003. Jalur objek menggunakan slash sebagai pemisah, seperti jalur sistem file.

  • Setiap objek dapat mendukung satu atau beberapa antarmuka . Antarmuka tidak lebih dari seperangkat metode dan sinyal, secara bahasa dikenal sebagai anggota (sangat mirip dengan antarmuka OOP). Metode dan sinyal memiliki tanda tangan tetap. Anggota selalu diberi nama tempat di dalam nama antarmuka yang terkenal .

  • Setelah diterbitkan, nama-nama terkenal tidak pernah berubah .

  • Layanan apa pun dapat terhubung ke sinyal layanan lain dan secara tak sinkron memanggil metodenya. Layanan apa pun dapat memancarkan sinyal.

Sinyal

Sekarang untuk pertanyaan spesifik Anda.

pengirim sinyal =: 1.1948 -> dest = (null destination) serial = 1829990 path = / org / ayatana / menu / DA00003; antarmuka = ​​org.ayatana.dbusmenu; member = ItemPropertyUpdated
int32 23
string "diaktifkan"
varian boolean benar

Ya, Anda benar, ini pertanda. Ini disiarkan oleh layanan :1.1948, dan objek "diri" adalah /org/ayatana/menu/DA00003. Sinyal memiliki nama ItemPropertyUpdatedyang didefinisikan dalam antarmuka org.ayatana.dbusmenu(seperti org.ayatana.dbusmenu::ItemPropertyUpdateddi C ++). Serial ini, saya kira, adalah semacam pengidentifikasi unik dari peristiwa di bus.

Lalu kita melihat argumen sinyal. Menurut dokumentasi antarmuka , argumen int32 pertama adalah id item, string kedua adalah nama propertinya, dan varian ketiga adalah nilai properti. Jadi, /org/ayatana/menu/DA00003objek memberi tahu kami bahwa item id # 23 mengubah enabledpropertinya menjadi true.


Contoh lain tentang sinyal:

pengirim sinyal =: 1.1602 -> dest = (tujuan nol) serial = 20408 jalur = / im / pidgin / ungu / PurpleObject; interface = im.pidgin.purple.PurpleInterface; member = SendingChatMsg
   int32 47893
   string "test"
   uint32 1
pengirim sinyal =: 1.1602 -> dest = (tujuan nol) serial = 20409 jalur = / im / pidgin / ungu / PurpleObject; interface = im.pidgin.purple.PurpleInterface; anggota = IrcSendingText
   int32 64170
   string "PRIVMSG #chat: test

Saya mengirim "tes" pesan teks menggunakan Pidgin ke saluran IRC, dan /im/pidgin/purple/PurpleObjectmemancarkan dua sinyal di bawah im.pidgin.purple.PurpleInterfaceantarmuka: pertama seorang jenderal SendingChatMsg, kemudian yang lebih spesifik IrcSendingText.

Metode

Sekarang metode. Metode adalah cara untuk meminta objek D-Bus untuk melakukan sesuatu, atau untuk melakukan beberapa permintaan dan mengembalikan data. Mereka sangat mirip dengan metode OOP klasik, kecuali bahwa metode D-Bus disebut asinkron.

Mari kita panggil metode D-Bus secara terprogram.

import dbus, dbus.proxies

#-- connect to the session bus (as opposed to the system bus)
session = dbus.SessionBus()

#-- create proxy object of D-Bus object
obj_proxy = dbus.proxies.ProxyObject(conn=session,
         bus_name="org.freedesktop.Notifications",     #-- name of the service we are retrieving object from
         object_path="/org/freedesktop/Notifications") #-- the object path

#-- create proxy object of the D-Bus object wrapped into specific interface
intf_proxy = dbus.proxies.Interface(obj_proxy, "org.freedesktop.Notifications")

#-- lastly, create proxy object of the D-Bus method
method_proxy = intf_proxy.get_dbus_method("Notify")

#-- ... and call the method
method_proxy("test from python",
             dbus.UInt32(0),
             "bluetooth",     #-- icon name
             "Notification summary",
             "Here goes notification body",
             [], {},
             5) #-- timeout

Perhatikan argumennya, terutama nama ikonnya. Dalam contoh Anda "notification-audio-volume-medium"adalah ikon pengeras suara volume sedang.

Layanan khusus

Sangat mungkin untuk menjalankan layanan D-Bus Anda sendiri, mengekspor objek D-Bus Anda sendiri dan mendefinisikan antarmuka D-Bus Anda sendiri dengan metode dan sinyal Anda sendiri. Ini semua dapat dilakukan dengan Python cukup mudah setelah Anda memahami konsep keseluruhan dan membaca dbusdokumentasi modul.:)


Diskusi disambut, meskipun saya mungkin tidak tersedia dalam satu atau dua hari.
ulidtko

Terima kasih :) Ini banyak menjelaskan. Entah bagaimana lucu bahwa pengirim bisa anonim, ketika saya menggunakan DFeet, ada nama proses yang sesuai untuk masing-masing pengirim, tetapi itu tidak mencerminkan dalam output dbus-monitor. Bisakah proses dilacak? Sekarang dengan Python saya sudah melihat saya dapat mengirim sinyal atau memberikan metode atau memicu metode pihak lain. Apakah mungkin untuk mencegat metode? Misalkan saya ingin melihat apakah program A memicu metode D B dan melakukan sesuatu dengannya?
Benjamin

Tentang Notifikasi: notify-osd dipicu secara pasif oleh aplikasi lain, daripada secara aktif mencari sinyal. Bukankah itu tidak praktis atau apakah saya salah paham tentang Dbus? Saya ingin membuat aplikasi yang akan menggantikan notify-osd dan mengumpulkan pemberitahuan di semacam kotak masuk. Bisakah saya mencegat notifikasi dengan mendengarkan sinyal?
Benjamin

@Benjamin, yah, ketika Anda ingin mencegat panggilan metode yang diarahkan ke layanan asing, Anda kemungkinan besar berpikir tentang desain yang rusak. Apa yang harus Anda lakukan untuk mengganti memberitahu-OSD adalah untuk menulis sebuah program yang menyediakan itu org.freedesktop.Notificationslayanan. Dengan cara ini semua metode panggilan ke layanan ini akan ditangani oleh kode Anda.
ulidtko

Apa obejct "diri" itu?
kawing-chiu

10

Saya juga mencari solusi untuk mengumpulkan notifikasi desktop melalui dbus dengan skrip python. Pertanyaan ini adalah yang paling dekat yang saya dapatkan dengan googling, tetapi menulis pengganti notify-osd sepertinya berlebihan :)

Melihat sumber applet notifikasi baru-baru ini saya mendapat beberapa petunjuk bagaimana memonitor pesan dbus dan di sini adalah implementasi python saya datang dengan:

import gtk
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def filter_cb(bus, message):
    # the NameAcquired message comes through before match string gets applied
    if message.get_member() != "Notify":
        return
    args = message.get_args_list()
    # args are
    # (app_name, notification_id, icon, summary, body, actions, hints, timeout)
    print("Notification from app '%s'" % args[0])
    print("Summary: %s" % args[3])
    print("Body: %s", args[4])


DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
bus.add_match_string(
    "type='method_call',interface='org.freedesktop.Notifications',member='Notify'")
bus.add_message_filter(filter_cb)
gtk.main()

Semoga ini bisa membantu seseorang, karena tampaknya tidak ada banyak contoh python sederhana yang terkait dengan pemantauan pesan dbus.


1
Itu pasti membantu saya! Terima kasih banyak! Beberapa saran untuk Anda: "type = 'method_call'" tidak diperlukan, karena pemberitahuan hanya menggunakan panggilan metode. Tidak ada sinyal dalam spesifikasi. Juga, "member = 'Beritahu'" juga tidak diperlukan, karena Anda sudah memfilter itu di fungsi Anda (dan, seperti yang Anda katakan dengan benar, Anda tidak bisa menghindarinya karena NameAquiredpesan pertama )
MestreLion
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.