Come leggere l'output di dbus-monitor?

19

Mi diverto con dbus-monitor per cercare di capire come funziona dbus Ambiente di Ubuntu Ho diverse domande al riguardo:

  1. Potresti farmi sapere come leggere correttamente quanto segue? Capisco la grande idea, ma non i dettagli.

    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
    

    Capisco che il primo è un segnale mentre il secondo è un metodo. destinazione significa che può esserci un ricevitore / slot specifico per un segnale? Cos'è un membro ? E gli oggetti della lista seguono il segnale degli argomenti passati nel segnale? Cosa sono i mittente e serial ?

  2. Ho notato qualcosa sulla relazione tra controllo volume e notifiche. Da ciò che ho letto dall'uscita 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
    

    Sembra che la notifica sia stata attivata dal suo metodo. Semplicemente non capisco perché funziona in questo modo. A mio avviso, avrebbe più senso se ci fosse un segnale emesso "notifica-audio-volume-medio" mentre la notifica avrebbe ascoltato questo segnale e avrebbe reagito di conseguenza. Se l'invio / ricezione fosse pubblico piuttosto che privato, non consentirebbe maggiore flessibilità ed efficienza? Ad esempio se c'è un segnale pubblico per "notification-audio-volume-medium" allora diverse applicazioni potrebbero ascoltare questo segnale (che consentirebbe l'esistenza di applicazioni di notifica concorrenti) e gli sviluppatori farebbero solo doversi occupare dell'invio di segnali, mentre raccogliere e gestire un segnale sarebbe il business dell'applicazione di notifica (o qualsiasi altro programma che necessita di quei segnali).

  3. Sono appena arrivato a Dbus e voglio saperne di più mentre sto lavorando con Dbus su Python, principalmente per sviluppare alcune applet. Ho visto il tutorial di dbus-python e insegna come ascoltare tutti i segnali (specificando né l'interfaccia né il percorso ecc.) Ma come monitorare i metodi quando vengono chiamati, come fa dbus-monitor?

Se hai la pazienza di insegnare come funziona, sei il benvenuto.

    
posta Benjamin 01.05.2011 - 10:18

2 risposte

23

Introduzione D-Bus

  • D-Bus fornisce i mezzi per comunicare tra servizi . I servizi possono essere anonimi (identificati esclusivamente dall'indirizzo del bus, come: 1.6), ei servizi possono acquisire nomi noti , come org.freedesktop.Notifications o org.freedesktop.NetworkManager . Il mittente e la destinazione che puoi vedere nei log sono servizi. "Destinazione nulla" significa trasmissione: consegna a tutti i servizi.

  • Un servizio può esportare uno o più oggetti sul bus. Gli oggetti hanno percorsi oggetto , come /org/freedesktop/NetworkManager/ActiveConnection/1 o /org/ayatana/menu/DA00003 . I percorsi oggetto utilizzano la barra come separatore, come i percorsi del file system.

  • Ogni oggetto può supportare una o più interfacce . Un'interfaccia non è altro che un insieme di metodi e segnali, noti come membri (molto simili all'interfaccia OOP). Metodi e segnali hanno firme fisse. I membri sono sempre assegnati ai nomi all'interno dei nomi di interfaccia noti .

  • Una volta pubblicati, i nomi noti non cambiano mai .

  • Qualsiasi servizio può connettersi ai segnali di un altro servizio e chiamare in modo asincrono i suoi metodi. Qualsiasi servizio può emettere segnali.

Segnali

Ora per le tue domande specifiche.

% Bl0ck_qu0te%

Sì, hai ragione, questo è un segnale. Viene trasmesso dal servizio :1.1948 e l'oggetto "self" è /org/ayatana/menu/DA00003 . Il segnale ha nome ItemPropertyUpdated che è definito nell'interfaccia org.ayatana.dbusmenu (come org.ayatana.dbusmenu::ItemPropertyUpdated in C ++). Il serial, immagino, è una sorta di identificatore univoco dell'evento sul bus.

Quindi vediamo gli argomenti del segnale. In base alla documentazione dell'interfaccia , il primo argomento int32 è l'id di un elemento, la seconda stringa è il suo nome di proprietà e la terza variante è il valore della proprietà. Pertanto, l'oggetto /org/ayatana/menu/DA00003 ci sta informando che l'ID articolo n. 23 ha cambiato la proprietà enabled in true.

Un altro esempio sui segnali:

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

Ho inviato un messaggio test "test" utilizzando Pidgin a un canale IRC e /im/pidgin/purple/PurpleObject ha emesso due segnali nell'interfaccia im.pidgin.purple.PurpleInterface : prima un generale SendingChatMsg , quindi un più specifico IrcSendingText .

Metodi

Ora metodi. I metodi sono un modo per chiedere agli oggetti D-Bus di fare qualcosa, o di eseguire alcune query e restituire i dati. Sono abbastanza simili ai classici metodi OOP, tranne che i metodi D-Bus sono chiamati in modo asincrono.

Chiamiamo un metodo D-Bus a livello di codice.

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

Nota gli argomenti, in particolare il nome dell'icona. Nel tuo esempio "notification-audio-volume-medium" era l'icona dell'altoparlante del volume a media potenza.

Servizi personalizzati

È assolutamente possibile eseguire i propri servizi D-Bus, esportare i propri oggetti D-Bus e definire le proprie interfacce D-Bus con i propri metodi e segnali. Tutto questo può essere fatto in Python abbastanza facilmente una volta compreso il concetto generale e letto la documentazione del modulo dbus . % Co_de%

    
risposta data ulidtko 01.05.2011 - 14:31
10

Stavo anche cercando una soluzione per raccogliere le notifiche sul desktop tramite dbus con uno script python. Questa domanda è stata la più vicina a googling, ma scrivere un sostituto per notify-osd mi è sembrato eccessivo:)

Guardando le notifiche recenti fonti di applet ho ricevuto alcuni suggerimenti su come monitorare i messaggi dbus e qui è l'implementazione python I si avvicinò con:

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

Spero che questo aiuti qualcuno, poiché sembra che non ci siano molti semplici esempi python relativi al monitoraggio dei messaggi dbus.

    
risposta data Keto 27.05.2012 - 14:23

Leggi altre domande sui tag