简体   繁体   English

阻止来自 python API 的 DBus 调用

[英]Blocking DBus call from python API

I am programming a BLE device and therefore need to get some information from the org.freedesktop.DBus.Properties interface, but can't get it to work from dbus python API. From the console this is no problem.我正在对 BLE 设备进行编程,因此需要从org.freedesktop.DBus.Properties接口获取一些信息,但无法从 dbus python API 获取它。从控制台这没有问题。 For example, from dbus-send I can invoke following method call successfully (with correct mac address of course):例如,从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

Now, what I'm trying to do is actually something like this:现在,我要做的实际上是这样的:

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)

which gives me the error: 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这给了我错误: 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

I tried also with no signature with no success.我也尝试过没有签名但没有成功。 And I also found a similar question here , but for C-API.在这里也发现了类似的问题,但针对的是 C-API。 So I tried to adapt it to the python dbus API, but still can't get it to work.所以我试着让它适应 python dbus API,但仍然无法正常工作。 Moreover, the official documentation isn't very helpful as well, as there is no clear statement on how the argument mechanism works here or a reference to such an explanation.此外,官方文档也不是很有帮助,因为这里没有关于参数机制如何工作的明确说明或对此类解释的引用。 This is pretty annoying, since I can invoke a blocking call for instance on the GetManagedObjects method from org.freedesktop.DBus.ObjectManager interface that way, but that one takes no arguments of course...这很烦人,因为我可以通过这种方式从org.freedesktop.DBus.ObjectManager接口调用GetManagedObjects方法的阻塞调用,但是那个当然不需要 arguments ...

Any help appreciated.任何帮助表示赞赏。

There are more Pythonic libraries for D-Bus such as pydbus有更多用于 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)

If you did want to do it with the deprecated python-dbus library then I have always done it this way:如果你确实想用已弃用的 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'))

If you want to do it with PyGObject library then an example of that is:如果你想用 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)

Just for completeness and if someone stumble upon this:只是为了完整性,如果有人偶然发现这个:

You can get the deprecated API call to work if you change the signature to just ss instead of (ss) for some reason.如果出于某种原因将签名更改为ss而不是(ss) ,则可以让已弃用的 API 调用起作用。 This seems not to be consistent with other dbus APIs, which must have the signature as tuple.这似乎与其他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