Làm thế nào để đọc đầu ra màn hình dbus?


20

Tôi đang chơi xung quanh với màn hình dbus để thử và hiểu cách thức hoạt động của dbus trong môi trường Ubuntu. Tôi có một số câu hỏi về vấn đề này:

  1. Bạn có thể vui lòng cho tôi biết làm thế nào để đọc đúng sau đây? Tôi hiểu ý tưởng lớn, nhưng không phải là chi tiết.

    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

    Tôi hiểu rằng cái đầu tiên là tín hiệu trong khi cái thứ hai là một phương thức. Có phải đích có nghĩa là có thể có một bộ thu / khe cụ thể cho tín hiệu không? Một là những gì thành viên ? Và các mục của danh sách có theo tín hiệu các đối số được truyền trong tín hiệu không? Người gửiserial là gì?

  2. Tôi nhận thấy điều gì đó về mối quan hệ giữa điều khiển âm lượng và thông báo. Từ những gì tôi đọc được từ đầu ra màn hình dbus

    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

    Có vẻ như thông báo được kích hoạt bởi phương thức của nó. Tôi thực sự không hiểu tại sao nó hoạt động theo cách này. Theo quan điểm của tôi, sẽ có ý nghĩa hơn nếu có một tín hiệu phát ra "thông báo-âm thanh-âm lượng trung bình" trong khi thông báo sẽ lắng nghe tín hiệu này và phản ứng tương ứng. Nếu việc gửi / nhận sẽ là công khai chứ không phải riêng tư, liệu nó có cho phép linh hoạt và hiệu quả hơn không? Chẳng hạn, nếu có tín hiệu chung cho "thông báo-âm thanh-âm lượng trung bình" sau đó một số ứng dụng có thể lắng nghe tín hiệu này (cho phép các ứng dụng thông báo cạnh tranh tồn tại) và các nhà phát triển sẽ phải quan tâm đến việc gửi tín hiệu, trong khi chọn và xử lý tín hiệu sẽ là doanh nghiệp của ứng dụng thông báo (hoặc bất kỳ ứng dụng nào khác chương trình cần những tín hiệu đó).

  3. Tôi chỉ mới làm quen với Dbus và muốn tìm hiểu thêm khi tôi làm việc với Dbus trên Python, chủ yếu để phát triển một số applet. Tôi đã xem hướng dẫn về dbus-python và nó dạy cách nghe tất cả các tín hiệu (bằng cách chỉ định cả giao diện và đường dẫn, v.v.) Nhưng làm thế nào để theo dõi các phương thức khi chúng được gọi, giống như màn hình dbus?

Nếu bạn có đủ kiên nhẫn để dạy cách thức hoạt động, bạn sẽ được chào đón.

Câu trả lời:


24

Giới thiệu xe buýt

  • D-Bus cung cấp phương tiện để liên lạc giữa các dịch vụ . Các dịch vụ có thể ẩn danh (chỉ được xác định bằng địa chỉ xe buýt, như: 1.6) và các dịch vụ có thể chứa các tên nổi tiếng , như org.freedesktop.Notificationshoặc org.freedesktop.NetworkManager. Người gửi và đích mà bạn có thể thấy trong nhật ký là các dịch vụ. "Null Destination" có nghĩa là phát sóng: giao hàng cho tất cả các dịch vụ.

  • Một dịch vụ có thể xuất một hoặc một số đối tượng lên xe buýt. Các đối tượng được đưa ra đường dẫn đối tượng , như /org/freedesktop/NetworkManager/ActiveConnection/1hoặc /org/ayatana/menu/DA00003. Đường dẫn đối tượng sử dụng dấu gạch chéo làm dấu phân cách, giống như đường dẫn hệ thống tập tin.

  • Mỗi đối tượng có thể hỗ trợ một hoặc một vài giao diện . Một giao diện không có gì khác hơn là một tập hợp các phương thức và tín hiệu, thường được gọi là thành viên (rất giống với giao diện OOP). Phương pháp và tín hiệu có chữ ký cố định. Các thành viên luôn được đặt tên trong các tên giao diện nổi tiếng .

  • Sau khi được công bố, những cái tên nổi tiếng không bao giờ thay đổi .

  • Bất kỳ dịch vụ nào cũng có thể kết nối với tín hiệu của dịch vụ khác và gọi không đồng bộ các phương thức của dịch vụ đó. Bất kỳ dịch vụ có thể phát ra tín hiệu.

Tín hiệu

Bây giờ đến câu hỏi cụ thể của bạn.

người gửi tín hiệu =: 1.1948 -> mệnh = (null đích) nối tiếp = 1829990 đường dẫn = / org / ayatana / menu / DA00003; giao diện = org.ayatana.dbusmenu; thành viên = ItemPropertyUpdated
int32 23
chuỗi "đã bật"
biến thể boolean đúng

Vâng, bạn đã đúng, đây là một tín hiệu. Nó được phát sóng bởi dịch vụ :1.1948và đối tượng "tự" là /org/ayatana/menu/DA00003. Tín hiệu có tên ItemPropertyUpdatedđược xác định trong giao diện org.ayatana.dbusmenu(như org.ayatana.dbusmenu::ItemPropertyUpdatedtrong C ++). Theo tôi, sê-ri là một loại định danh duy nhất của sự kiện trên xe buýt.

