Dbus-monitor çıkışı nasıl okunur?


20

Ubuntu ortamında dbus'un nasıl çalıştığını anlamak ve denemek için dbus-monitor ile oynuyorum . Bu konuda birkaç sorum var:

  1. Lütfen aşağıdakileri doğru bir şekilde nasıl okuyacağımı bana bildirir misiniz? Büyük fikri anlıyorum ama detayları değil.

    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
    

    İlki bir sinyal, ikincisi ise bir yöntem. Hedef , bir sinyal için belirli bir alıcı / slot olabileceği anlamına mı geliyor? Bir nedir üyesi ? Ve listenin öğeleri, sinyalin ardından gelen ve sinyalin içerdiği argümanlar mı? Nelerdir gönderen ve diziler ?

  2. Ses kontrolü ve bildirimler arasındaki ilişki hakkında bir şey fark ettim. Dbus-monitor çıkışından okuduklarımdan

    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
    

    Bildirimin yöntemiyle tetiklendiği anlaşılıyor. Sadece neden bu şekilde çalıştığını anlamıyorum. Benim görüşüme göre , bildirim bu sinyali dinleyip buna göre tepki verirken, "bildirim-ses-ses-orta-ortama" yayılan bir sinyal olup olmadığını daha mantıklı görecekti. Gönderme / alma özel değil halka açıksa, daha fazla esneklik ve verimlilik sağlayacak mı? Örneğin, "bildirim-ses-ses ortamı" için genel bir sinyal varsa o zaman birkaç uygulama bu sinyali dinleyebildi (bu, rakip bildirim uygulamalarının ortaya çıkmasına izin verecekti) ve geliştiricilerin sadece sinyal gönderme ile ilgilenmeleri gerekirken, bir sinyali almak ve yönetmek, bildiren uygulamanın işidir (ya da diğer bu sinyalleri gerektiren program).

  3. Sadece Dbus için yeniyim ve daha çok öğrenmek istiyorum, çünkü Python üzerinde Dbus ile çalışıyorum, özellikle bazı uygulamaları geliştirmek için. Dbus-python öğreticisini gördüm ve tüm sinyalleri nasıl dinleyeceğimi öğretiyor (ne arabirim ne de yol vb. Belirterek) Ama dbus-monitor gibi, çağrıldıklarında yöntemleri nasıl izleyebilirim?

Nasıl çalıştığını öğretme sabrınız varsa, memnuniyetle karşılıyorsunuz.

Yanıtlar:


24

D-Bus tanıtımı

  • D-Bus, hizmetler arasında iletişim kurmak için araçlar sağlar . Hizmetler olabilir anonim ve hizmetler edinebilirler: (1.6 gibi, otobüs adresi ile yalnızca tanımlanır) tanınmış isimler gibi, org.freedesktop.Notificationsya da org.freedesktop.NetworkManager. Kayıtlarda görebileceğiniz gönderici ve hedef, servislerdir. "Boş hedef" yayın anlamına gelir: tüm servislere teslimat.

  • Bir servis bir veya birkaç nesneyi veri yoluna aktarabilir . Nesnelere, veya gibi nesne yolları verilir . Nesne yolları, dosya sistemi yolları gibi ayırıcı olarak eğik çizgi kullanır./org/freedesktop/NetworkManager/ActiveConnection/1/org/ayatana/menu/DA00003

  • Her nesne bir veya birkaç arayüzü destekleyebilir . Bir arayüz, ortak olarak üyeler (OOP arayüzüne çok benzer) olarak bilinen bir dizi yöntem ve sinyalden başka bir şey değildir . Yöntemler ve sinyaller sabit imzalara sahiptir. Üyeler her zaman iyi bilinen arabirim isimlerinde isimlendirilir.

  • Bir kez yayınlandıktan sonra, iyi bilinen isimler asla değişmez .

  • Herhangi bir servis başka bir servisin sinyallerine bağlanabilir ve zaman uyumsuz olarak yöntemlerini çağırabilir. Herhangi bir servis sinyal yayabilir.

Sinyaller

Şimdi özel sorularınız için.

sinyal gönderici =: 1.1948 -> dest = (boş hedef) seri = 1829990 yol = / org / ayatana / menü / DA00003; arayüzü = org.ayatana.dbusmenu; elemanı = ItemPropertyUpdated
int32 23
"etkin" dizesi
değişken boolean true

