จะอ่านเอาต์พุต dbus-monitor ได้อย่างไร?


20

ฉันกำลังเล่นกับ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
    

    ดูเหมือนว่าการแจ้งเตือนจะดำเนินการโดยวิธีการของมัน ฉันแค่ไม่เข้าใจจริงๆว่าทำไมมันถึงทำงานแบบนี้ ในมุมมองของฉันมันจะสมเหตุสมผลถ้ามีสัญญาณที่ปล่อยออกมา"การแจ้งเตือน - เสียง - ระดับเสียง - กลาง"ในขณะที่การแจ้งเตือนจะฟังสัญญาณนี้และตอบสนองตามนั้น หากการส่ง / รับเป็นสาธารณะมากกว่าส่วนตัวจะไม่อนุญาตให้มีความยืดหยุ่นและประสิทธิภาพมากขึ้นใช่ไหม เช่นหากมีสัญญาณสาธารณะสำหรับ"การแจ้งเตือน - เสียง - ปริมาณ - สื่อ" แอพพลิเคชั่นหลายตัวสามารถฟังสัญญาณนี้ (ซึ่งจะช่วยให้แอปพลิเคชั่นแจ้งเตือนการแข่งขันมีอยู่) และนักพัฒนาจะต้องกังวลเกี่ยวกับการส่งสัญญาณในขณะที่การหยิบขึ้นมาและจัดการสัญญาณจะเป็นธุรกิจของแอปพลิเคชัน โปรแกรมที่ต้องการสัญญาณเหล่านั้น)

  3. ฉันเพิ่งใหม่กับ Dbus และต้องการเรียนรู้เพิ่มเติมขณะที่ฉันทำงานกับ Dbus บน Python เพื่อพัฒนาแอปเพล็ตเป็นหลัก ฉันได้เห็นการสอนของ dbus-pythonแล้วและมันสอนวิธีการฟังสัญญาณทั้งหมด (โดยการระบุทั้งอินเตอร์เฟสหรือพา ธ ฯลฯ ) แต่จะติดตามวิธีการเมื่อมีการเรียกเช่นเดียวกับ dbus-monitor

หากคุณมีความอดทนในการสอนวิธีการทำงานคุณก็ยินดีต้อนรับ

คำตอบ:


24

แนะนำ D-Bus

  • D-Bus จัดให้มีวิธีการสื่อสารระหว่างบริการต่างๆ บริการสามารถระบุชื่อ (ระบุ แต่เพียงผู้เดียวโดยรถบัสอยู่เช่น: 1.6) และบริการสามารถ aquire ชื่อที่รู้จักกันดีเช่นหรือorg.freedesktop.Notifications org.freedesktop.NetworkManagerผู้ส่งและปลายทางที่คุณสามารถดูได้ในบันทึกเป็นบริการ "ปลายทางว่างเปล่า" หมายถึงการออกอากาศ: ส่งไปยังบริการทั้งหมด

  • บริการสามารถส่งออกหนึ่งหรือหลายวัตถุไปยังรถบัส วัตถุที่จะได้รับทางวัตถุเหมือนหรือ/org/freedesktop/NetworkManager/ActiveConnection/1 /org/ayatana/menu/DA00003เส้นทางวัตถุใช้เครื่องหมายทับเป็นตัวคั่นเช่นเส้นทางระบบแฟ้ม

  • แต่ละวัตถุที่สามารถรองรับการอย่างใดอย่างหนึ่งหรือหลายอินเตอร์เฟซ อินเทอร์เฟซคืออะไรมากไปกว่าชุดของวิธีการและสัญญาณที่รู้จักกันในนาม coloquially ในฐานะสมาชิก (คล้ายกับส่วนต่อประสาน OOP) วิธีการและสัญญาณมีลายเซ็นคงที่ สมาชิกจะถูกกำหนดชื่อไว้เสมอภายในชื่ออินเทอร์เฟซที่รู้จักกันดี

  • เมื่อตีพิมพ์ชื่อที่รู้จักกันดีไม่เคยเปลี่ยน

  • บริการใด ๆ สามารถเชื่อมต่อกับสัญญาณของบริการอื่นและเรียกใช้วิธีการแบบอะซิงโครนัส บริการใด ๆ สามารถส่งสัญญาณ

