Как прочитать вывод dbus-monitor?

Я играю с 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
    

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

  2. Я заметил кое-что о связи между регулятором громкости и уведомлениями. Из того, что я прочитал с выхода 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
    

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

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

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

20
задан 12 November 2015 в 03:47

2 ответа

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

Рассмотрение источников апплета недавних уведомлений, я получил некоторые подсказки, как контролировать сообщения dbus и здесь являюсь реализацией Python, которую я придумал:

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.

10
ответ дан 12 November 2015 в 03:47

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

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

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

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

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

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

Сигналы

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

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, а объект «Я» - /org/ayatana/menu/DA00003. Сигнал имеет имя ItemPropertyUpdated, которое определено в интерфейсе org.ayatana.dbusmenu (как org.ayatana.dbusmenu::ItemPropertyUpdated в C ++). Серийный номер, я думаю, является своего рода уникальным идентификатором события в автобусе.

Затем мы видим сигнальные аргументы. Согласно документации интерфейса , первый аргумент int32 - это идентификатор элемента, вторая строка - имя его свойства, а третий вариант - значение свойства. Итак, объект /org/ayatana/menu/DA00003 уведомляет нас о том, что идентификатор элемента № 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. :) [один тысяча сто пятьдесят два]

0
ответ дан 12 November 2015 в 03:47

Другие вопросы по тегам:

Похожие вопросы: