WEBVTT

00:00.000 --> 00:07.000
So, thank you for coming to my talk.

00:07.000 --> 00:13.000
It's about, okay, I forgot to change the title apparently.

00:13.000 --> 00:21.000
I had to redo the slides because of some user error and apparently I didn't redo the title properly.

00:21.000 --> 00:27.000
And it's not about service discovery, it's about developing host applications.

00:27.000 --> 00:28.000
Sorry for that.

00:28.000 --> 00:33.000
Yes, it's my first time for them and also my first conference talk, so I'm a bit excited.

00:33.000 --> 00:35.000
So, please.

00:35.000 --> 00:38.000
Thank you.

00:47.000 --> 00:50.000
So, short introduction about me.

00:50.000 --> 00:53.000
I'm Florian from Germany.

00:53.000 --> 01:00.000
I work at Innovax, where IT service house and I'm senior embedded systems engineer.

01:00.000 --> 01:08.000
I started eight years ago with mainly embedded Android, went on to doing C++ on embedded Linux

01:08.000 --> 01:10.000
and real-time systems.

01:10.000 --> 01:13.000
And there are a couple of years I started with.

01:13.000 --> 01:18.000
I still consider myself being a neophyte, so I'm not that experienced.

01:18.000 --> 01:24.000
And I thought some feedback from a newbie would be a bit useful for the project.

01:24.000 --> 01:30.000
And also hopefully other newbies can learn one thing or two.

01:30.000 --> 01:36.000
So, on the agenda, we look in the first half at the basics.

01:36.000 --> 01:41.000
Mostly in the protocols stack and the GAT protocol.

01:41.000 --> 01:43.000
Yeah, I'll explain it later.

01:43.000 --> 01:51.000
And then we look at using Bluetooth low energy in the APIs and what tools are available.

01:51.000 --> 01:58.000
Some terminology, clarification, I've called the talk developing host applications,

01:58.000 --> 02:01.000
but that's not proper Bluetooth terminology.

02:01.000 --> 02:05.000
The experts will already know or be confused by what I meant by it.

02:05.000 --> 02:10.000
But laymen usually don't understand the word central device.

02:10.000 --> 02:13.000
So what I meant by host is a central device.

02:13.000 --> 02:17.000
And yeah, clients are paraphernal devices.

02:17.000 --> 02:23.000
Central devices, these are the devices which usually control the connection in Bluetooth low energy.

02:23.000 --> 02:28.000
A paraphernal device does some advertising and says, hey, I'm here, you can connect.

02:28.000 --> 02:31.000
And the central device is the one who does the connecting.

02:31.000 --> 02:36.000
Usually it's pretty powerful device like a laptop or smartphone.

02:36.000 --> 02:40.000
And it's less resource-constrained than the paraphernal device.

02:40.000 --> 02:48.000
And yeah, that reflects on the protocol design later because most logic resides or should reside on the central device.

02:48.000 --> 02:52.000
And then we have the paraphernal devices which are usually resource-constrained.

02:52.000 --> 03:02.000
And they are low-cost, high volume devices, usually like headphones, mice or other input devices or even cart terminals.

03:02.000 --> 03:06.000
They are designed to be relatively dumb from a protocol standpoint.

03:06.000 --> 03:12.000
So they can be built with a few hardware.

03:12.000 --> 03:15.000
So how does Billy work?

03:15.000 --> 03:17.000
The spec is pretty huge.

03:17.000 --> 03:21.000
I've checked the core specification for 5.4.

03:21.000 --> 03:23.000
And it has over 3,000 pages.

03:23.000 --> 03:26.000
And I didn't read all of them.

03:26.000 --> 03:30.000
And we have several protocols in Bluetooth low energy.

03:30.000 --> 03:36.000
There's the L2 cap, the logical link, control, and adaptation layer protocol.

03:36.000 --> 03:42.000
Then there's the HCI protocol which was mentioned further in the Bluetooth talk,

03:42.000 --> 03:44.000
Bluetooth talk.

