繁体   English   中英

阻止来自 python API 的 DBus 调用

[英]Blocking DBus call from python API

我正在对 BLE 设备进行编程,因此需要从org.freedesktop.DBus.Properties接口获取一些信息,但无法从 dbus python API 获取它。从控制台这没有问题。 例如,从dbus-send我可以成功调用以下方法调用(当然使用正确的 mac 地址):

$ dbus-send --system --dest=org.bluez --print-reply "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX" org.freedesktop.DBus.Properties.Get string:'org.bluez.Device1' string:'Paired'

>> method return time=1645780543.222377 sender=:1.7 -> destination=:1.329 serial=1113 reply_serial=2
   variant       boolean true

现在,我要做的实际上是这样的:

import dbus
bus = dbus.SystemBus()

connected = bus.call_blocking(
    'org.bluez',                             #bus_name
    '/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX', #object_path
    'org.freedesktop.DBus.Properties',       #dbus_interface
    'Get',                                   #method
    signature='(ss)',                        #signature
    args=['org.bluez.Device1', 'Connected'], #args
)
print(connected)

这给了我错误: ERROR:dbus.connection:Unable to set arguments ['org.bluez.Device1', 'Paired'] according to signature '(ss)': <class 'TypeError'>: Fewer items found in struct's D-Bus signature than in Python arguments

我也尝试过没有签名但没有成功。 在这里也发现了类似的问题,但针对的是 C-API。 所以我试着让它适应 python dbus API,但仍然无法正常工作。 此外,官方文档也不是很有帮助,因为这里没有关于参数机制如何工作的明确说明或对此类解释的引用。 这很烦人,因为我可以通过这种方式从org.freedesktop.DBus.ObjectManager接口调用GetManagedObjects方法的阻塞调用,但是那个当然不需要 arguments ...

任何帮助表示赞赏。

有更多用于 D-Bus 的 Pythonic 库,例如 pydbus

device_path = "/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX"

bus = pydbus.SystemBus()

device = bus.get('org.bluez', device_path)
print(device.Connected)

如果你确实想用已弃用的 python-dbus 库来做,那么我总是这样做:

BLUEZ_SERVICE_NAME = 'org.bluez'
DEVICE_INTERFACE = 'org.bluez.Device1'
remote_device_path = device_path
remote_device_obj = self.bus.get_object(BLUEZ_SERVICE_NAME,
                                        remote_device_path)
remote_device_props = dbus.Interface(remote_device_obj,
                                     dbus.PROPERTIES_IFACE)
print(remote_device_props.Get(DEVICE_INTERFACE, 'Connected'))

如果你想用 PyGObject 库来做,那么一个例子是:

from gi.repository import Gio, GLib

bus_type = Gio.BusType.SYSTEM
bus_name = 'org.bluez'
object_path = '/org/bluez/hci0'
prop_iface = 'org.freedesktop.DBus.Properties'
adapter_iface = 'org.bluez.Adapter1'


adapter_props_proxy = Gio.DBusProxy.new_for_bus_sync(
            bus_type=bus_type,
            flags=Gio.DBusProxyFlags.NONE,
            info=None,
            name=bus_name,
            object_path=object_path,
            interface_name=prop_iface,
            cancellable=None)

all_props = adapter_props_proxy.GetAll('(s)', adapter_iface)
print(all_props)
powered = adapter_props_proxy.Get('(ss)', adapter_iface, 'Powered')
print(powered)

只是为了完整性,如果有人偶然发现这个:

如果出于某种原因将签名更改为ss而不是(ss) ,则可以让已弃用的 API 调用起作用。 这似乎与其他dbus API 不一致,后者必须具有元组的签名。

connected = bus.call_blocking(
    'org.bluez',                             #bus_name
    '/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX', #object_path
    'org.freedesktop.DBus.Properties',       #dbus_interface
    'Get',                                   #method
    signature='ss',                          #signature
    args=['org.bluez.Device1', 'Connected'], #args
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM