2016-01-08 22:26:08

by Don Zickus

[permalink] [raw]
Subject: example GATT code to talk with a sensortag

Hi,

Sorry for the newbie question. I stumbled upon a TI sensortag and was able
to communicate with it using the gatttool. Now I am trying to figure out
how to build an app around that. Googling has shown me lots of examples of
folks using expect scripts (around the gatttool).

I was hoping for something in C or python. Is there an example
program/script around that I can copy and expand to get me started?

Thanks!

Cheers,
Don



2016-01-18 22:29:07

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Wed, Jan 13, 2016 at 10:44:02PM +0100, Łukasz Rymanowski wrote:
> Hi Don,
> > Did I miss a step or misunderstand your suggestion?
>
> You got it well.
> To be more clear.
> If your bluetoothd runs with -E option and you connect to BLE device
> which expose any GATT services, after connect you should see new
> objects paths. Smth like this:
>
> a) /org/bluez/hci0/dev_XXXXX/servicexxxx
> b) /org/bluez/hci0/dev_XXXXX/servicexxxx/charyyyy
> c) /org/bluez/hci0/dev_XXXXX/servicexxxx/charzzzz
>
> etc.
>
> Inside a) you should see GattService1 and inside b) and c) GattCharacteristic1
>
> Just make sure -E is there and if still not work, provide btmon.log

Hi Łukasz,

Sorry to bother you again. I am trying to turn what I learned from d-feet
into something for python. I can get UUIDs from the GetAll() command, but
no GattService info. I then noticed the device is not connected. So I
tried connecting it using the Connect() command. It keeps timing out.

There isn't much fomr btmon, but it looks useful so I attached it below.
Help?

I tried doing this under bluetootctl too and had some strange timeout
requests. When I execute 'connect xx:xx:xx', it seems to connect, start
dumping info, then disconnects with an error/timeout.

Cheers,
Don

python snippet..

service = bus.get_object(BLUEZ_SERVICE_NAME, "/org/bluez/hci0/dev_68_C9_0B_06_FA_8A")
service.Connect(dbus_interface="org.bluez.Device1")
service_props = service.GetAll("org.bluez.Device1", dbus_interface=DBUS_PROP_IFACE)


btmon output


< HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 [hci0] 374.345329
Type: Passive (0x00)
Interval: 60.000 msec (0x0060)
Window: 30.000 msec (0x0030)
Own address type: Public (0x00)
Filter policy: Ignore not in white list (0x01)
> HCI Event: Command Complete (0x0e) plen 4 [hci0] 374.346096
LE Set Scan Parameters (0x08|0x000b) ncmd 1
Status: Success (0x00)
< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 374.346190
Scanning: Enabled (0x01)
Filter duplicates: Enabled (0x01)
> HCI Event: Command Complete (0x0e) plen 4 [hci0] 374.347102
LE Set Scan Enable (0x08|0x000c) ncmd 1
Status: Success (0x00)
< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 414.345224
Scanning: Disabled (0x00)
Filter duplicates: Disabled (0x00)
> HCI Event: Command Complete (0x0e) plen 4 [hci0] 414.347154
LE Set Scan Enable (0x08|0x000c) ncmd 1
Status: Success (0x00)

python failure message:


Did not receive a reply. Possible causes include: the remote application did
not send a reply, the message bus security policy blocked the reply, the
reply timeout expired, or the network connection was broken.



2016-01-15 19:06:34

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Wed, Jan 13, 2016 at 10:44:02PM +0100, Łukasz Rymanowski wrote:
> >> Start discovery from org.bluez.Adapter1. After that find device object
> >> of your device. Then connect to this device form org.bluez.Device1.
> >> Once connected GattServices and GattCharacteristincs should be visible for you.
> >>
> >> All this you can do with d-feet of course.
> >
> > So, I tried your suggestions from within d-feet and made good progress, but
> > I don't think I am quite there yet. Here is what I did inside d-feet:
> >
> > Under /org/bluez/hci0 -> Interfaces -> org.bluez.Adapter1 -> Methods ->
> > StartDiscovery --> double clicked and 'executed' this
> >
> > Under /org/bluez/hci0/dev_XXXXX -> Interfaces -> org.bluez.Device1 ->
> > Methods -> Connect --> double clicked and 'executed' this
> >
> > Under /org/bluez/hci0/dev_XXXX -> Interfaces ->
> > org.freedesktop.DBus.Properties -> GetAll ---> double clicked, entered
> > '"org.bluez.Device1"' and 'executed' this
> > ---> received valid UUIDs, GattServices, etc as output
> >
> > Thank you!
> >
> >
> > I did _not_ see GattCharacteristic1 in the output, nor do I see either
> > GattService or GattCharacteristic1 show up as an interface in either
> > /org/bluez/hci0/dev_XXXXX or /org/bluez/hci0.
> >
> >
> > Did I miss a step or misunderstand your suggestion?
>
> You got it well.
> To be more clear.
> If your bluetoothd runs with -E option and you connect to BLE device
> which expose any GATT services, after connect you should see new
> objects paths. Smth like this:
>
> a) /org/bluez/hci0/dev_XXXXX/servicexxxx
> b) /org/bluez/hci0/dev_XXXXX/servicexxxx/charyyyy
> c) /org/bluez/hci0/dev_XXXXX/servicexxxx/charzzzz
>
> etc.
>
> Inside a) you should see GattService1 and inside b) and c) GattCharacteristic1
>
> Just make sure -E is there and if still not work, provide btmon.log