Sau đó, chúng ta thấy các đối số tín hiệu. Theo tài liệu giao diện , đối số int32 đầu tiên là id của một mục, chuỗi thứ hai là tên thuộc tính của nó và biến thể thứ ba là giá trị thuộc tính. Vì vậy, /org/ayatana/menu/DA00003đối tượng thông báo cho chúng tôi rằng id mục # 23 đã thay đổi thuộc tính của nó enabledthành true.


Một ví dụ khác về tín hiệu:

người gửi tín hiệu =: 1.1602 -> mệnh = (null đích) nối tiếp = 20408 đường dẫn = / im / pidgin / tím / PurpleObject; giao diện = im.pidgin.purple.PurpleInterface; thành viên = SendingChatMsg
   int32 47893
   chuỗi "kiểm tra"
   uint32 1
người gửi tín hiệu =: 1.1602 -> Dest = (null đích) nối tiếp = 20409 đường dẫn = / im / pidgin / tím / PurpleObject; giao diện = im.pidgin.purple.PurpleInterface; thành viên = IrcSendingText
   int32 64170
   chuỗi "PRIVMSG #chat: kiểm tra

Tôi đã gửi một tin nhắn văn bản "kiểm tra" bằng cách sử dụng Pidgin tới kênh IRC và /im/pidgin/purple/PurpleObjectphát ra hai tín hiệu dưới im.pidgin.purple.PurpleInterfacegiao diện: đầu tiên là chung SendingChatMsg, sau đó là cụ thể hơn IrcSendingText.

Phương pháp

Bây giờ phương pháp. Phương thức là một cách để yêu cầu các đối tượng D-Bus thực hiện điều gì đó hoặc thực hiện một số truy vấn và trả về dữ liệu. Chúng khá giống với các phương thức OOP cổ điển, ngoại trừ các phương thức D-Bus được gọi là không đồng bộ.

Chúng ta hãy gọi một phương thức D-Bus theo chương trình.

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

Lưu ý các đối số, đặc biệt là tên biểu tượng. Trong ví dụ của bạn "notification-audio-volume-medium"là biểu tượng của loa âm lượng trung bình.

Chăm sóc khách hàng

Hoàn toàn có thể chạy các dịch vụ D-Bus của riêng bạn, xuất các đối tượng D-Bus của riêng bạn và xác định giao diện D-Bus của riêng bạn bằng các phương thức và tín hiệu của riêng bạn. Tất cả điều này có thể được thực hiện trong Python khá dễ dàng khi bạn nắm được khái niệm tổng thể và đọc dbustài liệu mô-đun.:)


Thảo luận được hoan nghênh, mặc dù tôi có thể không có sẵn trong một hoặc hai ngày.
ulidtko

Cảm ơn :) Điều này làm rõ rất nhiều. Thật buồn cười khi người gửi có thể ẩn danh, khi tôi sử dụng DFeet, có một tên quy trình tương ứng với mỗi người gửi, nhưng điều đó không phản ánh trong đầu ra của màn hình dbus. Các quá trình có thể được truy tìm? Bây giờ với Python tôi đã thấy tôi có thể gửi tín hiệu hoặc cung cấp các phương thức hoặc kích hoạt các phương thức của các bên khác. Có phải cũng có thể đánh chặn các phương pháp? Giả sử tôi muốn xem liệu chương trình A có kích hoạt phương thức Dbus của B không và làm gì với nó?
Benjamin

Về Thông báo: osd thông báo được kích hoạt thụ động bởi các ứng dụng khác, thay vì chủ động tìm kiếm tín hiệu. Điều đó không thực tế hay tôi hiểu nhầm điều gì về Dbus? Tôi muốn tạo một ứng dụng thay thế thông báo osd và thu thập thông báo trong một loại hộp thư đến. Tôi có thể chặn thông báo bằng cách nghe tín hiệu không?
Benjamin

@Benjamin, tốt, khi bạn muốn chặn các cuộc gọi phương thức hướng đến các dịch vụ nước ngoài, bạn rất có thể nghĩ đến một thiết kế bị hỏng. Bạn nên làm gì để thay thế thông báo-OSD là viết một chương trình mà cung cấp các org.freedesktop.Notificationsdịch vụ. Bằng cách này, tất cả các phương thức gọi đến dịch vụ này sẽ được xử lý bởi mã của bạn.
ulidtko

"Tự" obejct là gì?
kawing-chiu

10

Tôi cũng đang tìm giải pháp để thu thập các thông báo trên máy tính để bàn thông qua dbus với một kịch bản python. Câu hỏi này là câu hỏi gần nhất mà tôi có với googling, nhưng viết một thay thế cho thông báo-osd có vẻ như là một sự quá mức :)

Nhìn vào các nguồn applet thông báo gần đây, tôi có một số gợi ý về cách theo dõi các tin nhắn dbus và đây là cách triển khai python mà tôi đã đưa ra:

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()

Hy vọng điều này sẽ giúp được ai đó, vì dường như không có nhiều ví dụ python đơn giản liên quan đến việc theo dõi các thông điệp dbus.


1
Nó chắc chắn đã giúp tôi! Cảm ơn nhiều! Một vài gợi ý cho bạn: "type = 'method_call'" là không cần thiết, vì các thông báo chỉ sử dụng các cuộc gọi phương thức. Không có tín hiệu trong thông số kỹ thuật. Ngoài ra, "thành viên = 'Thông báo'" cũng không cần thiết, vì bạn đã lọc điều đó trong chức năng của mình (và, như bạn đã nói chính xác, bạn không thể tránh điều đó do NameAquiredtin nhắn đầu tiên )
MestreLion
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.