阻止来自python API的DBus调用



我正在编程一个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方法上的阻塞调用,但这当然不需要参数。。。

感谢您的帮助。

有更多用于D-Bus的Python库,如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调用。这似乎与其他dbusAPI不一致,后者必须将签名作为元组。

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
)

最新更新