Hi Łukasz,

Yup, I see those now and the expected GattService1/Characteristic1
interfaces.

Thanks! I'll use that with the example-gatt-client to get me going. Thanks
again!

Cheers,
Don


2016-01-14 22:03:47

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Wed, Jan 13, 2016 at 10:44:02PM +0100, Łukasz Rymanowski wrote:
> > Thank you!
> >
> >
> > I did _not_ see GattCharacteristic1 in the output, nor do I see either
> > GattService or GattCharacteristic1 show up as an interface in either
> > /org/bluez/hci0/dev_XXXXX or /org/bluez/hci0.
> >
> >
> > Did I miss a step or misunderstand your suggestion?
>
> You got it well.
> To be more clear.
> If your bluetoothd runs with -E option and you connect to BLE device
> which expose any GATT services, after connect you should see new
> objects paths. Smth like this:
>
> a) /org/bluez/hci0/dev_XXXXX/servicexxxx
> b) /org/bluez/hci0/dev_XXXXX/servicexxxx/charyyyy
> c) /org/bluez/hci0/dev_XXXXX/servicexxxx/charzzzz
>
> etc.
>
> Inside a) you should see GattService1 and inside b) and c) GattCharacteristic1
>
> Just make sure -E is there and if still not work, provide btmon.log

Some days are better than others. After rebooting yesterday, my bluetooth
device stopped working... so while I am excited to test your suggestion, I
am stuck trying to make it work again. So I apologize if my response comes
later. I do appreciate the tips and patience!

Hopefully tomorrow things will work again.. :-/

Cheers,
Don

2016-01-13 21:44:02

by Łukasz Rymanowski

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

Hi Don,

On 13 January 2016 at 16:06, Don Zickus <[email protected]> wrote:
> On Tue, Jan 12, 2016 at 10:52:47PM +0100, Łukasz Rymanowski wrote:
>> Hi Don,
>>
>> On 11 January 2016 at 23:22, Don Zickus <[email protected]> wrote:
>> > On Mon, Jan 11, 2016 at 03:43:40PM -0300, Luiz Augusto von Dentz wrote:
>> >> Hi Don,
>> >>
>> >>
>> >> You will need to pass -E to bluetoothd to enable the experimental
>> >> intefaces, btw there is a recent change to GATT server/peripheral so I
>> >> suggest you try with the current version on git.
>> >
>> > Hi Luiz,
>> >
>> > I passed the -E and compiled and installed the latest git version of bluez
>> >
>> > commit e81aeaea21db84042ee0c30159290ca56d250111
>> > Author: Luiz Augusto von Dentz <[email protected]>
>> > Date: Wed Jan 6 12:20:45 2016 -0300
>> >
>> > I installed d-feet to help me with the d-bus interfaces as I was struggling
>> > with that. With the -E option I now see 'GattManager1' pop up under
>> > '/org/bluez/hci0'.
>> >
>> > I guess I was expecting to see a 'GattService1' and 'GattCharacteristic1',
>> > but I don't.
>> >
>
> Hi Łukasz,
>
> Thanks for the feedback!
>
>>
>> Start discovery from org.bluez.Adapter1. After that find device object
>> of your device. Then connect to this device form org.bluez.Device1.
>> Once connected GattServices and GattCharacteristincs should be visible for you.
>>
>> All this you can do with d-feet of course.
>
> So, I tried your suggestions from within d-feet and made good progress, but
> I don't think I am quite there yet. Here is what I did inside d-feet:
>
> Under /org/bluez/hci0 -> Interfaces -> org.bluez.Adapter1 -> Methods ->
> StartDiscovery --> double clicked and 'executed' this
>
> Under /org/bluez/hci0/dev_XXXXX -> Interfaces -> org.bluez.Device1 ->
> Methods -> Connect --> double clicked and 'executed' this
>
> Under /org/bluez/hci0/dev_XXXX -> Interfaces ->
> org.freedesktop.DBus.Properties -> GetAll ---> double clicked, entered
> '"org.bluez.Device1"' and 'executed' this
> ---> received valid UUIDs, GattServices, etc as output
>
> Thank you!
>
>
> I did _not_ see GattCharacteristic1 in the output, nor do I see either
> GattService or GattCharacteristic1 show up as an interface in either
> /org/bluez/hci0/dev_XXXXX or /org/bluez/hci0.
>
>
> Did I miss a step or misunderstand your suggestion?