03:44.000 --> 03:52.000
There's the protocol that's spoken between Bluetooth controller and the application processor if they are separate.

03:52.000 --> 03:57.000
Then there's the generic access profile that's basically advertising.

03:57.000 --> 04:01.000
And then we have the attribute protocol and the generic attribute protocol.

04:01.000 --> 04:04.000
These are the protocols for transferring actual data.

04:04.000 --> 04:11.000
Once a connection on the GAT layer was established and devices start talking with each other.

04:11.000 --> 04:16.000
For example, the generic access profile is used by IPcans by Apple.

04:16.000 --> 04:20.000
These are just using advertisements and saying, hey, I'm here.

04:20.000 --> 04:24.000
I have this ID and all other devices can receive the advertisements.

04:24.000 --> 04:33.000
But if you have a Bluetooth mouse or something, then you're usually using the attribute protocol to send data parameters between the devices.

04:33.000 --> 04:44.000
And I will focus most on the generic attribute protocol because that's the thing you will interact with as a programmer if you work on a separate application.

04:44.000 --> 04:49.000
The GAT protocol is a client server protocol.

04:49.000 --> 04:52.000
The peripheral device is usually the server.

04:52.000 --> 04:58.000
So the central device or smartphone laptop or something, it controls the connection.

04:58.000 --> 05:05.000
But from a data transfer standpoint, the peripheral device is the server, it serves the data.

05:05.000 --> 05:12.000
It can be the other way around in some applications, so it's not always like that.

05:12.000 --> 05:21.000
But in my experience, as limited as it is, it's usually the way I've written it here.

05:21.000 --> 05:28.000
So one word about UIDs, the Bluetooth spatial interest group, it really loves UIDs.

05:28.000 --> 05:35.000
They use it to identify everything by it, type information and object identity for the most parts.

05:35.000 --> 05:45.000
But the 128 bits of UID are quite big and we have a protocol that's designed for low energy.

05:45.000 --> 05:52.000
So what do we do to reduce data rate and the data amount of data we had to transmit?

05:52.000 --> 06:03.000
The solution is to have one big UID, which is taking the standard UID and you only send 16 bit or 32 bit portions.

06:03.000 --> 06:12.000
Instead of a full 128 bit portion and I've marked it, I hope you can see it on the slides in different colors.

06:12.000 --> 06:17.000
The first part of the big UID are substituted by smaller parts.

06:17.000 --> 06:28.000
So every time I will talk about a UID, which comes from the standard, it's usually a part of the big UID.

06:28.000 --> 06:37.000
So we start with the attribute protocol. As I said, it's a client server protocol. Everything is indexed by a 16 bit handle.

06:37.000 --> 06:42.000
So I have an attribute on my server on my attribute server.

06:42.000 --> 06:49.000
And if I want to retrieve the data, I have to say, give me the data for this handling of write it.

06:49.000 --> 07:00.000
The attribute data consists of the handle, a type, which is a UID, a value which is random data and a number of permission bits.

07:00.000 --> 07:05.000
We have basic operations at the read on write.

07:05.000 --> 07:12.000
I think our self explanatory we receive and send values and we have also notifying indicate.

07:12.000 --> 07:17.000
Notifying is when the client instructs the server to send updates.

07:17.000 --> 07:27.000
So for example, I have Bluetooth track or something and I want to receive every changed value.

07:27.000 --> 07:37.000
Then my client application, my central device instructs the server, the peripheral device to notify the other end of the connection on updates.

07:37.000 --> 07:46.000
And there are also indications which are basically the same, but indications require the client to acknowledge each update.

07:46.000 --> 07:52.000
So that's what you probably want if you have some critical applications like heart rate monitors or something.

07:52.000 --> 07:58.000
That ensures that data updates are not lost.

07:58.000 --> 08:08.000
Then we go on to the generic attribute protocol that has two building blocks basically we have services and we have characteristics.

08:08.000 --> 08:14.000
Services are in effect a bunch of characteristics grouped together.

08:14.000 --> 08:25.000
So when I connect to a device and ask it, do you support the service or do you have the service, then I know all the characteristics for the service are available.

