ney*_*rec 24 notification python dbus application-development
我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)
我知道第一个是信号,而第二个是方法。目的地是否意味着信号可以有特定的接收器/插槽?什么是会员?信号后面的列表项是信号中传递的参数吗?什么是发件人和连续出版物?
我注意到音量控制和通知之间的关系。从我从 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
Run Code Online (Sandbox Code Playgroud)
似乎通知是由其方法触发的。我只是不明白为什么它会这样工作。在我看来,如果有一个信号发出“通知-音频-音量-媒体”,而通知会监听这个信号并做出相应的反应,那会更有意义。如果发送/接收是公开的而不是私人的,它会不会允许更多的灵活性和效率?例如,如果有一个“通知-音频-音量-中等”的公共信号 然后几个应用程序可以监听这个信号(这将允许竞争的通知应用程序存在),开发人员只需要关心发送信号,而接收和处理信号将是通知应用程序的业务(或任何其他需要这些信号的程序)。
我刚接触 Dbus,想了解更多,因为我在 Python 上使用 Dbus,主要是为了开发一些小程序。我看过dbus-python 教程,它教如何监听所有信号(通过既不指定接口也不指定路径等)但是如何在调用方法时跟踪方法,就像 dbus-monitor 那样?
如果你有耐心教它是如何工作的,欢迎你。
uli*_*tko 31
D-Bus 提供了服务之间通信的手段。服务可以是匿名的(仅由总线地址标识,例如 :1.6),并且服务可以获取众所周知的名称,例如org.freedesktop.Notifications
或org.freedesktop.NetworkManager
。您可以在日志中看到的发送方和目的地是服务。“空目的地”意味着广播:传送到所有服务。
一项服务可以将一个或多个对象导出到总线。对象被赋予对象路径,如/org/freedesktop/NetworkManager/ActiveConnection/1
或/org/ayatana/menu/DA00003
。对象路径使用斜杠作为分隔符,就像文件系统路径一样。
每个对象可以支持一个或多个接口。一个接口只不过是一组方法和信号,通俗地称为成员(非常类似于 OOP 接口)。方法和信号具有固定的签名。成员总是在众所周知的接口名称中命名空间。
一经出版,知名的名字永远不会改变。
任何服务都可以连接到另一个服务的信号并异步调用其方法。任何服务都可以发出信号。
现在回答你的具体问题。
信号发送者=:1.1948 -> dest=(空目的地)serial=1829990 path=/org/ayatana/menu/DA00003;interface=org.ayatana.dbusmenu; 成员=ItemPropertyUpdated int32 23 字符串“启用” 变体布尔真
是的,你没看错,这是一个信号。它由 service 广播:1.1948
,“self”对象是/org/ayatana/menu/DA00003
. 信号具有ItemPropertyUpdated
在接口中定义的名称org.ayatana.dbusmenu
(如org.ayatana.dbusmenu::ItemPropertyUpdated
在 C++ 中)。我猜,串行是总线上事件的一种唯一标识符。
然后我们看到信号参数。根据接口文档,第一个 int32 参数是项目的 id,第二个字符串是其属性名称,第三个变量是属性值。因此,该/org/ayatana/menu/DA00003
对象通知我们项目 id #23 将其enabled
属性更改为 true。
信号的另一个例子:
信号发送者=:1.1602 -> dest=(空目的地)serial=20408 path=/im/pidgin/purple/PurpleObject;接口=im.pidgin.purple.PurpleInterface; 会员=发送ChatMsg int32 47893 字符串“测试” uint32 1 信号发送者=:1.1602 -> dest=(空目的地)serial=20409 path=/im/pidgin/purple/PurpleObject;接口=im.pidgin.purple.PurpleInterface; 成员=IrcSendingText int32 64170 字符串 "PRIVMSG #chat :test
我使用 Pidgin 向 IRC 频道发送了一条短信“测试”,并/im/pidgin/purple/PurpleObject
在im.pidgin.purple.PurpleInterface
界面下发出了两个信号:首先是一个通用的SendingChatMsg
,然后是更具体的IrcSendingText
.
现在方法。方法是一种要求 D-Bus 对象做某事,或执行一些查询并返回数据的方法。它们与经典的 OOP 方法非常相似,只是 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
Run Code Online (Sandbox Code Playgroud)
注意参数,尤其是图标名称。在您的示例中"notification-audio-volume-medium"
是中等功率音量扬声器的图标。
完全可以运行您自己的 D-Bus 服务、导出您自己的 D-Bus 对象并使用您自己的方法和信号定义您自己的 D-Bus 接口。一旦您掌握了整体概念并阅读了dbus
模块文档,这一切都可以在 Python 中轻松完成。:)
小智 12
我也在寻找使用 python 脚本通过 dbus 收集桌面通知的解决方案。这个问题是我通过谷歌搜索得到的最接近的问题,但是为 notify-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()
Run Code Online (Sandbox Code Playgroud)
希望这对某人有所帮助,因为似乎没有很多与监视 dbus 消息相关的简单 python 示例。