You got it well.
To be more clear.
If your bluetoothd runs with -E option and you connect to BLE device
which expose any GATT services, after connect you should see new
objects paths. Smth like this:

a) /org/bluez/hci0/dev_XXXXX/servicexxxx
b) /org/bluez/hci0/dev_XXXXX/servicexxxx/charyyyy
c) /org/bluez/hci0/dev_XXXXX/servicexxxx/charzzzz

etc.

Inside a) you should see GattService1 and inside b) and c) GattCharacteristic1

Just make sure -E is there and if still not work, provide btmon.log

>
>
> Cheers,
> Don


--
BR / Pozdrawiam
Łukasz

2016-01-13 15:06:41

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Tue, Jan 12, 2016 at 10:52:47PM +0100, Łukasz Rymanowski wrote:
> Hi Don,
>
> On 11 January 2016 at 23:22, Don Zickus <[email protected]> wrote:
> > On Mon, Jan 11, 2016 at 03:43:40PM -0300, Luiz Augusto von Dentz wrote:
> >> Hi Don,
> >>
> >>
> >> You will need to pass -E to bluetoothd to enable the experimental
> >> intefaces, btw there is a recent change to GATT server/peripheral so I
> >> suggest you try with the current version on git.
> >
> > Hi Luiz,
> >
> > I passed the -E and compiled and installed the latest git version of bluez
> >
> > commit e81aeaea21db84042ee0c30159290ca56d250111
> > Author: Luiz Augusto von Dentz <[email protected]>
> > Date: Wed Jan 6 12:20:45 2016 -0300
> >
> > I installed d-feet to help me with the d-bus interfaces as I was struggling
> > with that. With the -E option I now see 'GattManager1' pop up under
> > '/org/bluez/hci0'.
> >
> > I guess I was expecting to see a 'GattService1' and 'GattCharacteristic1',
> > but I don't.
> >

Hi Łukasz,

Thanks for the feedback!

>
> Start discovery from org.bluez.Adapter1. After that find device object
> of your device. Then connect to this device form org.bluez.Device1.
> Once connected GattServices and GattCharacteristincs should be visible for you.
>
> All this you can do with d-feet of course.

So, I tried your suggestions from within d-feet and made good progress, but
I don't think I am quite there yet. Here is what I did inside d-feet:

Under /org/bluez/hci0 -> Interfaces -> org.bluez.Adapter1 -> Methods ->
StartDiscovery --> double clicked and 'executed' this

Under /org/bluez/hci0/dev_XXXXX -> Interfaces -> org.bluez.Device1 ->
Methods -> Connect --> double clicked and 'executed' this

Under /org/bluez/hci0/dev_XXXX -> Interfaces ->
org.freedesktop.DBus.Properties -> GetAll ---> double clicked, entered
'"org.bluez.Device1"' and 'executed' this
---> received valid UUIDs, GattServices, etc as output

Thank you!


I did _not_ see GattCharacteristic1 in the output, nor do I see either
GattService or GattCharacteristic1 show up as an interface in either
/org/bluez/hci0/dev_XXXXX or /org/bluez/hci0.


Did I miss a step or misunderstand your suggestion?


Cheers,
Don

2016-01-12 21:52:47

by Łukasz Rymanowski

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

Hi Don,

On 11 January 2016 at 23:22, Don Zickus <[email protected]> wrote:
> On Mon, Jan 11, 2016 at 03:43:40PM -0300, Luiz Augusto von Dentz wrote:
>> Hi Don,
>>
>>
>> You will need to pass -E to bluetoothd to enable the experimental
>> intefaces, btw there is a recent change to GATT server/peripheral so I
>> suggest you try with the current version on git.
>
> Hi Luiz,
>
> I passed the -E and compiled and installed the latest git version of bluez
>
> commit e81aeaea21db84042ee0c30159290ca56d250111
> Author: Luiz Augusto von Dentz <[email protected]>
> Date: Wed Jan 6 12:20:45 2016 -0300
>
> I installed d-feet to help me with the d-bus interfaces as I was struggling
> with that. With the -E option I now see 'GattManager1' pop up under
> '/org/bluez/hci0'.
>
> I guess I was expecting to see a 'GattService1' and 'GattCharacteristic1',
> but I don't.
>

Start discovery from org.bluez.Adapter1. After that find device object
of your device. Then connect to this device form org.bluez.Device1.
Once connected GattServices and GattCharacteristincs should be visible for you.

All this you can do with d-feet of course.

Also, run btmon so you can see HCI traffic. In case it still does not
work, you can
try shate btmon log here.