08:25.000 --> 08:28.000
Services are identified by you IDs.

08:28.000 --> 08:37.000
So you don't ask for service by its name or plain text or something, but you have to give the device the name.

08:37.000 --> 08:41.000
These are also protected by permissions.

08:41.000 --> 08:46.000
And characteristics are basically a container for values.

08:46.000 --> 08:49.000
They are also identified by you IDs.

08:49.000 --> 09:01.000
There are several standard characteristics that have a standard UID, but you can also create your own services and your own characteristics with big 128 bit UIDs.

09:01.000 --> 09:18.000
And there's a metadata available for characteristics called the client characteristic configuration descriptor which communicates to the to the gut server that it should enable notifications for the values associated with this characteristic.

09:18.000 --> 09:20.000
Everything is built on attributes.

09:20.000 --> 09:35.000
We looked at before from the ATT protocol and basically you have a database on the server which is a big list of attributes in the at sense which all have a handle.

09:35.000 --> 09:44.000
And now you have to associate your handle with with the service you want to interact with or with the characteristic you want to read or write from the server.

09:44.000 --> 09:46.000
So you have to establish a mapping.

09:46.000 --> 09:52.000
The mapping may differ between devices and sessions, but for efficiency they can be cached.

09:52.000 --> 09:58.000
So if I have a proximity service or something like that.

09:58.000 --> 10:07.000
When I always know that the device is always provided the same handle for the same characteristic, then I can assume that it's cached.

10:07.000 --> 10:13.000
But cafia doesn't support this right now, but this does not.

10:13.000 --> 10:19.000
Specifically says they can be cached.

10:19.000 --> 10:24.000
So we want to build a central device with cafia.

10:24.000 --> 10:30.000
So we just have to enable the module in our product conf and we are basically ready to go.

10:30.000 --> 10:33.000
We have to enable Bluetooth, the Bluetooth subsystem.

10:33.000 --> 10:41.000
Then we say we want the central and the central is usually most useful with a get-clined combine so we can enable it.

10:41.000 --> 10:52.000
But for some implications, if you only want to interact with eye peeking for example, you don't even need to enable the get-clined.

10:52.000 --> 11:01.000
So in general a startup looks like we just call in line 2 the Bluetooth enable function for simplicity.

11:01.000 --> 11:06.000
I've chosen the synchronous version of it because you can pass in a callback.

11:06.000 --> 11:12.000
So it gets in the list asynchronously and the callback is called if we're done.

11:12.000 --> 11:16.000
But for this hello type, hello world type of application it's not necessary.

11:16.000 --> 11:20.000
Then we can just start scanning, we do a passive scan here.

11:20.000 --> 11:24.000
There are a couple of other scan options.

11:24.000 --> 11:28.000
And we also pass a callback function here and important.

11:28.000 --> 11:35.000
You do a sleep forever because one of the mistakes I did a couple of times was a simple endless loop there.

11:35.000 --> 11:40.000
But we already multi-threaded because the Bluetooth subsystem is multi-threaded.

11:40.000 --> 11:48.000
And if we do just an endless loop it will block the main threads, no other thread will run and no scanning will take place.

11:48.000 --> 11:57.000
Yes, in my example I just on the first scan I stopped the scanning and create a new connection.

11:57.000 --> 12:05.000
Yeah, that's it. After that we are connected and can proceed with service discovery, which is a topic on its own.

12:05.000 --> 12:15.000
There are also callbacks when so on the previous slide we just call the connection create function and that's it.

12:15.000 --> 12:17.000
It's also asynchronous.

12:17.000 --> 12:22.000
We get callbacks when the actual connection was established.

12:22.000 --> 12:32.000
You just declare a connection callbacks struct there's some macro magic but you can do it by yourself.

12:32.000 --> 12:41.000
And then you have these two callbacks register there. You get the connection handle passed in and a potential error.

12:41.000 --> 12:46.000
And there you can put your application logic in there.

12:46.000 --> 13:01.000
So that's basically it for a simple Bluetooth, a Bluetooth central device application with Sefer that connects to the first available connected to device.

