Я играю с dbus-monitor , чтобы попытаться понять, как работает dbus в среде Ubuntu. У меня есть несколько вопросов на этот счет:
Не могли бы вы дать мне знать, как правильно читать следующее? Я понимаю большую идею, но не детали.
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
Я понял, что первый - это сигнал, а второй - метод. Означает ли пункт назначения , что может быть определенный приемник / слот для сигнала? Что такое участник ? И соответствуют ли пункты списка сигналу аргументы, передаваемые в сигнале? Что такое отправитель и сериалы ?
Я заметил кое-что о связи между регулятором громкости и уведомлениями. Из того, что я прочитал с выхода 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» , в то время как уведомление будет прослушивать этот сигнал и реагировать соответствующим образом. Если бы отправка / получение было бы общедоступным, а не частным, разве это не позволило бы повысить гибкость и эффективность? Например, если бы был публичный сигнал для «уведомления-аудио-громкость-среда» , то несколько приложений могли бы прослушивать этот сигнал (что позволило бы появиться конкурирующим приложениям для уведомления), и разработчики просто имели бы заботиться об отправке сигналов, в то время как получение и обработка сигнала были бы делом уведомляющего приложения (или любой другой программы, которая нуждается в этих сигналах).
Я просто новичок в Dbus и хочу узнать больше, поскольку я работаю с Dbus на Python, главным образом над разработкой некоторых апплетов. Я видел руководство по dbus-python , и оно учит, как прослушивать все сигналы (не указывая ни интерфейс, ни путь и т. Д.). Но как отслеживать методы, когда они вызываются, как это делает dbus-monitor?
Если у вас есть терпение учить, как это работает, милости просим.
Я также искал решение собрать настольные уведомления через 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.
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 trueblockquote>Да, вы правы, это сигнал. Он транслируется службой
: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
.:)
[один тысяча сто пятьдесят два]