> I tried poking the 'GetAll' interfaces under my device
> '/org/bluez/hci0/dev_XXXXXX' using 'org.bluez.Device1' as my interface.
> That got me some device info but my UUIDs were empty []. I tried using the
> 'Connect' Method in the same interface but that didn't seem to change
> anything.
>
> I am scratching my head trying to understand how this works. Looking
> through the documentation in the bluez tree it appears I need a gatt-server
> that provides 'GattServices1'? Did I read that wrong?
>
> Again, my goal was to simply read temperature data out of my sensor. I know
> the UUID and the handle (from my successful use of the gatttool), I just
> don't know how to connect to the DBus correctly??? to get the same info.
>
> Perhaps I falsely assumed that if gatttool can get it, then there was an
> interface that I can use to get the same info.
>
> I apologize for all the newbie questions. And thank you for your patience
> and help so far.
>
> Cheers,
> Don
>

BR
Lukasz
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html



--
BR / Pozdrawiam
Łukasz

2016-01-11 22:22:07

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Mon, Jan 11, 2016 at 03:43:40PM -0300, Luiz Augusto von Dentz wrote:
> Hi Don,
>
>
> You will need to pass -E to bluetoothd to enable the experimental
> intefaces, btw there is a recent change to GATT server/peripheral so I
> suggest you try with the current version on git.

Hi Luiz,

I passed the -E and compiled and installed the latest git version of bluez

commit e81aeaea21db84042ee0c30159290ca56d250111
Author: Luiz Augusto von Dentz <[email protected]>
Date: Wed Jan 6 12:20:45 2016 -0300

I installed d-feet to help me with the d-bus interfaces as I was struggling
with that. With the -E option I now see 'GattManager1' pop up under
'/org/bluez/hci0'.

I guess I was expecting to see a 'GattService1' and 'GattCharacteristic1',
but I don't.

I tried poking the 'GetAll' interfaces under my device
'/org/bluez/hci0/dev_XXXXXX' using 'org.bluez.Device1' as my interface.
That got me some device info but my UUIDs were empty []. I tried using the
'Connect' Method in the same interface but that didn't seem to change
anything.

I am scratching my head trying to understand how this works. Looking
through the documentation in the bluez tree it appears I need a gatt-server
that provides 'GattServices1'? Did I read that wrong?

Again, my goal was to simply read temperature data out of my sensor. I know
the UUID and the handle (from my successful use of the gatttool), I just
don't know how to connect to the DBus correctly??? to get the same info.

Perhaps I falsely assumed that if gatttool can get it, then there was an
interface that I can use to get the same info.

I apologize for all the newbie questions. And thank you for your patience
and help so far.

Cheers,
Don



2016-01-11 19:58:05

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Mon, Jan 11, 2016 at 07:45:20PM +0100, Bastien Nocera wrote:
> On Mon, 2016-01-11 at 09:57 -0500, Don Zickus wrote:
> > On Sun, Jan 10, 2016 at 07:13:56PM -0300, Luiz Augusto von Dentz
> > wrote:
> > > Hi Don,
> > >
> > > On Fri, Jan 8, 2016 at 7:26 PM, Don Zickus <[email protected]>
> > > wrote:
> > > > Hi,
> > > >
> > > > Sorry for the newbie question.  I stumbled upon a TI sensortag
> > > > and was able
> > > > to communicate with it using the gatttool.  Now I am trying to
> > > > figure out
> > > > how to build an app around that.  Googling has shown me lots of
> > > > examples of
> > > > folks using expect scripts (around the gatttool).
> > > >
> > > > I was hoping for something in C or python.  Is there an example
> > > > program/script around that I can copy and expand to get me
> > > > started?
> > > >
> > > > Thanks!
> > > >
> > > > Cheers,
> > > > Don
> > >
> > > bluetoothctl has some generic support for GATT attributes, in
> > > addition
> > > we have some examples in python under test/example-gatt-client and
> > > test/example-gatt-server.
> >
> > Hi Luis,
> >
> > Perfect, thanks!!
>
> Let me know how far you manage to get. I have one such device from
> "Proximo" which I was hoping to be able to use.

No problem. :-)

Cheers,
Don

2016-01-11 19:57:21

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Mon, Jan 11, 2016 at 03:43:40PM -0300, Luiz Augusto von Dentz wrote:
> Hi Don,
>
> On Mon, Jan 11, 2016 at 3:14 PM, Don Zickus <[email protected]> wrote:
> > On Sun, Jan 10, 2016 at 07:13:56PM -0300, Luiz Augusto von Dentz wrote:
> >> Hi Don,
> >>
> >> On Fri, Jan 8, 2016 at 7:26 PM, Don Zickus <[email protected]> wrote:
> >> > Hi,
> >> >
> >> > Sorry for the newbie question. I stumbled upon a TI sensortag and was able
> >> > to communicate with it using the gatttool. Now I am trying to figure out
> >> > how to build an app around that. Googling has shown me lots of examples of
> >> > folks using expect scripts (around the gatttool).
> >> >
> >> > I was hoping for something in C or python. Is there an example
> >> > program/script around that I can copy and expand to get me started?
> >> >
> >> > Thanks!
> >> >
> >> > Cheers,
> >> > Don
> >>
> >> bluetoothctl has some generic support for GATT attributes, in addition
> >> we have some examples in python under test/example-gatt-client and
> >> test/example-gatt-server.
> >
> > Hi Luiz,
> >
> > Hmm, the example program complains about no such interface 'org.bluez.GattService1'.
> >
> > Originally I thought that was a generic bluez interface but now I am
> > wondering if that was specific to the example program.
> >
> > Any tip on what the expected interface should be (so I know what to add)?
> >
> > (by the way, I am using bluez-5.36 if that helps)
>
>
> You will need to pass -E to bluetoothd to enable the experimental
> intefaces, btw there is a recent change to GATT server/peripheral so I
> suggest you try with the current version on git.

