Bagaimana cara membuat daftar semua jalur objek di bawah layanan dbus?

16

Ini adalah pertanyaan lanjutan untuk Daftar layanan DBus yang tersedia .

Kode python berikut akan mencantumkan semua layanan DBus yang tersedia.

import dbus
for service in dbus.SystemBus().list_names():
    print(service)

Bagaimana cara membuat daftar jalur objek di bawah layanan dengan python? Tidak apa-apa jika jawabannya tidak melibatkan python meskipun lebih disukai.

Saya menggunakan Ubuntu 14.04

pengguna768421
sumber
Tidak apa-apa jika jawabannya tidak melibatkan python meskipun lebih disukai.
user768421

Jawaban:

15

Sesuai dokumen resmi (di bawah antarmuka standar ):

Ada beberapa antarmuka standar yang mungkin berguna di berbagai aplikasi D-Bus.

org.freedesktop.DBus.Introspectable

Antarmuka ini memiliki satu metode:

org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)

Instans objek dapat mengimplementasikan Introspectyang mengembalikan deskripsi XML objek, termasuk antarmuka (dengan sinyal dan metode), objek di bawahnya di pohon jalur objek, dan propertinya.

Jadi, inilah contoh yang sangat sederhana yang seharusnya membantu Anda memulai. Menggunakan xml.etree.ElementTreedan dbus:

#!/usr/bin/env python

import dbus
from xml.etree import ElementTree

def rec_intro(bus, service, object_path):
    print(object_path)
    obj = bus.get_object(service, object_path)
    iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
    xml_string = iface.Introspect()
    for child in ElementTree.fromstring(xml_string):
        if child.tag == 'node':
            if object_path == '/':
                object_path = ''
            new_path = '/'.join((object_path, child.attrib['name']))
            rec_intro(bus, service, new_path)

bus = dbus.SystemBus()
rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')

Itu introspeksi secara rekursif org.freedesktop.UPowermulai dari misalnya /org/freedesktop/UPowerdan mencetak semua jalur objek (nama node):

/org/freedesktop/UPower
/org/freedesktop/UPower/Wakeups
/org/freedesktop/UPower/devices
/org/freedesktop/UPower/devices/DisplayDevice
/org/freedesktop/UPower/devices/battery_BAT0
/org/freedesktop/UPower/devices/line_power_ADP0

yang cukup banyak apa yang akan Anda dapatkan jika Anda menggunakan d-feet(bukan bahwa Anda akan membutuhkannya):

masukkan deskripsi gambar di sini


Tentu, Anda dapat dengan mudah mendapatkan path objek melalui command line misalnya dengan gdbus:

gdbus introspect --system --dest org.freedesktop.UPower --object-path \
/ org / freedesktop / UPower --recurse | awk '/ ^ * node / {print $ 2}'
/ org / freedesktop / UPower
/ org / freedesktop / UPower / Wakeups
/ org / freedesktop / UPower / perangkat
/ org / freedesktop / UPower / devices / DisplayDevice
/ org / freedesktop / UPower / devices / battery_BAT0
/ org / freedesktop / UPower / devices / line_power_ADP0

Saya belum qdbusmenginstal tetapi menurut halaman ini

qdbus --system org.freedesktop.UPower

harus menghasilkan hasil yang serupa.

don_crissti
sumber
Bagaimana cara membuat daftar jalur objek rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')?
Khurshid Alam
Tidak, maksud saya membuat daftar jalur objek python, sehingga saya dapat memeriksa (dalam skrip saya) jika ada objek-jalur tertentu dalam daftar. Ini mencetak baik-baik saja objectpath., Tapi aku ingin sesuatu seperti k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower'). Saya kira itu mungkin dengan memodifikasi fungsi sedikit.
Khurshid Alam
Contoh kode dengan qbus:bus = dbus.SessionBus()..... obj_path = '/org/gnome/Gnote/RemoteControl'.......... cmd = 'qdbus org.gnome.Gnote'......... while obj_path not in ((subprocess.check_output(cmd, shell=True)).decode("utf-8")).split("\n"): ........pass
Khurshid Alam
@ KhurshidAlam - menginisialisasi daftar sebelum fungsi misalnya mylist=[]kemudian ganti printdengan mylist.appenddan kemudian sebagai perintah terakhir dalam blok fungsi return mylist- itu cukup banyak apa yang ada ... Anda kemudian dapat beralih di atas daftar atau apa pun misalnya tambahkan di bagian bawah skrip for x in mylist: print("OBJ_PATH", x)agar mereka dicetak dengan OBJ_PATHawalan ...
don_crissti
4

