Hey everyone, thanks for coming and yeah, today I would like to talk a little bit about
the Bluetooth Mesh and what we did in the Rust ecosystem to basically support it both
on the embedded and on the Linux side and it's a good continuation on the topic that
we had in the previous session because it's a little bit comparable and there's a lot
of material so basically what I will, and a little time, 20 minutes, so what I will
basically give you today is a lot of teasers and a lot of pointers and I hope you'll get
interested and could follow the links to further investigate things.
So let's get started with what the Bluetooth Mesh is.
Bluetooth Mesh is based on the BLE, so Bluetooth Low Energy Technology, but it's designed to
create a mesh network or devices on top of it, meaning that you should be able to connect
nodes or devices directly in dynamic hierarchies basically.
What's different between the Bluetooth Mesh and the thread, for example, is that Bluetooth
Mesh doesn't use any routing, it's based on the managed flooding principle, meaning
that the device will try to publish messages to all the devices in the range and those
devices will then figure out what to do next with those messages that have been received
and it supports published subscribe model as we will see in a minute.
So this is how it basically looks like and it's a similar what Stefan showed us with
the threads, so we have a regular node that can send and receive messages, we have relay
nodes which are only there to extend the range of the network, so they're just relaying
things that they're receiving and in a similar fashion as thread, we can have a low power
nodes that are mostly sleeping and are not active and which are accompanied by the friend
nodes which will buffer messages addressed over these low power nodes.
The stack looks something like this, so as I said like we have a Bluetooth load energy
as a basic layer, there's a networking layer that's responsible for creating networks and
exchanging keys and all that kind of things and then we have an application layer which
is completely defined in the Bluetooth mesh, meaning that all our models are predefined
and we can use it as we will see now.
So as I said the models are defined, so for example all the things that are talking like
a sensors or on-off switches are defined as a model on the application level on the mesh
and we can have a client and a server model meaning that the client and the server will
exchange the messages and communicate like that.
So how does it work then is that each device, each node can have multiple elements and those
elements can have multiple client or server models between them and each element has its
own unicast address that can be used to address an element within the device.
We can also create more complex hierarchies by defining a group of addresses and defining
the virtual addresses which provides us with a way to create more complex topologies and
to have like a full power of public subscriber architectures on the mesh level.
And every device is part of the particular network and the particular application within
that network meaning that all the messages that are exchanged between the devices are
double encrypted with the network and the application key.
To onboard the device onto the network we need to go through something like a provisioning
process meaning that we need to have like a special node that will behave like a provisioner
of the network and that node will be responsible for creating and managing the keys, setting
the addresses and things like that.
So what are the use cases on top of the Bluetooth low energy we can have extended range and more
flexible topologies but we can also have existing hardware so this is just another application
on existing Bluetooth low energy hardware that can be applied but with more flexible
technologies and providing an option to connect larger number of devices.
So I don't want to go too deep into this because it's probably a session of its own.
We heard a lot about the thread here but this is just a small comparison between all the
operating technologies in the space and their respective solutions in all the different layers.
So when we started playing with this we had one goal in mind and that is to create like
a full stack meaning that we can create application based on the Bluetooth mesh that will cover
the full stack going from the embedded microcontrollers to the Linux and having support for these
applications in the cloud and try to do all that in Rust.
We will talk about that a bit more in a moment and the idea was to create a platform that
could be easy to build these applications both on devices and on the cloud side but
also provide a way to ease the management of the Bluetooth mesh networks.
But before we dive into what we did in Rust is let's go a little bit through the current
state and on the embedded side the ZFR is the only thing that I found in the open source
that had a support for the Bluetooth mesh.
Of course all the vendors had their own support as the case that can be used out of the box
On the Linux side everything related to the Bluetooth is basically under the BlueZ project
and the BlueZ defines the Dibas APIs for communicating with the Bluetooth demon on the different
kind of things and of course they have the mesh API as well for the Dibas and it's used
to send messages between the Bluetooth demon and the applications that want to talk a Bluetooth
mesh on the Linux side.
But the demon is different so if you want to use the mesh on the Linux box you need
to install the different package and basically disable and stop the regular Bluetooth demon
and enable the specific Bluetooth mesh demon.
There's also a provisioner tool included which is called the Mesh CFG client and it's an
interactive tool that allows us to do all the provisioning things.
So create new networks, scan for the provision devices, add those devices to the network
and create addresses for their models.
One of the downsides of this tool is that it's too interactive so it's not that easily
scriptable and it's making it hard to create like reproducible networks and environments
that you want to do.
And the final state is then how do we create these applications on the Linux side that
will do this and there's even less examples of that on the network.
All that I could find when I started looking into it was some of the Python examples done
in the Bluetooth white papers and basically those are just simple Python applications
that use the divas interface to basically communicate with the mesh demon over it.
So coming from this kind of state you could see the end goal that we try to do is to try
to see how far can we go with this tech and try to implement most of these things in Rust.
And now the question is why Rust of course and we found a very good solution for system
programming so it basically allows us to create, it's statically compiled and strongly typed
which means that it has a strong preform.
Save programs without introducing runtimes and VMs, again a very suitable for system
programming for this kind of applications.
And finally it's a fairly modern language with a lot of good tooling so you know people
coming from other areas for example I don't consider myself an embedded programmer but
I feel much more comfortable playing with Rust for these use cases than I would be if
I would try to do the same thing in a C so yeah.
So first thing we did is to create a bit mesh create and that's a basic create that we try
to do is to implement all the traits that are needed for implementing the Bluetooth
mesh specification.
So as you remember all the layers of the Bluetooth mesh so everything needed for representing
the application models or the networking layer traits should be defined in this one
create and as you can see you will see we will be able to reuse that in all different
layers of the stack.
But in order to be able to reuse it in the embedded space that this create needs to be
and no STD meaning that it shouldn't rely on a standard library.
And this is a kind of go to example to show how the sensor data representation could look
like in defined by the BT mesh create.
So Rust embedded I think it's going so how many people here are using Rust today for
embedded programming.
Let's go.
So what's the goal here?
There's a Rust embedded working group that are dedicated to this task and its goal is
to enable people to run firmware using Rust, firmware targeted to the microcontrollers
with the small RAM and ROM capabilities without operating system and without memory allocator.
As I said like we have only 20 minutes and there's a lot of things so I just giving you
the pointers.
So there's a lot more to be said about embedded Rust but we don't have that much time.
And the next thing, next cool thing as I said doing embedded with Rust is that it enables
you to do quite a model programming things even for the firmware.
So there's a project called embassy which allows us to use basically as in programming
for the firmers.
It provides a scheduler and the hardware abstractions that we can use to build quite capable asynchronous
applications in Rust and it has a hardware support for all the major hardware platforms
today.
On top of that the project that we are involved in is building on top of the embassy and trying
to add more IoT things on top of the basic embedded development.
So communication with the cloud in terms of MQTT or HTTP, trying to support use cases
like Bluetooth mesh and try to create more advanced applications like OTA firmware updates.
And you can see here one of the examples from the workshop that we did that I'll mention
later on is for example how we can use the Bitimesh create on the firmware to basically
every time we read the sensor data we can package that sensor data in the proper sensor
Bluetooth mesh message and send it over the Bluetooth.
Then on the Linux side there's a project called Bluer which is part of the BlueZ Linux official
group which tries to implement all the Linux Bluetooth protocol stack in Rust and at the
moment it provides support for all the major features of the Bluetooth like get or Bluetooth
cloud energy.
What we try to do here is to provide support for the Bluetooth mesh in a similar way as
the rest of the Bluer works.
So again, nice thing about Rust is that you can use a lot of crates and existing technologies
that are there for different use cases.
So for example, a Bluer uses a Tokyo runtime, very frequently used runtime for building
all kind of server applications in Rust and communicates with the mesh daemon over using
the DBScrate.
The good thing is and that was the part of the plan is to use the Bitimesh create here
as well to use for the mesh traits that we would need it.
So this is the quick architecture of how things work on the Linux so I hope you can
see it well.
So we have a mesh daemon which communicates directly with the devices.
It has its own state in the mesh config and the mesh storage volumes and it communicates
with using the system DBScrate to random applications, being the gateway application
or some device simulator on the Linux as well.
But the good thing is that you can see here is that and this is one of the things that
I personally like a lot about using Rust for these use cases is that this code running
on the Linux looks pretty much similar like the code running on the firmware.
So here we are receiving the Bluetooth message, we are parsing it, we are creating a JSON
out of it and sending it over the MQTT to the cloud.
But you know, it's very easy for a single person to jump back and forth over the different
stack layers and using the similar crates and a similar style code then it would be
if we go from writing a C for the firmware and then a Python code for the gateway and
then doing something in Java in the cloud for example.
So the mesh support is not officially landed in Bloor and this is all my fault due to my
laziness and other priorities.
But hopefully this PR will be merged in the coming weeks, let's say.
Final part of the project that we have been building is to build a kind of IoT friendly
cloud platform, again done in Rust.
Here we try to provide all the services that your typical IoT application is needing.
So being able to do a lot of connectivity, having a capable device registry and being
able to integrate further into the cloud applications and using digital twinning and all these
kind of things on the other side.
But again, I'm coming back to the same thing.
So there's a thing called payload converter in the cloud that can actually intercept our
messages coming from the gateways.
And if you can remember in the previous example, we already parsed the Bluetooth messages and
send them as a JSON.
But if your gateway is sending just the row bytes, you can do that thing on the cloud,
again with the same crates and with a very similar code.
So we will parse the bytes, get the message, do some JSON processing, and forward that
message deeper into the cloud.
So we were playing with this for a while, and then there was a chance to actually try
to put this all into the work.
With the EclipseCon, we had a hackathon and a workshop where we tried to cover the whole
area with the Bluetooth mesh network, provide the microbeads for people to play around with,
and provide some basic applications in the cloud that will talk to each other.
But the basic big architecture looks like this.
So we have a public sandbox for our drug cloud consisting of Kafka and all this kind of stuff.
And we brought the gateway based on the Bloor.
We provided some examples of how to use microbeads with the Rust embedded drug device and embassy,
and provided a couple of applications that will talk to the cloud using the web socket
in the background.
So just to recap how this architecture looks on the firmware.
So you have a couple of layers, the embassy and the Bluetooth radio on the bottom.
Then we have a drug device and the BTMesh support next on, and on top of that, we can
write our own application that will do things with these messages.
On the gateway side, we implemented the gateway using the Bloor.
And we also tried to use some of the, so to say, latest edge technologies to deploy and
manage those gateways.
So trying to use MicroShift, which is the RedHeads version of the single node Kubernetes cluster,
paired with the open cluster management to deploy these gateways to appropriate nodes.
And I must say, to my surprise, it all worked pretty well.
So we had like a four or five gateways based on the Intel Nux and some Raspberry Pis.
Because Raspberry Pis didn't run the Kubernetes, we used the basic podman and the Docker images
to run the gateways.
And that provides a very good coverage of a very large space.
What we needed to do is to provide a couple of relay nodes.
You can see on this other picture, is to just to basically extend the range over some longer
corridors that were there.
But everything worked pretty good from this perspective.
So that's all what I have to cover today.
So as I said, there's a lot of teasers.
We didn't get into anything too much deeply.
But these are the communities.
So hit us on the Drug IoT metrics channel.
That's where we all hang and are happy to talk about these things.
If you're interested in EBC, I would suggest to take a look at that and the Bloor thing,
hopefully with the official BTMesh support very soon.
Thanks.
Thank you very much.