blueman icon indicating copy to clipboard operation
blueman copied to clipboard

[Question] Possible support for LE (Low Energy) char/desc manipulation?

Open parkerlreed opened this issue 8 years ago • 15 comments

Would be cool to read/modify the characteristics provided by low energy devices. bluetoothctl can do this as it stands but would be nice to have a GUI method.

parkerlreed avatar Dec 10 '16 05:12 parkerlreed

We use the dbus api [1] to communicate with BlueZ and are limited what we can set by it.

Can you give an example of what you like to do that you can in bluetoothctl but not in blueman.

[1] https://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/device-api.txt#n119

infirit avatar Dec 10 '16 11:12 infirit

A little long but it shows how the descriptions are displayed.

[parker@satellite ~]$ bluetoothctl
[NEW] Controller 5C:51:4F:B6:38:79 satellite [default]
[NEW] Device A4:77:33:F5:48:A5 Chromecast Audio
[NEW] Device F4:F5:D8:35:81:21 Chromecast
[NEW] Device AC:FD:93:2A:4D:79 Wireless Controller
[NEW] Device A0:91:69:97:79:6A Nexus 5X
[NEW] Device DC:0B:A6:F1:1B:E5 Designer Mouse
[NEW] Primary Service
        /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service000e
        0000180f-0000-1000-8000-00805f9b34fb
        Battery Service
[NEW] Characteristic
        /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service000e/char000f
        00002a19-0000-1000-8000-00805f9b34fb
        Battery Level
[NEW] Descriptor
        /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service000e/char000f/desc0011
        00002902-0000-1000-8000-00805f9b34fb
        Client Characteristic Configuration
[NEW] Primary Service
        /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009
        0000180a-0000-1000-8000-00805f9b34fb
        Device Information
[NEW] Characteristic
        /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c
        00002a50-0000-1000-8000-00805f9b34fb
        PnP ID
[NEW] Characteristic
        /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a
        00002a29-0000-1000-8000-00805f9b34fb
        Manufacturer Name String
[NEW] Primary Service
        /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0008
        00001801-0000-1000-8000-00805f9b34fb
        Generic Attribute Profile
