Search code examples
pythonraspberry-pibluetoothdbusbluez

Read dbus property with Python


I am trying to read the Bluetooth address of a Raspberry Pi from dbus. I can do it with busctl from the command line as detailed below, but the Python code that seems like it should run the same procedure fails. I get the same failure when reading other properties from dbus. I can get the address by the unsatisfactory method of running hciconfig as a sub process, but what's wrong with the Python code?

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 


Solution

  • This line of your code:

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

    should actually be

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