blueman
blueman copied to clipboard
[Question] Possible support for LE (Low Energy) char/desc manipulation?
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.
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
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
https://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt
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.
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 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: Are you sure that object actually exists? Should be in gdbus call -y -o / -d org.bluez -m org.freedesktop.DBus.ObjectManager.GetManagedObjects
then.
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 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 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
You're trying to use char000c
but introspecting char001c
.
Damn, you're right sorry guys :sob: it returns correctly now ([byte 0x5a],)
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:
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.
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 .