สัญญาณ

ตอนนี้สำหรับคำถามเฉพาะของคุณ

ผู้ส่งสัญญาณ =: 1.1948 -> ปลายทาง = (ปลายทางปลายทาง) อนุกรม = 1829990 เส้นทาง = / org / ayatana / เมนู / DA00003; อินเตอร์เฟซ = org.ayatana.dbusmenu; สมาชิก = ItemPropertyUpdated
int32 23
สตริง "เปิดใช้งาน"
บูลีนตัวแปรจริง

ใช่คุณพูดถูกนี่เป็นสัญญาณ มันออกอากาศโดยบริการ:1.1948และ "ตัวเอง" /org/ayatana/menu/DA00003เป็นวัตถุ สัญญาณมีชื่อItemPropertyUpdatedซึ่งกำหนดไว้ในอินเทอร์เฟซorg.ayatana.dbusmenu(เช่นorg.ayatana.dbusmenu::ItemPropertyUpdatedใน C ++) ฉันเดาว่าอนุกรมเป็นตัวระบุที่ไม่ซ้ำใครของเหตุการณ์บนรถบัส

จากนั้นเราจะเห็นข้อโต้แย้งสัญญาณ ตามเอกสารประกอบอินเตอร์เฟสอาร์กิวเมนต์ int32 แรกคือ id ของไอเท็มสตริงที่สองคือชื่อคุณสมบัติและตัวแปรที่สามคือค่าคุณสมบัติ ดังนั้น/org/ayatana/menu/DA00003วัตถุจึงแจ้งให้เราทราบว่ารหัสรายการ # 23 เปลี่ยนenabledคุณสมบัติเป็นจริง


อีกตัวอย่างหนึ่งเกี่ยวกับสัญญาณ:

ผู้ส่งสัญญาณ =: 1.1602 -> ปลายทาง = (ปลายทางปลายทาง) อนุกรม = 20408 เส้นทาง = / im / pidgin / purple / PurpleObject; อินเตอร์เฟซ = im.pidgin.purple.PurpleInterface; สมาชิก = SendingChatMsg
   int32 47893
   สตริง "ทดสอบ"
   uint32 1
ผู้ส่งสัญญาณ =: 1.1602 -> dest = (ปลายทางปลายทาง) อนุกรม = 20409 เส้นทาง = / im / pidgin / purple / PurpleObject; อินเตอร์เฟซ = im.pidgin.purple.PurpleInterface; สมาชิก = IrcSendingText
   int32 64170
   สตริง "PRIVMSG #chat: ทดสอบ

ฉันส่งข้อความทดสอบ "" ใช้ Pidgin เพื่อเป็นช่องทาง IRC และ/im/pidgin/purple/PurpleObjectปล่อยออกมาส่งสัญญาณสองภายใต้im.pidgin.purple.PurpleInterfaceอินเตอร์เฟซ: ครั้งแรกทั่วไปแล้วเฉพาะเจาะจงมากขึ้นSendingChatMsgIrcSendingText

วิธีการ

ตอนนี้วิธีการ เมธอดเป็นวิธีที่จะขอให้วัตถุ 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

หมายเหตุข้อโต้แย้งโดยเฉพาะชื่อไอคอน ในตัวอย่างของคุณ"notification-audio-volume-medium"คือไอคอนของลำโพงเสียงกลาง

บริการที่กำหนดเอง

เป็นไปได้อย่างแน่นอนที่จะเรียกใช้บริการ D-Bus ของคุณเองส่งออกวัตถุ D-Bus ของคุณเองและกำหนดอินเทอร์เฟซ D-Bus ของคุณเองด้วยวิธีการและสัญญาณของคุณเอง ทั้งหมดนี้สามารถทำได้ใน Python ค่อนข้างง่ายเมื่อคุณเข้าใจแนวคิดโดยรวมและอ่านdbusเอกสารประกอบของโมดูล:)