Hi Luiz,

Thanks for the tip! I will play with that and see how far I get.

Cheers,
Don

2016-01-11 18:45:20

by Bastien Nocera

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Mon, 2016-01-11 at 09:57 -0500, Don Zickus wrote:
> On Sun, Jan 10, 2016 at 07:13:56PM -0300, Luiz Augusto von Dentz
> wrote:
> > Hi Don,
> >
> > On Fri, Jan 8, 2016 at 7:26 PM, Don Zickus <[email protected]>
> > wrote:
> > > Hi,
> > >
> > > Sorry for the newbie question.  I stumbled upon a TI sensortag
> > > and was able
> > > to communicate with it using the gatttool.  Now I am trying to
> > > figure out
> > > how to build an app around that.  Googling has shown me lots of
> > > examples of
> > > folks using expect scripts (around the gatttool).
> > >
> > > I was hoping for something in C or python.  Is there an example
> > > program/script around that I can copy and expand to get me
> > > started?
> > >
> > > Thanks!
> > >
> > > Cheers,
> > > Don
> >
> > bluetoothctl has some generic support for GATT attributes, in
> > addition
> > we have some examples in python under test/example-gatt-client and
> > test/example-gatt-server.
>
> Hi Luis,
>
> Perfect, thanks!!

Let me know how far you manage to get. I have one such device from
"Proximo" which I was hoping to be able to use.

Cheers


2016-01-11 18:43:40

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

Hi Don,

On Mon, Jan 11, 2016 at 3:14 PM, Don Zickus <[email protected]> wrote:
> On Sun, Jan 10, 2016 at 07:13:56PM -0300, Luiz Augusto von Dentz wrote:
>> Hi Don,
>>
>> On Fri, Jan 8, 2016 at 7:26 PM, Don Zickus <[email protected]> wrote:
>> > Hi,
>> >
>> > Sorry for the newbie question. I stumbled upon a TI sensortag and was able
>> > to communicate with it using the gatttool. Now I am trying to figure out
>> > how to build an app around that. Googling has shown me lots of examples of
>> > folks using expect scripts (around the gatttool).
>> >
>> > I was hoping for something in C or python. Is there an example
>> > program/script around that I can copy and expand to get me started?
>> >
>> > Thanks!
>> >
>> > Cheers,
>> > Don
>>
>> bluetoothctl has some generic support for GATT attributes, in addition
>> we have some examples in python under test/example-gatt-client and
>> test/example-gatt-server.
>
> Hi Luiz,
>
> Hmm, the example program complains about no such interface 'org.bluez.GattService1'.
>
> Originally I thought that was a generic bluez interface but now I am
> wondering if that was specific to the example program.
>
> Any tip on what the expected interface should be (so I know what to add)?
>
> (by the way, I am using bluez-5.36 if that helps)


You will need to pass -E to bluetoothd to enable the experimental
intefaces, btw there is a recent change to GATT server/peripheral so I
suggest you try with the current version on git.


--
Luiz Augusto von Dentz

2016-01-11 18:14:54

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Sun, Jan 10, 2016 at 07:13:56PM -0300, Luiz Augusto von Dentz wrote:
> Hi Don,
>
> On Fri, Jan 8, 2016 at 7:26 PM, Don Zickus <[email protected]> wrote:
> > Hi,
> >
> > Sorry for the newbie question. I stumbled upon a TI sensortag and was able
> > to communicate with it using the gatttool. Now I am trying to figure out
> > how to build an app around that. Googling has shown me lots of examples of
> > folks using expect scripts (around the gatttool).
> >
> > I was hoping for something in C or python. Is there an example
> > program/script around that I can copy and expand to get me started?
> >
> > Thanks!
> >
> > Cheers,
> > Don
>
> bluetoothctl has some generic support for GATT attributes, in addition
> we have some examples in python under test/example-gatt-client and
> test/example-gatt-server.

Hi Luiz,

Hmm, the example program complains about no such interface 'org.bluez.GattService1'.

Originally I thought that was a generic bluez interface but now I am
wondering if that was specific to the example program.

Any tip on what the expected interface should be (so I know what to add)?

(by the way, I am using bluez-5.36 if that helps)

Cheers,
Don

