Как читать выход dbus-монитора?

19

Я играю с dbus-monitor , чтобы попытаться понять, как работает dbus Среда Ubuntu. У меня есть несколько вопросов в этом отношении:

  1. Не могли бы вы дать мне знать, как правильно читать следующее? Я понимаю большую идею, но не подробности.

    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
    

    Я понимаю, что первый - это сигнал, а второй - метод. Назначение destination означает, что может быть конкретный приемник / слот для сигнала? Что означает ? И являются ли элементы списка, следующие за сигналом, аргументами, переданными в сигнале? Что такое отправитель и сериалы ?

  2. Я заметил что-то о связи между контролем громкости и уведомлениями. Из того, что я прочитал с выхода dbus-монитора

    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
    

    Кажется, что уведомление вызвано его методом. Я просто не понимаю, почему это работает. На мой взгляд, было бы более разумным, если бы был сигнал, излучаемый «уведомление-аудио-объем-среда» , в то время как уведомление прослушивало этот сигнал и соответствующим образом реагировало. Если отправка / получение будет публичной, а не частной, не позволит ли она обеспечить большую гибкость и эффективность? Например, если был общедоступный сигнал для "notification-audio-volume-medium" , тогда несколько приложений могли бы прослушивать этот сигнал (что позволило бы создать конкурирующие приложения для уведомлений), и разработчики просто должны быть связаны с отправкой сигналов, в то время как сбор и обработка сигнала будет уведомляющим бизнесом приложения (или любой другой программой, которая нуждается в этих сигналах).

  3. Я просто новичок в Dbus и хочу узнать больше, поскольку я работаю с Dbus на Python, в основном для разработки некоторых апплетов. Я видел учебник dbus-python и он учит, как слушать все сигналы (не указав ни интерфейс, ни путь и т. д.). Но как отслеживать методы при их вызове, например, dbus-monitor?

Если у вас есть терпение, чтобы научить, как это работает, пожалуйста.

    
задан Benjamin 01.05.2011 в 08:18
источник

2 ответа

23

Введение в D-Bus

  • D-Bus предоставляет средства для связи между услугами . Услуги могут быть анонимными (идентифицированы исключительно по адресу шины, например: 1.6), а сервисы могут использовать известные имена , например org.freedesktop.Notifications или org.freedesktop.NetworkManager . Отправителем и получателем, которые вы можете видеть в журналах, являются сервисы. «Null destination» означает трансляцию: доставка всем службам.

  • Служба может экспортировать один или несколько объектов на шину. Объектам присваиваются пути объектов , например /org/freedesktop/NetworkManager/ActiveConnection/1 или /org/ayatana/menu/DA00003 . Пути объектов используют слэш как разделитель, например пути файловой системы.

  • Каждый объект может поддерживать один или несколько интерфейсов . Интерфейс - это не что иное, как набор методов и сигналов, которые широко известны как members (очень похожие на интерфейс OOP). Методы и сигналы имеют фиксированные подписи. Члены всегда именуются в именах интерфейсов известных .

  • После опубликования известные имена никогда не меняются .

  • Любая служба может подключаться к сигналам другой службы и асинхронно вызывать ее методы. Любая служба может излучать сигналы.

Сигналы

Теперь к вашим конкретным вопросам.

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

Да, вы правы, это сигнал. Он транслируется службой :1.1948 , а «self» - /org/ayatana/menu/DA00003 . Сигнал имеет имя ItemPropertyUpdated , которое определено в интерфейсе org.ayatana.dbusmenu (например, org.ayatana.dbusmenu::ItemPropertyUpdated в C ++). Серийный, я думаю, является своего рода уникальным идентификатором события на шине.

Затем мы видим аргументы сигнала. Согласно документации по интерфейсу , первый аргумент int32 - это идентификатор элемента, вторая строка - его имя свойства, а третий вариант - значение свойства. Таким образом, объект /org/ayatana/menu/DA00003 уведомляет нас что элемент id # 23 изменил свое свойство enabled на true.

Другой пример сигналов:

signal sender=:1.1602 -> dest=(null destination) serial=20408 path=/im/pidgin/purple/PurpleObject; interface=im.pidgin.purple.PurpleInterface; member=SendingChatMsg
   int32 47893
   string "test"
   uint32 1
signal sender=:1.1602 -> dest=(null destination) serial=20409 path=/im/pidgin/purple/PurpleObject; interface=im.pidgin.purple.PurpleInterface; member=IrcSendingText
   int32 64170
   string "PRIVMSG #chat :test

Я отправил текстовое сообщение «test», используя Pidgin для канала IRC, и /im/pidgin/purple/PurpleObject выбрали два сигнала в интерфейсе im.pidgin.purple.PurpleInterface : сначала общий SendingChatMsg , затем более конкретный IrcSendingText .

Методы

Теперь методы. Методы - это способ спросить объекты D-Bus что-то сделать или выполнить некоторые запросы и вернуть данные. Они очень похожи на классические методы ООП, за исключением того, что методы D-Bus называются асинхронно.

Мы будем называть метод D-Bus программным способом.

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

Обратите внимание на аргументы, особенно на имя значка. В вашем примере "notification-audio-volume-medium" был символом громкоговорителя среднего уровня.

Пользовательские службы

Абсолютно можно запускать собственные службы D-Bus, экспортировать собственные объекты D-Bus и определять свои собственные интерфейсы D-Bus с помощью собственных методов и сигналов. Все это можно сделать в Python довольно легко, как только вы поймете общую концепцию и прочитаете документацию модуля dbus . :)

    
ответ дан ulidtko 01.05.2011 в 12:31
источник
10

Я также искал решение для сбора уведомлений на рабочем столе через dbus с помощью скрипта python. Этот вопрос был самым близким, с которым я столкнулся с поисковой системой, но написать замену для уведомления-osd было похоже на перебор:)

Глядя на последние уведомления в источниках апплета, я получил несколько советов о том, как отслеживать сообщения dbus, и вот реализация python I придумал:

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

Надеюсь, это поможет кому-то, поскольку, кажется, не так много простых примеров python, связанных с мониторингом сообщений dbus.

    
ответ дан Keto 27.05.2012 в 12:23