การสนทนายินดีต้อนรับแม้ว่าฉันอาจไม่สามารถใช้ได้ในหนึ่งหรือสองวัน
ulidtko

ขอบคุณ :) สิ่งนี้ชัดเจนมาก เป็นเรื่องตลกที่ผู้ส่งสามารถระบุชื่อได้เมื่อฉันใช้ DFeet มีชื่อกระบวนการที่ตรงกับผู้ส่งแต่ละคน แต่นั่นไม่ได้สะท้อนในเอาต์พุต dbus-monitor สามารถติดตามกระบวนการได้หรือไม่? ตอนนี้ด้วย Python ฉันได้เห็นว่าฉันสามารถส่งสัญญาณหรือให้วิธีการหรือทริกเกอร์วิธีการของฝ่ายอื่น มันเป็นไปได้ที่จะสกัดกั้นวิธี? สมมติว่าฉันต้องการดูว่าโปรแกรม A เรียกใช้วิธี Dbus ของ B แล้วทำอะไรกับมันบ้าง?
Benjamin

เกี่ยวกับการแจ้งเตือน: alert-osd ถูกทริกเกอร์โดยแอปพลิเคชั่นอื่น ๆ แทนที่จะมองหาสัญญาณอย่างแข็งขัน มันไม่จริงหรือฉันเข้าใจผิดเกี่ยวกับ Dbus เหรอ? ฉันต้องการสร้างแอปพลิเคชั่นที่จะแทนที่ alert-osd และรวบรวมการแจ้งเตือนในรูปแบบของกล่องจดหมาย ฉันสามารถสกัดกั้นการแจ้งเตือนโดยการฟังสัญญาณได้หรือไม่?
Benjamin

@Benjamin ดีเมื่อคุณต้องการที่จะสกัดกั้นวิธีการโทรไปยังบริการต่างประเทศคุณอาจคิดว่าการออกแบบที่แตกสลาย สิ่งที่คุณควรจะทำอย่างไรที่จะมาแทนที่แจ้ง-OSD คือการเขียนโปรแกรมที่ให้org.freedesktop.Notificationsบริการ วิธีนี้ทุกวิธีการโทรไปยังบริการนี้จะได้รับการจัดการโดยรหัสของคุณ
ulidtko

obejct "ตัวเอง" คืออะไร?
kawing-chiu

10

ฉันยังหาวิธีแก้ปัญหาเพื่อรวบรวมการแจ้งเตือนบนเดสก์ท็อปผ่าน dbus ด้วยสคริปต์ python คำถามนี้เป็นคำถามที่ใกล้เคียงที่สุดที่ฉันได้รับพร้อมกับ googling แต่การเขียนข้อความแจ้งเตือน osd แทน osd นั้นดูเหมือนว่าเป็น overkill :)

ดูแหล่งที่มาของแอปเพล็ตการแจ้งเตือนล่าสุดฉันมีคำแนะนำบางอย่างเกี่ยวกับวิธีการตรวจสอบข้อความ 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()

หวังว่านี่จะช่วยให้ใครบางคนดูเหมือนว่าไม่มีตัวอย่างงูหลามที่เกี่ยวข้องกับการตรวจสอบข้อความ dbus


1
มันช่วยฉันได้อย่างแน่นอน! ขอบคุณมาก! คำแนะนำเล็กน้อยสำหรับคุณ: "type = 'method_call'" ไม่จำเป็นเนื่องจากการแจ้งเตือนใช้การเรียกใช้เมธอดเท่านั้น ไม่มีสัญญาณในสเป็ค นอกจากนี้ "member = 'Notify'" ก็ไม่จำเป็นเช่นกันเนื่องจากคุณได้กรองสิ่งที่อยู่ในฟังก์ชั่นของคุณแล้ว (และอย่างที่คุณพูดถูกต้องคุณไม่สามารถหลีกเลี่ยงได้เนื่องจากNameAquiredข้อความแรก)
MestreLion
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.