2016-01-11 14:57:35

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Sun, Jan 10, 2016 at 07:13:56PM -0300, Luiz Augusto von Dentz wrote:
> Hi Don,
>
> On Fri, Jan 8, 2016 at 7:26 PM, Don Zickus <[email protected]> wrote:
> > Hi,
> >
> > Sorry for the newbie question. I stumbled upon a TI sensortag and was able
> > to communicate with it using the gatttool. Now I am trying to figure out
> > how to build an app around that. Googling has shown me lots of examples of
> > folks using expect scripts (around the gatttool).
> >
> > I was hoping for something in C or python. Is there an example
> > program/script around that I can copy and expand to get me started?
> >
> > Thanks!
> >
> > Cheers,
> > Don
>
> bluetoothctl has some generic support for GATT attributes, in addition
> we have some examples in python under test/example-gatt-client and
> test/example-gatt-server.

Hi Luis,

Perfect, thanks!!

Cheers,
Don

2016-01-10 22:13:56

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

Hi Don,

On Fri, Jan 8, 2016 at 7:26 PM, Don Zickus <[email protected]> wrote:
> Hi,
>
> Sorry for the newbie question. I stumbled upon a TI sensortag and was able
> to communicate with it using the gatttool. Now I am trying to figure out
> how to build an app around that. Googling has shown me lots of examples of
> folks using expect scripts (around the gatttool).
>
> I was hoping for something in C or python. Is there an example
> program/script around that I can copy and expand to get me started?
>
> Thanks!
>
> Cheers,
> Don

bluetoothctl has some generic support for GATT attributes, in addition
we have some examples in python under test/example-gatt-client and
test/example-gatt-server.


--
Luiz Augusto von Dentz

2016-01-09 08:08:46

by Barry Byford

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

Hello Don,

On 8 January 2016 at 22:26, Don Zickus <[email protected]> wrote:
> Hi,
>
> Sorry for the newbie question. I stumbled upon a TI sensortag and was able
> to communicate with it using the gatttool. Now I am trying to figure out
> how to build an app around that. Googling has shown me lots of examples of
> folks using expect scripts (around the gatttool).
>
> I was hoping for something in C or python. Is there an example
> program/script around that I can copy and expand to get me started?
>
> Thanks!
>
> Cheers,
> Don
>

I'm a bit of a newbie myself although maybe slightly further down the
path than you.
I've done some Python to communicate between a Raspberry Pi and a
Sensor tag. A short video about the experiment is at
https://youtu.be/1ZvFdX5bA8k
My intention is to clean up the code and post it to
https://github.com/ukBaz/python-bluezero within the next couple of
weeks so keep an eye on the repository.

Regards,
Barry

2016-04-01 20:21:59

by Don Zickus

[permalink] [raw]
Subject: Re: example GATT code to talk with a sensortag

On Mon, Jan 11, 2016 at 07:45:20PM +0100, Bastien Nocera wrote:
> > > bluetoothctl has some generic support for GATT attributes, in
> > > addition
> > > we have some examples in python under test/example-gatt-client and
> > > test/example-gatt-server.
> >
> > Hi Luis,
> >
> > Perfect, thanks!!
>
> Let me know how far you manage to get. I have one such device from
> "Proximo" which I was hoping to be able to use.

Hi Bastien,

Sorry for the late reply. We have had this script working for awhile now.
It is menu driven. Just select 'find devices' and then select your
device to have it dump out a table. It is very minimalistic but you can get
the point (I hope :-) ).

Cheers,
Don

================================
#!/usr/bin/python

import argparse
import dbus
import gobject
import sys
import pprint
import time
import traceback

from dbus.mainloop.glib import DBusGMainLoop

# defines
ADAPTER_IFACE = 'org.bluez.Adapter1'
BLUEZ_SERVICE_NAME = 'org.bluez'
DBUS_OM_IFACE = 'org.freedesktop.DBus.ObjectManager'
DBUS_PROP_IFACE = 'org.freedesktop.DBus.Properties'
DEVICE_IFACE = 'org.bluez.Device1'
GATT_SERVICE_IFACE = 'org.bluez.GattService1'
GATT_CHRC_IFACE = 'org.bluez.GattCharacteristic1'

# global
g_bus = None
g_mainloop = None

def init_global():
global g_bus
g_bus = dbus.SystemBus()
global g_mainloop
g_mainloop = gobject.MainLoop()

# bluez utility functions
def get_device_interface(object_path):
proxy = g_bus.get_object(BLUEZ_SERVICE_NAME, object_path)
dev_interface = dbus.Interface(proxy, DEVICE_IFACE)
return dev_interface

def get_device_property(object_path, property):
dbus_interface = get_dbus_prop_interface(object_path)
prop = dbus_interface.Get(DEVICE_IFACE, property)
return prop

