GetManagedObjects 可以用来返回子树吗?

问题描述 投票:0回答:1

在访问蓝牙的 Python 应用程序中,我可以使用以下命令查询属于已连接设备的所有属性:

object_manager = dbus.Interface(
    bus.get_object("org.bluez", "/"),
    "org.freedesktop.DBus.ObjectManager")
managed_objects = object_manager.GetManagedObjects()

这可行,但它返回 BlueZ 拥有的所有托管对象,包括许多我不关心的对象。 因此,如果我想将其限制为属于特定设备的对象(例如

/org/bluez/hci0/dev_00_11_22_33_44_55
),我需要显式过滤输出:

for path, ifaces in managed_objects.items():
    if path.startswith(device_path):
        ....

有更好的方法吗? 理想情况下,我想将设备路径传递给对象管理器,并且只接收其下方的路径,但是

GetManagedObjects
方法不接受任何参数,而且我没有看到任何其他方法来获取必要的信息.

我知道我可以为

InterfacesAdded
信号注册一个接收器,这效果很好,但前提是 BlueZ 查询远程设备。 如果数据已经缓存,我需要从 ObjectManager 显式读取它。

dbus bluez
1个回答
0
投票

您可以通过以设备对象路径为起点,递归调用org.freedesktop.DBus.Properties界面中的

Introspect方法
来获取所有对象路径。

生成的内省数据采用 XML 格式。根内省元素始终是节点元素。它可能有一个 name 属性,表示接口内省的(绝对)对象路径。它还包含该对象路径中公开的所有接口、信号、方法以及子对象路径(节点)。

使用该接口很简单,您只需定义它并调用方法,然后解析 XML 响应即可:

introspect_interface = dbus.Interface(
    bus.get_object("org.bluez", object_path),
    "org.freedesktop.DBus.Introspectable"
)
xml_data = introspect_interface.Introspect()
parsed_data = ET.fromstring(xml_data)
nodes = [node.get('name') for node in parsed_data.findall('node')]
interfaces = [iface.get('name') for iface in parsed_data.findall('interface')]

下一步是调用该对象路径的

GetAll()
接口中的
org.freedesktop.DBus.Properties
方法,该方法需要一个字符串参数,这是接口名称,我们为该对象路径上的所有接口获取它,不包括
 org.freedesktop.DBus.Introspectable, org.freedesktop.DBus.Properties
接口。可以这样做:

properties_interface = dbus.Interface(
    bus.get_object("org.bluez", object_path),
    "org.freedesktop.DBus.Properties"
)
properties = properties_interface.GetAll(interface)

将所有内容放在一起,最终代码将是:

import dbus
import xml.etree.ElementTree as ET

common_interfaces = ["org.freedesktop.DBus.Properties", "org.freedesktop.DBus.Introspectable"]

bus = dbus.SystemBus()

def introspect_object_path(object_path):
    print(f"Introspecting:  {object_path}")
    introspect_interface = dbus.Interface(
        bus.get_object("org.bluez", object_path),
        "org.freedesktop.DBus.Introspectable"
    )
    properties_interface = dbus.Interface(
        bus.get_object("org.bluez", object_path),
        "org.freedesktop.DBus.Properties"
    )
    xml_data = introspect_interface.Introspect()
    parsed_data = ET.fromstring(xml_data)
    nodes = [node.get('name') for node in parsed_data.findall('node')]
    interfaces = [iface.get('name') for iface in parsed_data.findall('interface')]
    for interface in interfaces:
        if interface in common_interfaces:
            continue
        print(f"Getting properties for interface: {interface}")
        properties = properties_interface.GetAll(interface)
        # Handle properties...
        print(properties)
    for node in nodes:
        introspect_object_path(object_path + f"/{node}")


base_object_path = "/org/bluez/hci0/dev_00_11_22_33_44_55"
introspect_object_path(base_object_path)
© www.soinside.com 2019 - 2024. All rights reserved.