13:01.000 --> 13:16.000
Yes, now the big elephant in the room my previous talk on a meetup was about service discovery because let's a bit of a pain and the documentation is a bit lacking in my opinion, at least for starters like me.

13:16.000 --> 13:33.000
And we need to set up even more parameters in callbacks and then call them calling to the table bill eStack and the bill eStack calls us back with a results from our service discovery.

13:33.000 --> 13:45.000
So we have to walk through each service one by one and ask it what it's what characteristics is have a sorry.

13:45.000 --> 14:00.000
We have to go through each service and ask it what characteristics it supports and that sounds simple and straightforward but it actually is not.

14:00.000 --> 14:15.000
So before we look at some problems rough overview of the API we have this cover function that takes the connection and some parameters and the parameters are big struct already because there are several options to scan for services.

14:15.000 --> 14:31.000
For example, can't say we just want one service or proximity service then we put in the new idea that we know of the service into the struct and then call got to discover that works fine and easy but we don't have a way to find out how much batteries left on the device.

14:31.000 --> 15:00.000
And now we have a bit of a problem because we don't know if the battery service comes before the before the proximity service or after it and the way the service discovery works is we have this big list of attributes and it runs in there from back to front and if we have to ask it twice then we waste quite a lot of time if we are trying to discover multiple services.

15:00.000 --> 15:22.000
Also we have in line six the discover function it's actually a function pointer which is a callback I just mentioned we are asynchronous again we start the discovery and if the discovery communication with the other endpoint was done we get a callback and that's on this slide.

15:22.000 --> 15:37.000
We have a big struct again with the attributes that were found for our parameter and that's basically the API we have to work with to discover all services available on the device.

15:37.000 --> 16:01.000
And as I said it's everything is asynchronous if you write your code in a naive manner and just call a beauty get discover repeatedly you will get out of all the events because it just runs through the attributes one by one and you get the characteristics and services in the mixed and it's not very useful.

16:02.000 --> 16:10.000
Yeah, that's just a bit of sample code that's not even good code I said it didn't work and we don't look to it at long.

16:10.000 --> 16:26.000
Yeah, the pitfalls as I said there's only API documentation an example code no external explanations why I have or in what order I have to do proper proper services covering.

16:26.000 --> 16:38.000
There is no example for multi services coverage if I want to very my device for its battery status and some other useful information I already have to at least handle two different services.

16:38.000 --> 16:57.000
And that's no example for handling optional services so I had a project where we tried to do a proximity tracker and that profile which requires several services to be present you have either two services or you don't have them so you have.

16:57.000 --> 17:15.000
I think three services in total but you have either three or one service so you have during discovery to to look do I have one of these required services then I have to have the other one to or if only one is it's not a proper device and I can't communicate with it properly.

17:16.000 --> 17:31.000
And getting that right was a bit tricky and the system the subsystem is quite big and complex most of the APIs are asynchronous as I said you get out of order events if you don't be careful.

17:31.000 --> 17:34.000
We have multi threading issues.

17:34.000 --> 17:45.000
The callbacks are usually called from the receive thread and there are several things you can't do in there and if you try to.

17:45.000 --> 17:54.000
I don't remember right now but I think if you try to disable the bluetooth stack in one of the receive callbacks then you will just get a kernel panic from Tefear and.

17:55.000 --> 17:57.000
Yeah, we'll be wondering what happened.

17:59.000 --> 18:12.000
Yes and some of these callbacks are called from interrupt and you can't even start a timer in there so that's a bit annoying because you don't always know what kind of callback you are just implementing.

18:13.000 --> 18:28.000
So hints for being productive if you want to find out if you're called from the receive thread or from interrupt the quickest thing usually is to look in the source code to a search for the callback function pointer.

18:29.000 --> 18:43.000
And yeah look for it the code is correct usually and the doxygen rendering is also suboptimal so looking at the code is really the best thing in my experience to find out what you need to do.