def get_dbus_prop_interface(object_path):
proxy = g_bus.get_object(BLUEZ_SERVICE_NAME, object_path)
dbus_interface = dbus.Interface(proxy, DBUS_PROP_IFACE)
return dbus_interface

def get_gatt_svc_interface(object_path):
proxy = g_bus.get_object(BLUEZ_SERVICE_NAME, object_path)
gatt_interface = dbus.Interface(proxy, GATT_CHRC_IFACE)
return gatt_interface

def get_dbus_manager():
manager = dbus.Interface(g_bus.get_object(BLUEZ_SERVICE_NAME, "/"),
DBUS_OM_IFACE)
return manager

def get_managed_objects():
manager = get_dbus_manager()
objects = manager.GetManagedObjects()
return objects

# generic callbacks

def generic_error_cb(error):
print('D-Bus call failed: ' + str(error))
g_mainloop.quit()

def interfaces_removed_cb(object_path, interfaces):
print "interfaces_removed_cb: %s" % object_path


# Generic BT Device (hopefully)
class BTDevice:
"""manager of cc2260"""
def __init__(self, service_path):
print "path = %s" % service_path
self.object_path = service_path
s1 = service_path
s2 = 'dev_'
address = s1[s1.index(s2) + len(s2):]
self.address = address.replace('_', ':')
self.notify_count = 0
self.gatt_service_retry = True

def get_all(self):
dbus_interface = get_dbus_prop_interface(self.object_path)
try:
self.service_props = dbus_interface.GetAll(DEVICE_IFACE)
print "\nName: %s" % self.service_props['Name']
print "Adapter: %s\n" % self.service_props['Adapter']
except:
self.service_props = None
self.disconnect()

def get_uuids(self):
self.uuids = []
if self.service_props:
if 'UUIDs' in self.service_props:
self.uuids = self.service_props['UUIDs']

print "there are %d primary uuids:" % len(self.uuids)
for u in self.uuids:
print " %s" % u

def get_gatt_services(self):
# GattServices are not always immediately present
# perhaps we could drive the mainloop here and wait
# for them to appear, but for now the hack solution
# is to sleep for up to 10 seconds
# BUG: sometimes the sensor requires a reset to resolve
# this issue
if 'GattServices' not in self.service_props:
wait = 10
print "\nwaiting %d seconds for gatt services to materialize" \
% wait
time.sleep(wait)
self.get_all()
if 'GattServices' in self.service_props:
self.gatt_services = self.service_props['GattServices']
else:
self.gatt_services = []
print "there are %d gatt_services" % len(self.gatt_services)
if not self.gatt_services:
if self.gatt_service_retry:
# avoid infinite recursion
self.gatt_service_retry = False
print "timing failure -> retry"
self.get_gatt_services()
else:
print "unable to locate gatt_services -> Failure"
sys.exit(-1)
else:
for svc in self.gatt_services:
print " %s" % svc

def exists(self):
found = False
objects = get_managed_objects()
for path, ifaces in objects.iteritems():
if path == self.object_path:
found = True
break

return found

def connected(self):
_connected = get_device_property(self.object_path, 'Connected')
return _connected

def connect(self):
if not self.connected():
dev_interface = get_device_interface(self.object_path)
print "\nattempting to connect to %s" % self.object_path
try:
dev_interface.Connect()
print "connected"
except:
print(traceback.format_exc())
raise Exception("unable to connect to device")

def disconnect(self):
if self.connected():
dev_interface = get_device_interface(self.object_path)
if dev_interface:
print "\nattempting to disconnect..."
try:
dev_interface.Disconnect()
except:
print(traceback.format_exc())
raise Exception("unable to disconnect to device")
else:
# don't see how this can happen if connected returned
# True -> perhaps a race condition
raise Exception("device does not exist")
print "disconnected!!!!!!\n"

def sensor_cb(self, iface, changed_props, invalidated_props):
if iface != DEVICE_IFACE:
return

# check to see if Connected property has changed
connected = changed_props.get('Connected')
if connected is None:
return

# it has -> probably means not connected
print "Connected status is now %s" % connected
if not connected:
print "device is no longer connected"
g_mainloop.quit()

class BTAdapter:
def __init__(self):
adapters = []

self.om = dbus.Interface(g_bus.get_object(BLUEZ_SERVICE_NAME, '/'),
DBUS_OM_IFACE)

objects = self.om.GetManagedObjects()

for path, interfaces in objects.iteritems():
if ADAPTER_IFACE not in interfaces:
continue
#self.print_field('Adapter', path)
adapters.append(path)

if not adapters:
raise Exception("No adapters located")
if len(adapters) > 1:
raise Exception("More than one adapter located")

self.path = adapters[0]

proxy = g_bus.get_object(BLUEZ_SERVICE_NAME, adapters[0])
self.interface = dbus.Interface(proxy, ADAPTER_IFACE)
self.target_path = None
self.devices = {}
self.disco_duration = 60
self.disco_interval = 5
return

def print_field(self, field, value):
print "%-10s: %s" % (field, value)

