使用 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
我正在尝试从 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