使用 Python 读取 dbus 属性

Read dbus property with Python

我正在尝试从 dbus 读取 Raspberry Pi 的蓝牙地址。我可以使用命令行中的 busctl 来完成,如下所述,但是 Python 代码似乎应该 运行 相同的过程失败。从 dbus 读取其他属性时,我遇到了同样的失败。我可以通过运行ning hciconfig作为子进程的不理想方法获取地址,但是Python代码有什么问题?

1. List dbus bluez with busctl 

  busctl introspect org.bluez /org/bluez/hci0
  produces this (edited) result:

  NAME                                TYPE      SIGNATURE RESULT/VALUE           FLAGS
  org.bluez.Adapter1                  interface -         -                      -
  .GetDiscoveryFilters                method    -         as                     -
  .Address                            property  s         "DC:A6:32:04:DB:56"    emits-change
  .AddressType                        property  s         "public"               emits-change
  org.freedesktop.DBus.Introspectable interface -         -                      -
  .Introspect                         method    -         s                      -
  org.freedesktop.DBus.Properties     interface -         -                      -
  .Get                                method    ss        v                      -
  .GetAll                             method    s         a{sv}                  -
  .Set                                method    ssv       -                      -
  .PropertiesChanged                  signal    sa{sv}as  -                      -


2. Read Address with busctl

  busctl get-property org.bluez /org/bluez/hci0 org.bluez.Adapter1 Address

  produces this correct result:
    s "DC:A6:32:04:DB:56"

  this is from dbus-monitor:
  
  method call time=1653300359.259826 sender=:1.43 ->
       destination=org.bluez serial=2 
       path=/org/bluez/hci0;
       interface=org.freedesktop.DBus.Properties;
       member=Get
          string "org.bluez.Adapter1"
          string "Address"
  method return time=1653300359.259940 sender=:1.8 ->
     destination=:1.43 serial=85 reply_serial=2
     variant       string "DC:A6:32:04:DB:56"



3. Python3 code to do the same thing as follows:

  bus = dbus.SystemBus() 
  obj = bus.get_object("org.bluez","/org/bluez/hci0") 
  interface = dbus.Interface(obj,"org.freedesktop.Dbus.Properties")
  address = interface.Get("org.bluez.Adapter1","Address")

  produces this result:
  
  bus = runs OK
  obj = runs OK
  interface = runs OK
  address = fails with following error:  
    Method "Get" with signature "ss" on interface "org.freedesktop.DBus.Properties"  doesn't exist

  BUT IT DOES! and it works for busctl 

  address = interface.Get()
  address = interface.Get("org.bluez.Adapter1")
  address = interface.GetAll()
  address = interface.GetAll("org.bluez.Adapter1")
  address = obj.Get("org.bluez.Adapter1","Address",dbus_interface="org.freedesktop.Dbus.Properties")
    also fail with the same error 

你的这行代码:

interface = dbus.Interface(obj,"org.freedesktop.Dbus.Properties")

其实应该是

interface = dbus.Interface(obj,"org.freedesktop.DBus.Properties")

对于 python 代码,您可能会发现使用更 Pythonic 的 D-Bus 绑定更容易。

我发现 pydbus 易于使用。

以下是您使用 Pydbus 的示例:

(venv) pi@raspberry:~$ python3
Python 3.9.2 (default, Mar 12 2021, 04:06:34) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pydbus
>>> bus = pydbus.SystemBus() 
>>> adapter = bus.get('org.bluez', '/org/bluez/hci0')
>>> adapter.Address
'B8:27:EB:22:57:E0'
>>> dir(adapter)
['ActiveInstances', 'Address', 'AddressType', 'Alias', 'Class', 'Discoverable', 'DiscoverableTimeout', 'Discovering', 'Get', 'GetAll', 'GetDiscoveryFilters', 'Introspect', 'Modalias', 'Name', 'Pairable', 'PairableTimeout', 'Powered', 'PropertiesChanged', 'Register', 'RegisterAdvertisement', 'RegisterApplication', 'RegisterEndpoint', 'RegisterPlayer', 'RemoveDevice', 'Roles', 'Set', 'SetDiscoveryFilter', 'StartDiscovery', 'StopDiscovery', 'SupportedIncludes', 'SupportedInstances', 'SupportedSecondaryChannels', 'UUIDs', 'Unregister', 'UnregisterAdvertisement', 'UnregisterApplication', 'UnregisterEndpoint', 'UnregisterPlayer', '_Introspect', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bus', '_bus_name', '_object', '_path', 'onPropertiesChanged']
>>> adapter.GetDiscoveryFilters()
['UUIDs', 'RSSI', 'Pathloss', 'Transport', 'DuplicateData', 'Discoverable', 'Pattern']
>>> 

如果您想继续使用 dbus 库,BlueZ 源代码树中有很多示例:https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test