def print_val(self, props, key, convert=False):
if key in props:
if convert:
self.print_field(key, hex(int(props[key])))
else:
self.print_field(key, props[key])

def get_devices(self):
objects = self.om.GetManagedObjects()
for path, interfaces in objects.iteritems():
if DEVICE_IFACE not in interfaces:
continue
props = interfaces[DEVICE_IFACE]
self.devices[path] = props
return self.devices

def list_devices_summary(self):
print
self.get_devices()
idx = 1
for device in self.devices:
props = self.devices[device]
print "%s: %-40s: %s" % (repr(idx), props['Name'], device)
idx = idx + 1
print

def list_devices_details(self):
self.get_devices()
for device in self.devices:
props = self.devices[device]
self.print_field("Path", device)
self.print_val(props, 'Name')
self.print_val(props, 'Alias')
self.print_val(props, 'Address')
self.print_val(props, 'Class', True)
self.print_val(props, 'Icon')
self.print_val(props, 'Adapter')
self.print_val(props, 'Connected')
if 'UUIDs' in props:
for uuid in props['UUIDs']:
self.print_field('UUID', uuid)
print

def properties_cb(self, iface, changed_props, invalidated_props):
print "properties_cb"
print changed_props
print invalidates_props

def start_discovery_timeout_cb(self):
sys.stdout.write('*')
sys.stdout.flush()
self.disco_count = self.disco_count + 1
if self.disco_count * self.disco_interval >= self.disco_duration:
# discovery is complete
g_mainloop.quit()
return False
return True

def interface_added(self, object_path, interfaces):
if DEVICE_IFACE in interfaces:
if object_path not in self.devices:
self.discovered.append(object_path)

def interface_removed(self, object_path, interfaces):
if DEVICE_IFACE in interfaces:
print "removed interface %s" % object_path

def start_discovery(self):
self.om.connect_to_signal('InterfacesAdded', self.interface_added)
self.om.connect_to_signal('InterfacesRemoved', self.interface_removed)
self.om.connect_to_signal("PropertiesChanged", self.properties_cb)
# start a timer, this will run forever otherwise
self.timer_id = gobject.timeout_add(self.disco_interval * 1000,
self.start_discovery_timeout_cb)
self.discovered = list()
self.disco_count = 0
print
print "START DISCOVERY - this operation will take %s seconds to " \
"complete" % self.disco_duration
self.interface.StartDiscovery()
try:
g_mainloop.run()
except:
print(traceback.format_exc())
sys.exit(-1)
self.interface.StopDiscovery()
print
if not self.discovered:
print "no devices were found during discovery"
else:
for d in self.discovered:
print "discovered: %s" % d
print "DISCOVERY COMPLETE"
print
return

def find_device(self, object_path):
self.om.connect_to_signal('InterfacesAdded', self.find_device_cb)
self.target_path = object_path
self.interface.StartDiscovery()
print "attempting discovery for specific device"
try:
g_mainloop.run()
except KeyboardInterrupt:
print "\n"
return

def find_device_cb(self, object_path, interfaces):
print "find_device_cb: %s" % object_path
print "target_path = %s" % self.target_path
if object_path == self.target_path:
print "found device: %s" % object_path
g_mainloop.quit()


def list_options(d):
min_opt = 1
optno = 0
optlist = list()

print
print "please choose a device or option from the following menu:"
print

first = True
for path in d:
props = d[path]
# if the device doesn't have a name - we don't care about it
if 'Name' not in props:
continue
optno = optno + 1
print "%s: %-40s: %s" % (repr(optno), props['Name'], path)
optlist.append(path)

optno = optno + 1
print "%s: %s" % (repr(optno), "perform bluetooth discovery")

optno = optno + 1
print "%s: exit program" % repr(optno)

print

max_opt = optno
return (min_opt, max_opt, optlist)

def get_answer(optinfo):

minval = optinfo[0]
maxval = optinfo[1]
paths = optinfo[2]

ans = 0
while ans < minval or ans > maxval:
ans = raw_input("please enter a value from %d to %d: " %
(minval, maxval))
try:
ans = int(ans)
except:
pass

if ans == maxval:
path = "EXIT"
elif ans == (maxval - 1):
path = "DISCO"
else:
path = paths[ans-1]
return path

def main():
# Set up the main loop.
DBusGMainLoop(set_as_default=True)

init_global()

adapter = BTAdapter()

done = False
path = None

# figure out what device the user wants to test with
while not done:
devices = adapter.get_devices()
optinfo = list_options(devices)
option = get_answer(optinfo)
if option == "EXIT":
done = True
elif option == "DISCO":
adapter.start_discovery()
else:
done = True
path = option

# has the user selected a device
if path:
print
print "processing device %s" % path
print
device = BTDevice(path)
device.connect()
device.get_all()
device.get_uuids()
device.get_gatt_services()
device.disconnect()

return

if __name__ == '__main__':
main()