¿Cómo leer la salida dbus-monitor?

17

Estoy jugando con dbus-monitor para intentar comprender cómo está trabajando dbus. Entorno de Ubuntu. Tengo varias preguntas al respecto:

  1. ¿Podría decirme cómo leer los siguientes correctamente? Entiendo la gran idea, pero no los detalles.

    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
    

    Entiendo que el primero es una señal, mientras que el segundo es un método. ¿ destino significa que puede haber un receptor / slot específico para una señal? ¿Qué es un miembro ? ¿Y los elementos de la lista que siguen a la señal son los argumentos aprobados en la señal? ¿Qué son remitente y publicaciones seriadas ?

  2. Noté algo sobre la relación entre el control de volumen y las notificaciones. Por lo que leí de la salida del monitor 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
    

    Parece que la notificación se desencadena por su método. Simplemente no entiendo por qué funciona de esta manera. En mi opinión, tendría más sentido si hubiera una señal emitida "notificación-audio-volumen-medio" mientras la notificación escucharía esta señal y reaccionaría en consecuencia. Si el envío / recepción sería público en lugar de privado, ¿no permitiría una mayor flexibilidad y eficiencia? Por ejemplo, si hubiera una señal pública para "notification-audio-volume-medium" , varias aplicaciones podrían escuchar esta señal (lo que permitiría la existencia de aplicaciones de notificación competidoras) y los desarrolladores solo tiene que preocuparse por enviar señales, mientras que levantar y manejar una señal sería el negocio de la aplicación notificante (o cualquier otro programa que necesite esas señales).

  3. Soy nuevo en Dbus y quiero aprender más ya que estoy trabajando con Dbus en Python, principalmente para desarrollar algunos applets. He visto el tutorial dbus-python y enseña cómo escuchar todas las señales (al especificar ni la interfaz ni la ruta, etc.) ¿Pero cómo rastrear los métodos cuando son llamados, como dbus-monitor?

Si tienes la paciencia para enseñar cómo funciona eso, de nada.

    
pregunta Benjamin 01.05.2011 - 08:18

2 respuestas

21

Introducción a D-Bus

  • D-Bus proporciona medios para comunicarse entre servicios . Los servicios pueden ser anónimos (identificados únicamente por la dirección del bus, como: 1.6), y los servicios pueden obtener nombres conocidos , como org.freedesktop.Notifications o org.freedesktop.NetworkManager . El remitente y el destino que puede ver en los registros son servicios. "Destino nulo" significa difusión: entrega a todos los servicios.

  • Un servicio puede exportar uno o varios objetos al bus. Los objetos reciben rutas de objetos , como /org/freedesktop/NetworkManager/ActiveConnection/1 o /org/ayatana/menu/DA00003 . Las rutas de los objetos usan barras como separadores, como las rutas del sistema de archivos.

  • Cada objeto puede admitir una o varias interfaces . Una interfaz no es más que un conjunto de métodos y señales, coloquialmente conocidos como miembros (muy similar a la interfaz OOP). Los métodos y las señales tienen firmas fijas. Los miembros siempre tienen el espacio de nombres dentro de nombres de interfaz conocidos .

  • Una vez publicados, los nombres conocidos nunca cambian .

  • Cualquier servicio puede conectarse a las señales de otro servicio y llamar asincrónicamente sus métodos. Cualquier servicio puede emitir señales.

Señales

Ahora a sus preguntas específicas.

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

Sí, tienes razón, esta es una señal. Se transmite por el servicio :1.1948 , y el objeto "self" es /org/ayatana/menu/DA00003 . La señal tiene el nombre ItemPropertyUpdated que se define en la interfaz org.ayatana.dbusmenu (como org.ayatana.dbusmenu::ItemPropertyUpdated en C ++). El serial, supongo, es un tipo de identificador único del evento en el autobús.

Luego vemos los argumentos de señal. De acuerdo con la documentación de la interfaz , el primer argumento int32 es la identificación de un artículo, la segunda cadena es su nombre de propiedad, y la tercera variante es el valor de la propiedad. Entonces, el objeto /org/ayatana/menu/DA00003 nos está notificando que el id. de elemento 23 cambió su propiedad enabled a verdadero.

Otro ejemplo de señales:

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

Envié un mensaje de texto "prueba" usando Pidgin a un canal IRC, y /im/pidgin/purple/PurpleObject emitió dos señales bajo la interfaz im.pidgin.purple.PurpleInterface : primero un SendingChatMsg general, luego un IrcSendingText más específico.

Métodos

Ahora métodos. Los métodos son una forma de pedirle a los objetos D-Bus que hagan algo, o realizar alguna consulta y devolver datos. Son bastante similares a los métodos OOP clásicos, excepto que los métodos D-Bus se llaman de forma asíncrona.

Llamemos a un método D-Bus mediante programación.

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

Tenga en cuenta los argumentos, especialmente el nombre del icono. En su ejemplo "notification-audio-volume-medium" era el ícono del altavoz de volumen de potencia media.

Servicios personalizados

Es absolutamente posible ejecutar sus propios servicios de D-Bus, exportar sus propios objetos D-Bus y definir sus propias interfaces D-Bus con sus propios métodos y señales. Todo esto se puede hacer en Python con bastante facilidad una vez que capte el concepto general y lea la documentación del módulo dbus . :)

    
respondido por el ulidtko 01.05.2011 - 12:31
10

También estaba buscando una solución para recopilar las notificaciones de escritorio a través de dbus con un script de python. Esta pregunta fue lo más cerca que me dieron de buscar en Google, pero escribir un reemplazo para notify-osd me pareció una exageración:)

Mirando las notificaciones recientes fuentes del applet Obtuve algunos consejos sobre cómo monitorear los mensajes del dbus y aquí está la implementación de Python I se le ocurrió:

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

Espero que esto ayude a alguien, ya que parece que no hay muchos ejemplos simples de python relacionados con la supervisión de los mensajes de dbus.

    
respondido por el Keto 27.05.2012 - 12:23

Lea otras preguntas en las etiquetas