우분투 환경에서 dbus가 어떻게 작동하는지 이해하기 위해 dbus-monitor 를 가지고 놀고 있습니다. 이와 관련하여 몇 가지 질문이 있습니다.
-
다음을 올바르게 읽는 방법을 알려주시겠습니까? 나는 큰 아이디어를 이해하지만 세부 사항은 이해하지 못합니다.
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
알림이 메소드에 의해 트리거 된 것 같습니다. 왜 이런 식으로 작동하는지 이해하지 못합니다. 내 생각에, “알림-오디오-볼륨-중간” 방출되는 신호가 있다면 , 통지가이 신호를 듣고 그에 따라 반응 하는 것이 더 의미가있을 것이다. 송신 / 수신이 개인이 아닌 공개 인 경우 더 많은 유연성과 효율성을 허용하지 않습니까? 예를 들어 “알림-오디오-볼륨-중간” 에 대한 공개 신호가있는 경우 그런 다음 여러 응용 프로그램이이 신호를 수신 할 수 있으며 (경쟁 알림 응용 프로그램의 존재를 허용 할 수 있음) 개발자는 신호 전송에 관심을 가져야하지만 신호를 수집하고 처리하는 것은 응용 프로그램의 비즈니스 (또는 기타 해당 신호가 필요한 프로그램).
-
저는 Dbus를 처음 접했고 Python에서 Dbus와 함께 일하면서 주로 애플릿을 개발하기 위해 더 많은 것을 배우고 싶습니다. 나는 dbus-python 튜토리얼을 보았고 모든 인터페이스를 듣는 방법 (인터페이스 나 경로 등을 지정하지 않음)을 가르치고 있지만 dbus-monitor처럼 메소드가 호출 될 때 추적하는 방법은 무엇입니까?
그것이 어떻게 작동하는지 가르치는 인내심이 있다면 환영합니다.
답변
D- 버스 소개
-
D-Bus는 서비스 간 통신을위한 수단을 제공 합니다 . 서비스가 될 수 있습니다 익명 및 서비스는 aquire 수 있습니다 (1.6 같은 버스 주소만으로 확인) 잘 알려진 이름 처럼,
org.freedesktop.Notifications
또는org.freedesktop.NetworkManager
. 로그에서 볼 수있는 발신자와 대상은 서비스입니다. “널 대상”은 브로드 캐스트 : 모든 서비스로의 전송을 의미합니다. -
서비스는 하나 이상의 객체 를 버스로 내보낼 수 있습니다 . 객체에는 또는 과 같은 객체 경로 가 제공 됩니다. 객체 경로는 파일 시스템 경로와 같이 슬래시를 구분 기호로 사용합니다.
/org/freedesktop/NetworkManager/ActiveConnection/1
/org/ayatana/menu/DA00003
-
각 개체는 하나 이상의 인터페이스를 지원할 수 있습니다 . 인터페이스는 공칭 적으로 멤버 (OOP 인터페이스와 매우 유사)로 알려진 일련의 메소드 및 신호에 지나지 않습니다 . 방법과 신호에는 서명이 고정되어 있습니다. 멤버는 항상 잘 알려진 인터페이스 이름으로 네임 스페이스됩니다 .
-
일단 알려진 이름 은 변경되지 않습니다 .
-
모든 서비스는 다른 서비스의 신호에 연결하여 비동기 적으로 메소드를 호출 할 수 있습니다. 모든 서비스는 신호를 방출 할 수 있습니다.
신호
지금 당신의 구체적인 질문에.
신호 발신자 = : 1.1948-> 대상 = (널 대상) 시리얼 = 1829990 경로 = / org / ayatana / menu / DA00003; interface = org.ayatana.dbusmenu; member = ItemPropertyUpdated int32 23 문자열 "사용 가능" 변형 부울 true
예, 맞습니다. 이것은 신호입니다. service :1.1948
에 의해 방송되며 “self”객체는 /org/ayatana/menu/DA00003
입니다. 신호에는 ItemPropertyUpdated
인터페이스에 정의 된 이름 이 있습니다 org.ayatana.dbusmenu
( org.ayatana.dbusmenu::ItemPropertyUpdated
C ++ 에서처럼 ). 시리얼은 버스의 이벤트에 대한 일종의 고유 식별자라고 생각합니다.
그런 다음 신호 인수를 봅니다. 인터페이스 documentation 에 따르면 첫 번째 int32 인수는 항목의 id이고 두 번째 문자열은 속성 이름이며 세 번째 변형은 속성 값입니다. 따라서 /org/ayatana/menu/DA00003
객체는 항목 ID # 23이 enabled
속성을 true로 변경했음을 알려줍니다 .
신호에 대한 또 다른 예 :
신호 발신자 = : 1.1602-> 대상 = (널 대상) 시리얼 = 20408 경로 = / im / pidgin / purple / PurpleObject; interface = im.pidgin.purple.PurpleInterface; member = SendingChatMsg int32 47893 문자열 "test" uint32 1 신호 발신자 = : 1.1602-> 대상 = (널 대상) 시리얼 = 20409 경로 = / im / pidgin / purple / PurpleObject; interface = im.pidgin.purple.PurpleInterface; member = IrcSendingText int32 64170 문자열 "PRIVMSG #chat : test
I는 IRC 채널 피진을 사용하여 텍스트 메시지 “테스트”를 송신하고, /im/pidgin/purple/PurpleObject
언더 두 신호 출사 im.pidgin.purple.PurpleInterface
인터페이스 : 제 일반적인 SendingChatMsg
후보다 구체적인를 IrcSendingText
.
행동 양식
이제 방법. 메소드는 D-Bus 객체에 무언가를하도록 요청하거나 쿼리 및 리턴 데이터를 수행하는 방법입니다. D-Bus 메서드가 비동기 적으로 호출된다는 점을 제외하면 일반적인 OOP 메서드와 매우 유사합니다.
프로그래밍 방식으로 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 인터페이스를 정의 할 수 있습니다. 전체 개념을 파악하고 dbus
모듈 설명서를 읽으면 파이썬에서이 모든 작업을 쉽게 수행 할 수 있습니다 .:)
답변
또한 파이썬 스크립트로 dbus를 통해 데스크탑 알림을 수집하는 솔루션을 찾고있었습니다. 이 질문은 인터넷 검색에서 가장 가까운 질문이지만 notify-osd에 대한 대체품을 작성하는 것은 지나친 것처럼 보입니다. 🙂
최근 알림 애플릿 소스를 살펴보면 dbus 메시지를 모니터링하는 방법에 대한 힌트를 얻었으며 다음은 파이썬 구현입니다.
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()
dbus 메시지 모니터링과 관련된 간단한 파이썬 예제가 많지 않기 때문에 누군가에게 도움이되기를 바랍니다.