Monday, December 27, 2010

GATT related dbus API

After trying gatttool, I am trying how to use this new attribute dbus api in bluez. I find there is an "attrib/example.c" and it would create some service records to demo GATT. When we create a device to bluez, it would detect the device type. If it's a LE device, it would run to "attrib_client_register", then register Primary and Characteristics services. We can use d-feet to see these interfaces. Also, bluez will write some data files to "/var/lib/bluetooth/". When we restart bluez, it can create these interfaces without discovering the remote device again.


Primary Service
We can know what kind of services this remote BT device has from 'UUIDs' value. For example, "0x1801" is GENERIC_ATTRIB_SVCLASS_ID and "0x1800" is GENERIC_ACCESS_PROFILE_ID. 'Services' value is the object path of all primary services.

erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52 org.bluez.Device.GetProperties


method return sender=:1.93 -> dest=:1.96 reply_serial=2
array [
dict entry(
string "Address"
variant string "78:DD:08:A3:A7:52"
)
dict entry(
string "Name"
variant string ""
)
dict entry(
string "Alias"
variant string "78-DD-08-A3-A7-52"
)
dict entry(
string "Paired"
variant boolean true
)
dict entry(
string "Trusted"
variant boolean false
)
dict entry(
string "Blocked"
variant boolean false
)
dict entry(
string "Connected"
variant boolean false
)
dict entry(
string "UUIDs"
variant array [
string "00001105-0000-1000-8000-00805f9b34fb"
string "00001106-0000-1000-8000-00805f9b34fb"
string "0000110a-0000-1000-8000-00805f9b34fb"
string "0000110c-0000-1000-8000-00805f9b34fb"
string "0000110e-0000-1000-8000-00805f9b34fb"
string "00001112-0000-1000-8000-00805f9b34fb"
string "0000111f-0000-1000-8000-00805f9b34fb"
string "00001800-0000-1000-8000-00805f9b34fb"
string "00001801-0000-1000-8000-00805f9b34fb"
string "0000a002-0000-1000-8000-00805f9b34fb"
string "0000a004-0000-1000-8000-00805f9b34fb"
string "4f0ac096-35d4-4911-9631-dea8dc74eefe"
]
)
dict entry(
string "Services"
variant array [
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0001"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0010"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0100"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0200"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0680"
]
)
dict entry(
string "Adapter"
variant object path "/org/bluez/5444/hci0"
)
]


Characteristics Service
We can also discover what kind of characteristics service this BT device has. It would like use gatttool to run "--characteristics" and it would register related interfaces like below:

erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200 org.bluez.Characteristic.Discover
method return sender=:1.107 -> dest=:1.112 reply_serial=2


erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200 org.bluez.Characteristic.GetProperties


method return sender=:1.107 -> dest=:1.117 reply_serial=2
array [
dict entry(
string "Characteristics"
variant array [
object path "/org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0204"
object path "/org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0212"
]
)
]

Attribute Value - READ
From example.c, we know "0xA006" is TEMPERATURE_UUID. We can call below dbus method to retrieve its properties. This "Value" property is an array of bytes and it could have format, value and representation to describe the exact value meaning.


erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0204 org.bluez.Characteristic.GetProperties


method return sender=:1.107 -> dest=:1.118 reply_serial=2
array [
dict entry(
string "UUID"
variant string "0000a006-0000-1000-8000-00805f9b34fb"
)
dict entry(
string "Name"
variant string ""
)
dict entry(
string "Description"
variant string "Outside Temperature"
)
dict entry(
string "Value"
variant array of bytes [
8a 02
]
)
]


Bluez Data Files
GATT related files in /var/lib/bluetooth

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/primary
78:DD:08:A3:A7:52 0001#0006#00001800-0000-1000-8000-00805f9b34fb 0010#0012#00001801-0000-1000-8000-00805f9b34fb 0100#0111#0000a002-0000-1000-8000-00805f9b34fb 0200#0214#0000a004-0000-1000-8000-00805f9b34fb 0680#0685#4f0ac096-35d4-4911-9631-dea8dc74eefe

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/characteristic
78:DD:08:A3:A7:52#0001 0006#02#0006#00002a00-0000-1000-8000-00805f9b34fb 0006#02#0006#00002a00-0000-1000-8000-00805f9b34fb
78:DD:08:A3:A7:52#0010 0012#02#0012#0000a001-0000-1000-8000-00805f9b34fb
78:DD:08:A3:A7:52#0200 0204#02#0210#0000a006-0000-1000-8000-00805f9b34fb 0212#02#0214#0000a009-0000-1000-8000-00805f9b34fb

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/attributes
78:DD:08:A3:A7:52#0205 00002904-0000-1000-8000-00805f9b34fb#0EFE07A00108A0
78:DD:08:A3:A7:52#0206 00002901-0000-1000-8000-00805f9b34fb#4F7574736964652054656D706572617475726500
78:DD:08:A3:A7:52#0213 00002904-0000-1000-8000-00805f9b34fb#04000AA00BA008
78:DD:08:A3:A7:52#0214 00002901-0000-1000-8000-00805f9b34fb#4F7574736964652052656C61746976652048756D696400

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/profiles
78:DD:08:A3:A7:52 00001105-0000-1000-8000-00805f9b34fb 00001106-0000-1000-8000-00805f9b34fb 0000110a-0000-1000-8000-00805f9b34fb 0000110c-0000-1000-8000-00805f9b34fb 0000110e-0000-1000-8000-00805f9b34fb 00001112-0000-1000-8000-00805f9b34fb 0000111f-0000-1000-8000-00805f9b34fb 00001801-0000-1000-8000-00805f9b34fb


Attribute Value - WRITE
How to change a characteristic value? I really don't know how to send a value like "variant array of bytes [8a 02]". Then, I use ipython to send this dbus method, then I can rewrite its value.


In [1]: import dbus
In [2]: bus_name="org.bluez"
In [3]: obj_path="/org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0204"
In [4]: bus = dbus.SystemBus()
In [5]: proxy = bus.get_object(bus_name,obj_path)
In [6]: char = dbus.Interface(proxy, dbus_interface="org.bluez.Characteristic")
In [7]: properties = char.GetProperties()
In [8]: print properties
dbus.Dictionary({dbus.String(u'Description'): dbus.String(u'Outside Temperature', variant_level=1), dbus.String(u'UUID'): dbus.String(u'0000a006-0000-1000-8000-00805f9b34fb', variant_level=1), dbus.String(u'Value'): dbus.Array([dbus.Byte(128), dbus.Byte(110)], signature=dbus.Signature('y'), variant_level=1), dbus.String(u'Name'): dbus.String(u'', variant_level=1)}, signature=dbus.Signature('sv'))
In [9]: result = char.SetProperty("Value", dbus.Array([dbus.Byte(77), dbus.Byte(22)]))
In [10]: properties = char.GetProperties()
In [11]: print properties
dbus.Dictionary({dbus.String(u'Description'): dbus.String(u'Outside Temperature', variant_level=1), dbus.String(u'UUID'): dbus.String(u'0000a006-0000-1000-8000-00805f9b34fb', variant_level=1), dbus.String(u'Value'): dbus.Array([dbus.Byte(77), dbus.Byte(22)], signature=dbus.Signature('y'), variant_level=1), dbus.String(u'Name'): dbus.String(u'', variant_level=1)}, signature=dbus.Signature('sv'))

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.