18:43.000 --> 19:02.000
And for interactions with other components during service discovery and even later is using event loop or some other structure which decouples your callbacks from the actual application logic so you are free to use whatever mechanism you want to like there you can just.

19:03.000 --> 19:12.000
Allocates a memory and start timer some stuff and it prevents the calls from the restrictions from the problems from call restrictions.

19:13.000 --> 19:31.000
Yeah, I did a little demo I can't really show it right now, but I had two dev boards one Nordic dev board and an inconvenient dev board and the simplification just flashed fine on both started up and I had to.

19:31.000 --> 19:44.000
I had zero code changes on my application so that was quite nice this paper I had only a simple application which scans for devices list the services and tries to connect on the right ones.

19:44.000 --> 19:54.000
And I didn't do any fancy power saving things I've heard some rumors that there are the things we'll get Harry with Sofia with the APIs.

19:54.000 --> 20:09.000
Yeah, a short word on the tooling unfortunately I fell sick last week and I didn't finish my research into the tools there is emulator support this is basically copied from the documentation.

20:09.000 --> 20:28.000
We can either run our targets application in Qemil and all we can use the POSIX native simulator both are in theory bluetooth enabled but on my device I just got an invalid value return value from the driver and didn't have the time to leave back into what the actual issue was.

20:28.000 --> 20:42.000
Yeah, but another thing for Qemil you need the BT proxy utility on my Linux distribution which is I'm a Linux that isn't available you have to get it from somewhere I've compiled it.

20:42.000 --> 20:48.000
But I said I couldn't debug it in the end.

20:48.000 --> 21:02.000
So where to go from here I have a small demo project for the services coverage stuff which I've tested on the boards which is the one that work fine that has a central device part.

21:02.000 --> 21:18.000
I really like the Nordic semiconductor introduction in their online academy website thing it has a really good introduction over view introduction to bluetooth low energy to get started if you don't have a clue even if you don't work this.

21:18.000 --> 21:23.000
I really found the bluetooth part of their course pretty good.

21:23.000 --> 21:34.000
You can check out the specifications it's big but it's available online and also the S1 numbers because the specification itself doesn't contain any ID.

21:34.000 --> 21:42.000
So when you first look into the specifications I want to ring what's the UID for the battery service it's an a separate document.

21:42.000 --> 21:50.000
And also Nordic same again a bit of a fanboy I guess here and they have a pretty cool mobile app the NIF connect from mobile.

21:50.000 --> 22:02.000
It's basically a generic debugger so you can just start scanning from Android app and connect to random devices and list their services and interact with them it's pretty nice for debugging.

22:02.000 --> 22:15.000
And basically that's it I'll be at the saffron table in building K later with my dev boards so you can come and chat and you can also join the saffron community on discord.

22:15.000 --> 22:17.000
It's pretty active.

22:17.000 --> 22:20.000
Yeah that's easy to get I'm.

22:20.000 --> 22:23.000
Do you have any questions?

22:23.000 --> 22:26.000
We have Germans perfect.

22:26.000 --> 22:28.000
Any questions?

22:28.000 --> 22:57.000
You mentioned with the QA Muslim relation the access to bluetooth does this mean that the emulation will use the bluetooth of your laptop and you can connect the bluetooth devices.

22:57.000 --> 23:08.000
Yes you start the BD proxy utility and that forwards the HCI commands from the saffron applications to the bluetooth controller.

23:08.000 --> 23:22.000
You need to the initialize the bluetooth controller so fun fact I also had to compile HCI control myself so I could disable the bluetooth controller for the operating system for Linux and then saffron can take it over.

23:22.000 --> 23:28.000
And if you would like to simulate or emulate the bluetooth devices themselves.

23:28.000 --> 23:31.000
You mind on the client side?

23:31.000 --> 23:41.000
Yeah I think it works the same way it's the HCI lever layer is shared between the central and the peripheral devices so I think it just works the same way.

23:41.000 --> 23:44.000
Okay thank you.

23:44.000 --> 23:49.000
Any more questions?

23:49.000 --> 23:53.000
Okay if we don't have any questions thank you.