[NEW] Device 1C:96:5A:F4:78:BC Motorola Keylink
[Designer Mouse]# help
Available commands:
  list                       List available controllers
  show [ctrl]                Controller information
  select <ctrl>              Select default controller
  devices                    List available devices
  paired-devices             List paired devices
  power <on/off>             Set controller power
  pairable <on/off>          Set controller pairable mode
  discoverable <on/off>      Set controller discoverable mode
  agent <on/off/capability>  Enable/disable agent with given capability
  default-agent              Set agent as the default one
  advertise <on/off/type>    Enable/disable advertising with given type
  set-advertise-uuids [uuid1 uuid2 ...] Set advertise uuids
  set-advertise-service [uuid][data=[xx xx ...] Set advertise service data
  set-advertise-manufacturer [id][data=[xx xx ...] Set advertise manufacturer data
  set-advertise-tx-power <on/off> Enable/disable TX power to be advertised
  set-scan-filter-uuids [uuid1 uuid2 ...] Set scan filter uuids
  set-scan-filter-rssi [rssi] Set scan filter rssi, and clears pathloss
  set-scan-filter-pathloss [pathloss] Set scan filter pathloss, and clears rssi
  set-scan-filter-transport [transport] Set scan filter transport
  set-scan-filter-clear      Clears discovery filter.
  scan <on/off>              Scan for devices
  info [dev]                 Device information
  pair [dev]                 Pair with device
  trust [dev]                Trust device
  untrust [dev]              Untrust device
  block [dev]                Block device
  unblock [dev]              Unblock device
  remove <dev>               Remove device
  connect <dev>              Connect device
  disconnect [dev]           Disconnect device
  list-attributes [dev]      List attributes
  set-alias <alias>          Set device alias
  select-attribute <attribute> Select attribute
  attribute-info [attribute] Select attribute
  read                       Read attribute value
  write <data=[xx xx ...]>   Write attribute value
  notify <on/off>            Notify attribute value
  register-profile <UUID ...> Register profile to connect
  unregister-profile         Unregister profile
  version                    Display version
  quit                       Quit program
[Designer Mouse]# select-attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service000e/char000f
[Designer Mouse:/service000e/char000f]# read
Attempting to read /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service000e/char000f
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service000e/char000f Value: 0x62
  62                                               b
[Designer Mouse:/service000e/char000f]# # Current battery level
Invalid command
[Designer Mouse:/service000e/char000f]# select-attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a
[Designer Mouse:/service0009/char000a]# read
Attempting to read /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x4d
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x69
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x63
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x72
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x6f
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x73
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x6f
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x66
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000a Value: 0x74
  4d 69 63 72 6f 73 6f 66 74                       Microsoft
[Designer Mouse:/service000e/char000f/desc0011]# select-attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c
[Designer Mouse:/service0009/char000c]# read
Attempting to read /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c Value: 0x02
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c Value: 0x5e
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c Value: 0x04
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c Value: 0x05
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c Value: 0x08
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c Value: 0x00
[CHG] Attribute /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service0009/char000c Value: 0x01
  02 5e 04 05 08 00 01                             .^.....
[Designer Mouse:/service0009/char000c]# exit

As far as dbus goes it seems it's possible but I'm not quite sure what to set to get it. There is a dbus method for it

[parker@satellite ~]$ qdbus --system org.bluez /org/bluez/hci0/dev_DC_0B_A6_F1_1B_E5/service000e/char000f org.bluez.GattCharacteristic1.ReadValue
Error: org.freedesktop.DBus.Error.UnknownMethod
Method "ReadValue" with signature "" on interface "org.bluez.GattCharacteristic1" doesn't exist

All possible methods on that object

bool                                               org.bluez.GattCharacteristic1.StopNotify           org.freedesktop.DBus.Properties.PropertiesChanged  QStringList
method                                             org.bluez.GattCharacteristic1.UUID                 org.freedesktop.DBus.Properties.Set                QVariantMap
org.bluez.GattCharacteristic1.Flags                org.bluez.GattCharacteristic1.Value                property                                           read
org.bluez.GattCharacteristic1.Notifying            org.bluez.GattCharacteristic1.WriteValue           QByteArray                                         signal
org.bluez.GattCharacteristic1.ReadValue            org.freedesktop.DBus.Introspectable.Introspect     QDBusObjectPath                                    void
org.bluez.GattCharacteristic1.Service              org.freedesktop.DBus.Properties.Get                QDBusVariant
org.bluez.GattCharacteristic1.StartNotify          org.freedesktop.DBus.Properties.GetAll             QString

parkerlreed avatar Dec 10 '16 19:12 parkerlreed

https://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt

cschramm avatar Dec 15 '16 07:12 cschramm

A general note, I think we have little use for GATT at this moment. It is mostly intended for applications and bluez plugins that want to provide a service. Although blueman provides a couple like NM integration, I see currently nothing in the GATT api that we have to implement. But then I do not have many LE devices so I may be completely off 😄.

We could expose this through a manager plugin which allows these to be seen and potentially manipulated. This does require some work which I am not looking to add (if this is decided) for the 2.1 release. Marking as feature request for now.

infirit avatar Dec 16 '16 15:12 infirit

This is how you read the value, in this case the manufacturer name of my brand new mouse, Logitech.

$ gdbus call -y -o "/org/bluez/hci0/dev_D2_0C_FD_5A_21_11/service000c/char000d" -d "org.bluez" -m "org.bluez.GattCharacteristic1.ReadValue" {}
([byte 0x4c, 0x6f, 0x67, 0x69, 0x74, 0x65, 0x63, 0x68],)

In bluez dbus api it is also also exposed as a dbus propertie Value.

The method expects a{sv} but I have not yet understood what keys to pass, in this case an empty array seems to work ok.

Too tired now to poke at this further so tbc.

infirit avatar May 13 '17 23:05 infirit

@infirit do you have any more examples/documentation about the command, I'm using a Logitech MX Anywhere 2 mouse, and I'm trying to extract battery level value So far I've been successful with bluetoothctl, but it's not very script friendly. I've tried your example by changing characteristic to /org/bluez/hci0/dev_F0_05_2F_8B_DB_FE/service001b/char000c which (apart from device address) is battery level according to bluetoothctl, but it won't work

gdbus call -y -o "/org/bluez/hci0/dev_F0_05_2F_8B_DB_FE/service001b/char000c" -d "org.bluez" -m "org.bluez.GattCharacteristic1.ReadValue" {}
Error: GDBus.Error:org.freedesktop.DBus.Error.UnknownObject: Method "ReadValue" with signature "s" on interface "org.bluez.GattCharacteristic1" doesn't exist

lcorsini avatar Mar 13 '18 14:03 lcorsini

@lcorsini: Are you sure that object actually exists? Should be in gdbus call -y -o / -d org.bluez -m org.freedesktop.DBus.ObjectManager.GetManagedObjects then.

cschramm avatar Mar 13 '18 15:03 cschramm

yes it exists, if I run:

gdbus introspect -y -d org.bluez -o /org/bluez/hci0/dev_F0_05_2F_8B_DB_FE/service001b/char001c I can see the object

node /org/bluez/hci0/dev_F0_05_2F_8B_DB_FE/service001b/char001c {                                                      
  interface org.freedesktop.DBus.Introspectable {          
    methods:                                               
      Introspect(out s xml);                               
    signals:                                               
    properties:                                            
  };                                                       
  interface org.bluez.GattCharacteristic1 {                
    methods:                                               
      ReadValue(in  a{sv} options,                         
                out ay value);                             
      WriteValue(in  ay value,                             
                 in  a{sv} options);                       
      StartNotify();                                       
      StopNotify();                                        
    signals:                                               
    properties:                                            
      readonly s UUID = '00002a19-0000-1000-8000-00805f9b34fb';                                                        
      readonly o Service = '/org/bluez/hci0/dev_F0_05_2F_8B_DB_FE/service001b';                                        
      readonly ay Value = [0x5a];                          
      readonly b Notifying = false;                        
      readonly as Flags = ['read', 'notify'];              
  };                                                       
  interface org.freedesktop.DBus.Properties {              
    methods:                                               
      Get(in  s interface,                                 
          in  s name,                                      
          out v value);                                    
      Set(in  s interface,                                 
          in  s name,                                      
          in  v value);                                    
      GetAll(in  s interface,                              
             out a{sv} properties);                        
    signals:                                               
      PropertiesChanged(s interface,                       
                        a{sv} changed_properties,          
                        as invalidated_properties);        
    properties:                                            
  };                                                       
  node desc001e {                                          
  };                                                       
}; 

What I'm interested in is: readonly ay Value = [0x5a]; which is the battery level in hex

lcorsini avatar Mar 13 '18 15:03 lcorsini

@lcorsini as @cschramm suggests UnknownObject means the path is at fault. You can also try reading it on the properties interface. Does something like below work for you?

gdbus call -y -o /org/bluez/hci0/dev_D2_0C_FD_5A_21_12/service000c/char000d -d org.bluez -m org.freedesktop.DBus.Properties.Get org.bluez.GattCharacteristic1 Value

ps: These do disappear after a while so make sure to be connected.

infirit avatar Mar 13 '18 15:03 infirit

@infirit it's the same as my first try

gdbus call -y -o /org/bluez/hci0/dev_F0_05_2F_8B_DB_FE/service001b/char000c -d org.bluez -m org.freedesktop.DBus.Properties.Get org.bluez.GattCharacteristic1 Value
Error: GDBus.Error:org.freedesktop.DBus.Error.UnknownObject: Method "Get" with signature "ss" on interface "org.freedesktop.DBus.Properties" doesn't exist

that's seems to be because the signature on the property is ay and it's the same if I read directly from org.bluez.GattCharacteristic1

gdbus call -y -o "/org/bluez/hci0/dev_F0_05_2F_8B_DB_FE/service001b/char000c" -d "org.bluez" -m "org.bluez.GattCharacteristic1.ReadValue" {} 
Error: GDBus.Error:org.freedesktop.DBus.Error.UnknownObject: Method "ReadValue" with signature "s" on interface "org.bluez.GattCharacteristic1" doesn't exist

lcorsini avatar Mar 13 '18 15:03 lcorsini

You're trying to use char000c but introspecting char001c.

cschramm avatar Mar 13 '18 15:03 cschramm

Damn, you're right sorry guys :sob: it returns correctly now ([byte 0x5a],)

lcorsini avatar Mar 13 '18 15:03 lcorsini

btw getting the property from command line works by returning ([byte 0x5a],) if I read the same property using d-feet (gui dbus explorer) I get the property as Array of [Byte]Value(read)=[90] do you know why? is it possible to do in command line? apart from this I finally can check my mouse battery :+1:

lcorsini avatar Mar 13 '18 16:03 lcorsini

Array of [Byte]Value(read)=[90]

That is purely how it is presented in the ui there is not such thing on the command line. Not sure what you are planning to do but Gio has DBusProxy class that can be used from python. Its interface will hide much of the ugliness you now see on the command-line.

infirit avatar Mar 13 '18 17:03 infirit

Yeah the idea is to write a wrapper in python to read battery level, a systray applet would be cool but something writable to conky would still be fine

Il giorno 13 marzo 2018 @ 18:09:54, Sander Sweers ([email protected]) ha scritto:

Array of [Byte]Value(read)=[90]

That is purely how it is presented in the ui there is not such thing on the command line. Not sure what you are planning to do but Gio has DBusProxy class that can be used from python. Its interface will hide much of the ugliness you now see on the command-line.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/blueman-project/blueman/issues/625#issuecomment-372743618, or mute the thread https://github.com/notifications/unsubscribe-auth/ABbq6msW4SDxGAarx5Sds5cRvEIRRlU2ks5td_1igaJpZM4LJkVk .

lcorsini avatar Mar 13 '18 17:03 lcorsini