Saya tidak yakin Anda bisa melakukan ini secara terprogram dengan Python. Anda mungkin tetapi akan sangat sakit kepala untuk mengetahui caranya. Saya mencoba melakukannya sebelumnya dan akhirnya membenci Dbus. Bagaimanapun saya merekomendasikan untuk menggunakan d-feet jika Anda ingin menyelidiki sesuatu. Di bawah ini adalah tangkapan layar yang saya curi dari blog saya .

masukkan deskripsi gambar di sini

Setelah Anda mengetahui nama program, jalur objek, dll. Anda kemudian dapat menggunakan Python untuk mengakses hal-hal itu.

Contoh

progname = 'org.freedesktop.NetworkManager'
objpath  = '/org/freedesktop/NetworkManager'
intfname = 'org.freedesktop.NetworkManager'
methname = 'GetDevices'

bus = dbus.SystemBus()

obj  = bus.get_object(progname, objpath)  # Here we get object
intf = dbus.Interface(obj, intfname)      # Here we get interface
meth = inf.get_dbus_method(methname)      # Here we get method

meth()                                    # And finally calling the method

Seperti yang Anda lihat, itu menyebalkan untuk menyelesaikan sesuatu yang sederhana. Tapi ini adalah alur kerja termudah yang bisa Anda dapatkan dengan Dbus!

Jadi gunakan alat GUI untuk mengetahui jalur objek, antarmuka, dll. Kemudian gunakan cuplikan kode di atas sebagai templat untuk mengakses hal-hal itu. Saya juga menyarankan Anda melakukan ini melalui penerjemah IPython untuk melihat metode, properti, dll. Apa yang dimiliki setiap objek (dengan menekan tab).

Pithikos
sumber
1

Apa yang saya tahu dari pengalaman saya untuk mendapatkan jalur objek dari nama bus (layanan) adalah mungkin untuk melakukan introspeksi dengan jalur objek '/' yaitu (menggunakan contoh di atas)

introspectfunc('org.freedesktop.UPower', '/') 

ini akan kembali:

<node name="/"> 
<node name="org"/>
<node name="org"/>
<node name="org"/>
<node name="org"/>
<node name="org"/>
<node name="org"/></node>

lalu introspeksi dengan jalur '/ org'

introspectfunc('org.freedesktop.UPower', '/org')

ini akan kembali:

<node name="/org"> 
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/></node>

dan seterusnya:

introspectfunc('org.freedesktop.UPower', '/org/freedesktop')
introspectfunc('org.freedesktop.UPower', '/org/freedesktop/UPower')
etc.

Ini seperti pergi melalui struktur folder dari hard drive di mana path objek '/' adalah root dan setiap node adalah subfolder. Ini tampaknya cara terbaik untuk mengambil jalur objek dari nama bus tertentu (layanan) dan untuk membangun koleksi yang berisi jalur objek

qnbibiqn
sumber
1

Sesuai jawaban #don_crissti , saya menerapkan, solusi ini memberikan nama antarmuka dan metode dan sinyal informasi

import dbus
from xml.etree import ElementTree
bus = dbus.SystemBus()

def busNames():
    return [ name for name in  bus.list_names() if not name.startswith(":") ]


def pathNames(service,object_path="/",paths=None,serviceDict=None):
    if paths == None:
        paths = {}
    paths[object_path] = {}
    obj = bus.get_object(service, object_path)
    iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
    xml_string = iface.Introspect()
    root = ElementTree.fromstring(xml_string)
    for child in root:
        if child.tag == 'node':
            if object_path == '/':
                    object_path = ''
            new_path = '/'.join((object_path, child.attrib['name']))
            pathNames(service, new_path,paths)
        else:
            if object_path == "":
                object_path = "/"
            functiondict = {}
            paths[object_path][child.attrib["name"]] = functiondict
            for func in child.getchildren():
                if func.tag not in functiondict.keys():
                    functiondict[func.tag] =[]
                functiondict[func.tag].append(func.attrib["name"])
    if serviceDict == None:
        serviceDict = {}
    serviceDict[service] = paths
    return serviceDict



import json
import random
service=random.sample(busNames(),1).pop()
print service
print json.dumps(pathNames(service),indent=3)
Mulai Miranda
sumber