Evet haklısın, bu bir sinyal. Hizmet tarafından yayınlandı :1.1948ve "öz" nesne /org/ayatana/menu/DA00003. Sinyal, ItemPropertyUpdatedarayüzde tanımlanmış bir isme sahiptir org.ayatana.dbusmenu( org.ayatana.dbusmenu::ItemPropertyUpdatedC ++ 'da olduğu gibi ). Seri, sanırım, otobüste olayın bir tür benzersiz tanımlayıcısı.

Sonra sinyal argümanlarını görürüz. Arabirim belgelerine göre , ilk int32 argümanı bir öğenin kimliği, ikinci dize onun özellik ismi ve üçüncü değişken özellik değeridir. Bu nedenle, /org/ayatana/menu/DA00003nesne bize # 23 öğe kimliğinin enabledözelliğini true olarak değiştirdiğini bildiriyor.


Sinyallere bir başka örnek:

sinyal gönderici =: 1.1602 -> dest = (boş hedef) seri = 20408 yol = / im / pidgin / mor / PurpleObject; arayüzü = im.pidgin.purple.PurpleInterface; elemanı = SendingChatMsg
   int32 47893
   "test" dizesi
   uint32 1
sinyal gönderici =: 1.1602 -> dest = (boş hedef) seri = 20409 yol = / im / pidgin / mor / PurpleObject; arayüzü = im.pidgin.purple.PurpleInterface; elemanı = IrcSendingText
   int32 64170
   "PRIVMSG #chat: test dizesi

Pidgin'i kullanarak bir IRC kanalına "test" mesajı gönderdim /im/pidgin/purple/PurpleObjectve im.pidgin.purple.PurpleInterfacearayüz altında iki sinyal verdim : ilk önce genel SendingChatMsg, sonra daha spesifik IrcSendingText.

Yöntemler

Şimdi yöntemler. Yöntemler, D-Bus nesnelerinden bir şey yapmalarını isteme veya bazı sorgulama ve veri döndürme yöntemleridir. D-Bus yöntemlerinin eşzamansız olarak adlandırılması dışında, klasik OOP yöntemlerine oldukça benzerler.

Programlı bir D-Bus metodu diyelim.

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

Argümanları, özellikle simge adını not edin. Örnekte "notification-audio-volume-medium"orta enerjili ses hoparlör simgesi oldu.

Müşteri Hizmetleri

Kendi D-Bus servislerinizi çalıştırmak, kendi D-Bus nesnelerinizi dışa aktarmak ve kendi D-Bus arayüzlerinizi kendi yöntem ve sinyallerinizle tanımlamak kesinlikle mümkündür. Tüm bunlar, genel konsepti kavrayarak ve dbusmodül belgelerini okuduğunuzda Python'da kolayca yapılabilir .:)


Bir ya da iki gün içinde müsait olamayamama rağmen görüşmeye açığız.
ulidtko

Teşekkürler :) Bu çok açıklığa kavuşturuyor. DFeet kullanırken, her göndericiye karşılık gelen bir işlem adı var, ancak bu, dbus-monitor çıktısına yansımamış, ancak göndericilerin anonim olması çok komik. İşlemler izlenebiliyor mu? Şimdi Python ile sinyal gönderebildiğimi veya yöntemler sağlayabileceğimi veya diğer tarafların yöntemlerini tetikleyebileceğimi gördüm. Metotlara müdahale etmek de mümkün mü? A programının B'nin Dbus yöntemini tetiklediğini ve bununla bir şey yapıp yapmadığını görmek istediğimi varsayalım.
Benjamin

Bildirimler Hakkında: notify-osd aktif olarak sinyal aramak yerine, diğer uygulamalar tarafından pasif olarak tetiklenir. Bu pratik değil mi, yoksa Dbus hakkında bir şeyler yanlış mı anladım? Notify-osd'un yerine geçecek ve bir tür gelen kutusunda bildirimleri toplayacak bir uygulama yapmak istiyorum. O zaman sinyalleri dinleyerek bildirimleri engelleyebilir miyim?
Benjamin

@ Benjamin, iyi, yabancı hizmetlere yönelik yöntem çağrıları engellemek istediğinizde, büyük olasılıkla kırık bir tasarım düşünün. Eğer-osd bildirmek yerine ne yapması gerektiğini bir program yazmaktır sağlarorg.freedesktop.Notifications hizmeti. Bu şekilde, bu hizmete yapılan tüm yöntemler kodunuz tarafından ele alınacaktır.
ulidtko

"Öz" obejct nedir?
kawing-chiu

10

Ayrıca bir python betiği ile dbus üzerinden masaüstü bildirimleri toplamak için bir çözüm arıyordum. Bu soru googling ile aldığım en yakınıydı, ancak notify-osd yerine bir yazı yazmak bir overkill gibiydi :)

En yeni bildirimler applet kaynaklarına baktığımda dbus mesajlarının nasıl izleneceği konusunda bazı ipuçları edindim ve işte burası şu anda bulduğum python uygulaması:

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()

Umarım bu, birisine yardımcı olur, öyle görünüyor ki, dbus mesajlarının izlenmesi ile ilgili pek çok basit python örneği yok.


1
Kesinlikle bana yardımcı oldu! Çok teşekkür ederim! Sizin için birkaç öneri: "type = 'method_call'" bildirimler sadece yöntem çağrıları kullandığından gereklilik değildir . Spesifikasyonda sinyal yok. Ayrıca, "member = 'Notify'" da gerekli değildir, çünkü işlevinizde zaten filtrelendiğinizden (ve doğru bir şekilde söylediğiniz gibi, ilk NameAquiredmesajdan dolayı bundan kaçınamazsınız )
MestreLion
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.