WEBVTT

00:00.000 --> 00:22.000
So, hi. My name is Alexi. I'm here today to talk about some kind of fun projects.

00:22.000 --> 00:27.000
To introduce myself a bit more, I am working at Brooklyn, similarly to Luca.

00:28.000 --> 00:33.000
I am doing embedded stuff. Obviously, I mostly work with embedded Linux platforms.

00:33.000 --> 00:35.000
I'm doing canal developments.

00:36.000 --> 00:42.000
My company is focused on all these kind of things, and especially on upstreaming and using open source.

00:43.000 --> 00:49.000
And so, when I'm not working on those embedded Linux things, I also do a bit of hacking on some other platforms.

00:49.000 --> 00:53.000
And so, that's actually what I want to talk to you about today.

00:54.000 --> 00:59.000
So, the project I want to talk about is a kind of game that I have developed with a few friends.

00:59.000 --> 01:04.000
And this is a blind test game. So, it comes with a set of hardware.

01:04.000 --> 01:08.000
And the concept is pretty simple. There's a song playing. You have to guess the song.

01:08.000 --> 01:13.000
And to be able to compete, you have some physical buzzers. So, this is this kind of button here.

01:13.000 --> 01:17.000
This is handmade with some custom electronics software and all.

01:18.000 --> 01:25.000
You have a web interface. Everyone has its own score on the screen. You have the music playing, a countdown, and everything.

01:26.000 --> 01:32.000
So, we have developed this kind of thing with some friends. It works. We have a working implementation.

01:32.000 --> 01:39.000
And this is a nice kind of project to have a little sandbox to play with some other technologies.

01:39.000 --> 01:44.000
And especially with this buzzer thing. So, what I'm calling buzzer is the physical button here.

01:45.000 --> 01:52.000
And this one is very simple. In the end, this is an ESP32, those inexpensive chips with some Wi-Fi in there.

01:52.000 --> 01:59.000
And I have a few peripherals to use. I have a buzzer button. This is basically a button that I have to detect.

01:59.000 --> 02:05.000
Some LED and some Wi-Fi connection to what I'm calling an NBC here. This is a controller.

02:05.000 --> 02:11.000
Access acting as an access point. This is nothing more than a Raspberry Pi.

02:12.000 --> 02:19.000
And so, the goal of this project here for this part is to create the whole firmware for this button to connect to this controller.

02:19.000 --> 02:26.000
And notify the controller about any time someone presses the button so that the player can play.

02:27.000 --> 02:34.000
So, as I mentioned, there is already a working implementation. We've been playing with friends with colleagues, even.

02:35.000 --> 02:46.000
And here the challenge is to rewrite this. It is written in C. And since the firmware is kind of small, it is perfectly fine to take some time to rewrite it in rest and to experiment in rest.

02:46.000 --> 02:53.000
But more specifically, in no STD rest, as I am doing some MD Linux, I am more interested in no STD here.

02:53.000 --> 03:00.000
That means that I won't have all the fancy tools and types that I have with the standard rest library.

03:01.000 --> 03:07.000
So, that's what I've been doing in the recent weeks. I have now a working implementation again, but with rest.

03:07.000 --> 03:14.000
And I'm here today just to let you know about my feedback, where did I struggle, what did work well, what did not.

03:14.000 --> 03:22.000
And just a bit of disclaimer, this one fixed all the bugs in the firmware. This won't make it blazingly fast. This is not the goal here.

03:22.000 --> 03:27.000
This is mostly about learning some rest and playing with rest.

03:28.000 --> 03:36.000
All right, so let's do it. The first step is to switch from our C environment to ready to work rest environments.

03:36.000 --> 03:42.000
And this is pretty simple. Before doing that, I need to know what I need to write my firmware.

03:42.000 --> 03:51.000
Here's the main feature is to be able to use some peripherals on the platform and to use the Wi-Fi interface embedded in the chip.

03:51.000 --> 04:01.000
To do that, we have an ecosystem ready to use an open source one. This is ESP HL maintained by Spressif if I'm not wrong.

04:01.000 --> 04:09.000
And in there, more specifically, we have ESP radio. This is the one which will let us use the Wi-Fi stack in the chip.

04:09.000 --> 04:20.000
It comes with a few constraints, obviously, to be able to use this ESP radio stack. We need ESP HL, but we need it with some specific features which are considered unstable.

04:20.000 --> 04:25.000
So that's a few things that we have to enable in our project configuration.

04:25.000 --> 04:34.000
We need some alok crate. I have mentioned no STD. We are already bringing in some alok, but we need it to be able to use some Wi-Fi.

04:34.000 --> 04:43.000
We need the ESP HL's glue and so on. And why we are at it? Let's bring some other crates, for example, to be able to write some ACing code.

04:44.000 --> 04:50.000
In this case, I brought an embassy because this is pretty well supported with ESP HL.

04:50.000 --> 04:56.000
And so I will be able to split all my architecture between different tasks, for example.

04:56.000 --> 05:02.000
So let's start with that. We need to bring up our environments. This is pretty straightforward.

05:02.000 --> 05:08.000
I have to install the rest of the chain with RESTAP. From there, I can install this ESP Generator.

05:08.000 --> 05:13.000
This is a template tool that will just create the basic skeleton fire projects.

05:13.000 --> 05:18.000
It is highly configurable. You can decide to bring embassy or not to bring alok or not.

05:18.000 --> 05:23.000
You can even do something very minimal without even using one file with this.

05:23.000 --> 05:31.000
It will generate everything. You can switch to this directory and bam, you are ready to run some code.

05:31.000 --> 05:37.000
What does it look like? So I have taken the basic example generated by this ESP Generator.

05:37.000 --> 05:43.000
I won't focus too much about the details on all the code I will show. It will be way too long.

05:43.000 --> 05:49.000
But basically here, we already have a main task here, which is receiving a spawner.

05:49.000 --> 05:53.000
From this spawner, I will be able to spawn all my tasks in my code.

05:53.000 --> 06:00.000
We have a few no SDD details here. We see on top no SDD. We are asking not to search for a main function.

06:00.000 --> 06:05.000
We have some specific linking to perform. This is already on-door for us.

06:05.000 --> 06:10.000
In our main task, we start getting a handle on the peripheral.

06:10.000 --> 06:19.000
This is some nice rest abstraction to have a single-tone on all the big mutable hardware we have on our platform.

06:19.000 --> 06:24.000
Some basic initialization. We see some example about manipulating Wi-Fi.

06:24.000 --> 06:29.000
Then some infinite loop in which we start seeing some weights intact.

06:29.000 --> 06:33.000
That's how I will be playing with a single.

06:34.000 --> 06:38.000
Before diving into the implementation, just a word about embassy.

06:38.000 --> 06:42.000
So what's exactly embassy? This is a runtime, an async runtime.

06:42.000 --> 06:47.000
When you want to perform some async code, you need a runtime providing, for example, an executor.

06:47.000 --> 06:49.000
So embassy is one of those.

06:49.000 --> 06:55.000
It comes with a few attributes here that allows me to declare some functions as task.

06:56.000 --> 07:01.000
So those tasks will be able to run concurrently to my main function, for example.

07:01.000 --> 07:04.000
So I will be able to write concurrent code.

07:04.000 --> 07:10.000
For example, here I have a dummy task, which will print a message every five seconds.

07:10.000 --> 07:14.000
While the rest of the code is running.

07:14.000 --> 07:20.000
All of this is a cooperative scheduling.

07:20.000 --> 07:24.000
All right, we have the basic tooling. We can start implementing things.

07:24.000 --> 07:29.000
So the very first thing I want to do is to make sure that my button, my buzzer,

07:29.000 --> 07:35.000
is able to connect to my controller, the embassy thing, acting as a Wi-Fi access point.

07:35.000 --> 07:42.000
And to do that, let's not dig too much into the code, but basically I can retrieve some Wi-Fi objects.

07:42.000 --> 07:47.000
I can declare a configuration in which I will set some SSAD password.

07:47.000 --> 07:51.000
And then I have some API to wait for the connection.

07:51.000 --> 07:54.000
First, wait for the controller to be started.

07:54.000 --> 07:57.000
And then wait for the connection.

07:57.000 --> 08:01.000
You see that here, I am already moving all of this into a dedicated task.

08:01.000 --> 08:06.000
So I can define a task that will involve the monitoring of my Wi-Fi connection.

08:06.000 --> 08:10.000
I have also this small task here, that is kind of monitoring.

08:10.000 --> 08:14.000
I am using embassy next, which is a stack providing TCP, for example.

08:14.000 --> 08:18.000
And so I need something to run the stack in a dedicated task.

08:18.000 --> 08:22.000
So that's why I have this net task on top.

08:22.000 --> 08:27.000
On the main function, I can start sponing my task.

08:27.000 --> 08:29.000
So you see that I receive this sponer here.

08:29.000 --> 08:32.000
And I am using it to start my task.

08:32.000 --> 08:38.000
So my Wi-Fi task, my embassy net stack task, and so on.

08:38.000 --> 08:44.000
And in the main task, I can wait for the connection task to have finished finish this job.

08:44.000 --> 08:49.000
So for example, waiting to have received a 9pv4 configuration.

08:49.000 --> 08:52.000
All right, simple, and we are connected.

08:52.000 --> 08:55.000
Is it maybe not?

08:55.000 --> 08:56.000
Why that?

08:56.000 --> 09:03.000
The first time I tried to run this kind of code, it crashed miserably and systematically.

09:03.000 --> 09:10.000
And things were quite weird, because we have the panic message pointing and some ESP runs this, whatever it means.

09:10.000 --> 09:14.000
Function code would be a Cisco table, not implemented.

09:14.000 --> 09:17.000
And a kind of broken backtrace.

09:17.000 --> 09:20.000
And the weird thing is that it happens systematically.

09:20.000 --> 09:24.000
But it happens only when I try to connect the button to my custom access point.

09:24.000 --> 09:30.000
If I try to connect it to my ISP router, for example, at own, it works.

09:30.000 --> 09:36.000
So fortunately, for this, it is reproducible with the basic ESP HL example.

09:36.000 --> 09:41.000
That's the test worth doing, because maybe I've done something stupid in my code.

09:41.000 --> 09:45.000
But here, no, I can reproduce it with some basic example.

09:45.000 --> 09:50.000
So the next logic thing to do is to call for help in ESP HL.

09:50.000 --> 09:56.000
So I have started feeling a bug, giving as many details as I could.

09:56.000 --> 10:00.000
And I've started discussing with who I assume to be as perceived employees.

10:00.000 --> 10:04.000
People maintaining this ESP HL crates.

10:04.000 --> 10:12.000
And we did a few back and forth, and it allowed me to understand few things about this ESP chip that I did not get at all.

10:12.000 --> 10:13.000
This is what's happening.

10:13.000 --> 10:16.000
I have my custom firmware in the flash.

10:16.000 --> 10:18.000
I have some run code.

10:18.000 --> 10:24.000
And what happened is that from time to time, my firmware is calling into some run code function.

10:24.000 --> 10:25.000
That's not outstanding.

10:25.000 --> 10:28.000
That's something that's perfectly fine in embedded systems.

10:28.000 --> 10:29.000
That happens.

10:29.000 --> 10:33.000
I suspect that this is done for some Wi-Fi features from the Wi-Fi stack.

10:33.000 --> 10:39.000
But the thing I did not suspect is that the run code can also call some functions into my flash.

10:39.000 --> 10:43.000
And this is where things will go wrong.

10:43.000 --> 10:44.000
This is kind of smart.

10:44.000 --> 10:51.000
If you do not provide a Cisco table to the run code, it should for bugs to some default things.

10:52.000 --> 10:55.000
But there was a table defined in ESP HL.

10:55.000 --> 10:57.000
And this table was not filled.

10:57.000 --> 11:01.000
There were some entries in there that just caused a straight panic.

11:01.000 --> 11:04.000
So that's the panic message we have seen.

11:04.000 --> 11:09.000
So after understanding things, those things, after doing a few tests on my own.

11:09.000 --> 11:13.000
But not understanding a thing about what was writing.

11:13.000 --> 11:18.000
I've let the adults do the code and make some commits.

11:18.000 --> 11:22.000
So they have implemented a get-reads in this school table.

11:22.000 --> 11:24.000
My luck re-entrant free run trunks.

11:24.000 --> 11:30.000
And from there, finally my browser is able to connect my custom access point.

11:30.000 --> 11:34.000
So if one of you has this GitHub under, I owe you a bear.

11:34.000 --> 11:36.000
Thank you.

11:36.000 --> 11:41.000
Okay, so we have a basic wireless connection.

11:41.000 --> 11:46.000
Unfortunately, this is fixed on the main branch on ESP HL.

11:46.000 --> 11:49.000
ESP HL has not been released yet with those fixes.

11:49.000 --> 11:52.000
But fortunately, cargo is able to handle that.

11:52.000 --> 11:55.000
So you can open your cargo.tomail.

11:55.000 --> 12:00.000
Create this patch.crites.io thingy here.

12:00.000 --> 12:02.000
And you set some specific remotes.

12:02.000 --> 12:08.000
And once your crates have been updated upstream, you can get rid of this.

12:08.000 --> 12:12.000
All right, we have a Wi-Fi connection working.

12:12.000 --> 12:15.000
I have a small TCP server running on my controller.

12:15.000 --> 12:18.000
This is actually a WebSocket server.

12:18.000 --> 12:21.000
So let's try to connect to this server.

12:21.000 --> 12:24.000
I am using the embassy net crates.

12:24.000 --> 12:28.000
This one provides object like TCP sockets, which are very useful.

12:28.000 --> 12:31.000
So I can create this TCP sockets.

12:31.000 --> 12:33.000
Set some time-out keep alive.

12:33.000 --> 12:36.000
Set will be on the automatically via the stack.

12:36.000 --> 12:38.000
Set the target.

12:38.000 --> 12:41.000
So we have the IP address of my controller here.

12:41.000 --> 12:43.000
And try to connect.

12:43.000 --> 12:48.000
And then in my main loop, I can check for any data that is coming from the controller.

12:48.000 --> 12:49.000
And so.

12:49.000 --> 12:50.000
Pretty easy, right?

12:50.000 --> 12:51.000
Is it?

12:51.000 --> 12:53.000
Once again.

12:53.000 --> 12:55.000
We have to split things a bit.

12:55.000 --> 12:58.000
And we won't be able to just handle everything in the main task.

12:58.000 --> 12:59.000
Why that?

12:59.000 --> 13:01.000
Because we are breaking this in rest.

13:01.000 --> 13:04.000
And so we have some ownership to rest always.

13:04.000 --> 13:09.000
This TCP socket object can be owned by only one task.

13:09.000 --> 13:16.000
So what I'm planning to do at this step is to move this socket into a dedicated stack, a dedicated task.

13:16.000 --> 13:21.000
And if anyone wants somewhere in my firmware to send a message,

13:21.000 --> 13:23.000
it can't access directly to the socket.

13:23.000 --> 13:26.000
It is owned already by another task.

13:26.000 --> 13:36.000
So I have to set up this kind of channels thinking between my tasks to exchange commands to send or data and statuses received by the button.

13:36.000 --> 13:39.000
So let's try to implement that.

13:39.000 --> 13:42.000
I create the ethernose task, socket task.

13:42.000 --> 13:43.000
In there.

13:43.000 --> 13:48.000
And you see here that as parameters, I'm providing channels.

13:48.000 --> 13:52.000
It is, in fact, only one side of a channel that I'm providing.

13:52.000 --> 13:56.000
The other side will be used by all the tasks.

13:56.000 --> 13:58.000
And I have the main loop.

13:58.000 --> 14:04.000
We see here some nice constructs based on the icing framework I am using.

14:04.000 --> 14:07.000
I am doing select on two different features.

14:07.000 --> 14:12.000
In fact, all the icing functions I am using right now are features.

14:12.000 --> 14:13.000
They return features.

14:13.000 --> 14:15.000
And so I have to pull those features.

14:15.000 --> 14:20.000
And to do that, I can use select, for example, to pull on multiple features.

14:20.000 --> 14:27.000
And by doing that, the first features that we trigger, will make the select return.

14:27.000 --> 14:32.000
And it will return and either this either enum, if I remember correctly.

14:32.000 --> 14:36.000
We'll let me know about which future triggered first.

14:36.000 --> 14:42.000
So from there, in my task, I am pulling both the TCP socket for incoming data.

14:42.000 --> 14:48.000
And the TX channel, in case someone want to send data through this socket.

14:48.000 --> 14:51.000
And then the corresponding code on the main side.

14:51.000 --> 14:55.000
If I want to send a message, I use the channel.

14:55.000 --> 14:57.000
All right, simple.

14:57.000 --> 14:58.000
Nope.

14:58.000 --> 15:03.000
This is where I've started to wrestle with a dark beast called the compiler.

15:03.000 --> 15:09.000
If, like me, you are a C developer only sings rust from far.

15:09.000 --> 15:11.000
This is where you will start having goosebumps.

15:11.000 --> 15:15.000
Because there is some lifetime issues and things like that.

15:15.000 --> 15:18.000
It made me scratch my head quite some time.

15:18.000 --> 15:20.000
So what's happening basically here?

15:20.000 --> 15:22.000
I am moving things between tasks.

15:22.000 --> 15:25.000
Some things have reference to other things.

15:26.000 --> 15:31.000
And so rest wants to know about left times of those references to make sure that it is valid.

15:31.000 --> 15:34.000
So let's try to navigate in all of this.

15:34.000 --> 15:38.000
Here, I am being told that I am just missing references.

15:38.000 --> 15:40.000
All right, let's try to apply something here.

15:40.000 --> 15:43.000
Applying anonymous left times.

15:43.000 --> 15:46.000
So that's this code underscore thing.

15:46.000 --> 15:48.000
And not enough.

15:48.000 --> 15:50.000
Now I'm being told, okay, there is a left time.

15:50.000 --> 15:54.000
So that you are passing to a task must have a static left time.

15:54.000 --> 15:57.000
Which means it must live for all program duration.

15:57.000 --> 15:58.000
Fine.

15:58.000 --> 16:01.000
I can change the prototype and good static.

16:01.000 --> 16:03.000
Not too enough.

16:03.000 --> 16:05.000
The object you are passing are not static.

16:05.000 --> 16:08.000
Yeah, obviously I am creating them in the main task.

16:08.000 --> 16:09.000
Okay.

16:09.000 --> 16:14.000
So let's create global viable that will not leave long enough.

16:14.000 --> 16:16.000
Not good enough.

16:16.000 --> 16:20.000
And from there, I started to stop understanding.

16:20.000 --> 16:23.000
We have those phantom data thingy here.

16:23.000 --> 16:26.000
I am not strong enough in rest.

16:26.000 --> 16:32.000
But I've searched some embassy examples, some ESPHL examples.

16:32.000 --> 16:38.000
And apparently the good thing to do here is to wrap your data structures in some static cells,

16:38.000 --> 16:42.000
which will allocate memory for this data at real time.

16:42.000 --> 16:47.000
But you can still declare this data initialized this data at random.

16:47.000 --> 16:51.000
So this is what is done in this TX in it, RX in it.

16:51.000 --> 16:54.000
And from there, yes, we can compile.

16:54.000 --> 16:57.000
We did not even test the code yet.

16:57.000 --> 16:59.000
Okay.

16:59.000 --> 17:04.000
So we assume to have working TCP connection.

17:04.000 --> 17:07.000
We don't have a better able to send a buzz notification yet.

17:07.000 --> 17:09.000
We have to read a button.

17:09.000 --> 17:11.000
And fortunately this one is quite simple.

17:11.000 --> 17:13.000
We can benefit from ESPHL.

17:13.000 --> 17:16.000
We just need to configure and read a GPIO.

17:16.000 --> 17:20.000
And the nice thing here is that it handles everything for us.

17:20.000 --> 17:22.000
This wait for falling head here.

17:22.000 --> 17:25.000
It automatically configures the relevant interrupts.

17:25.000 --> 17:26.000
Wait for the interrupt.

17:26.000 --> 17:28.000
These are both the interactive ones.

17:28.000 --> 17:29.000
It has triggered.

17:29.000 --> 17:30.000
And that's it.

17:30.000 --> 17:33.000
And from there, I can send them a set for the dedicated channel.

17:33.000 --> 17:36.000
So that it goes through my TCP socket.

17:36.000 --> 17:38.000
Well, it's almost straightforward.

17:38.000 --> 17:43.000
You have to undo some bouncing on the GPIO, for example.

17:43.000 --> 17:44.000
All right.

17:44.000 --> 17:45.000
We have a button.

17:45.000 --> 17:47.000
We are missing one thing.

17:47.000 --> 17:49.000
There is an LED in our button.

17:49.000 --> 17:52.000
This LED is useful, for example, to blink in a specific color.

17:52.000 --> 17:56.000
So that each player can remember about its thing.

17:56.000 --> 18:00.000
The LED I have chosen because I had some in my code.

18:00.000 --> 18:03.000
It's some WS2812.

18:03.000 --> 18:07.000
This is not an LED where you just apply a voltage on the pin.

18:07.000 --> 18:11.000
This needs a specific serial protocol to be manipulated.

18:11.000 --> 18:16.000
And fortunately on ESPHL32, we have a specific peripheral called Aranti.

18:16.000 --> 18:21.000
This one is used for remotes, for TVs, for doors, and all.

18:21.000 --> 18:28.000
And you can disable a modulation on this and use it as a controller for your specific LED protocol.

18:28.000 --> 18:31.000
And I do not even have to write it on my own.

18:31.000 --> 18:34.000
I can just check on crates.io.

18:34.000 --> 18:38.000
Find these smart LEDs crates, and it tells us everything.

18:38.000 --> 18:40.000
Please give me an ARMT envelope.

18:40.000 --> 18:43.000
And then I will give you API to drive your LED.

18:43.000 --> 18:45.000
So that's why we are doing here.

18:45.000 --> 18:48.000
We are instantiating this ARMT peripheral here.

18:48.000 --> 18:51.000
And feeding it to the crates.

18:51.000 --> 18:56.000
Then I have this LED object, and I can use some right traits on it

18:56.000 --> 18:59.000
to apply a specific color.

18:59.000 --> 19:02.000
Boom, done.

19:02.000 --> 19:03.000
All right.

19:03.000 --> 19:06.000
We are missing one thing.

19:06.000 --> 19:09.000
We need to exchange messages with the controller.

19:09.000 --> 19:11.000
We have set up the medium.

19:11.000 --> 19:13.000
We need to define the protocol.

19:13.000 --> 19:15.000
And here the protocol is JSON.

19:15.000 --> 19:17.000
We exchange JSON message.

19:17.000 --> 19:19.000
Anytime there is a buzz, I send a JSON message.

19:19.000 --> 19:22.000
Anytime the controller wants to set a color on my button.

19:22.000 --> 19:24.000
I receive a JSON message.

19:24.000 --> 19:25.000
And so that would be very nice.

19:25.000 --> 19:29.000
Not to have to select this ARMT messages on our own.

19:29.000 --> 19:31.000
And that's where Rust is very good.

19:31.000 --> 19:33.000
We have this set of crates here.

19:33.000 --> 19:35.000
This is amazing.

19:35.000 --> 19:36.000
How does it work?

19:36.000 --> 19:39.000
This is a general crate providing traits.

19:39.000 --> 19:43.000
And a standard ARMT laser, this ARMT laser for famous protocols.

19:43.000 --> 19:45.000
JSON, C-BOR, CSV, and so on.

19:45.000 --> 19:48.000
You can even write your own password.

19:48.000 --> 19:50.000
But you have multiple crates that you can use.

19:50.000 --> 19:53.000
You have the main one, giving the main traits.

19:53.000 --> 20:00.000
You have a JSON for example, which is the one implementing the actual password.

20:00.000 --> 20:03.000
But here this one depends on STD.

20:03.000 --> 20:05.000
I don't want to write STD code.

20:05.000 --> 20:07.000
I don't want to build STD in my family.

20:07.000 --> 20:10.000
I can somehow disable STD in there.

20:10.000 --> 20:12.000
But then I need to enable LOC.

20:12.000 --> 20:13.000
Sure.

20:13.000 --> 20:14.000
We have LOC.

20:14.000 --> 20:17.000
But I would like to try without LOC.

20:17.000 --> 20:22.000
And so there is this set of JSON code that is working without STD without LOC.

20:22.000 --> 20:27.000
It is slightly less powerful, but perfectly enough for what I want to do.

20:27.000 --> 20:30.000
To use it, cargo add the crates.

20:30.000 --> 20:33.000
And this is amazing.

20:33.000 --> 20:35.000
I have my JSON on the left.

20:35.000 --> 20:41.000
I just have to write the corresponding strict and use the corresponding attributes in my code.

20:41.000 --> 20:44.000
So I declare that the pattern can have a type.

20:44.000 --> 20:46.000
It can have GTAs.

20:46.000 --> 20:49.000
In those details, I have integrals, floats and all.

20:49.000 --> 20:56.000
You see here, those derived macros here, setting the using the macros from STD.

20:56.000 --> 21:03.000
And then when I receive a message on my TCP socket, I just have to use this from STD.

21:03.000 --> 21:10.000
With this nice little turbo-fish thing, saying that I want to deserialize a message LED pattern.

21:10.000 --> 21:12.000
And boom, I have a strict.

21:12.000 --> 21:15.000
I have all the details of the command inside there.

21:15.000 --> 21:19.000
If I want to send a message, I build a structure with a relevant field.

21:19.000 --> 21:21.000
And I call it the other way around.

21:21.000 --> 21:24.000
To slice, please store it in a buffer.

21:24.000 --> 21:27.000
And I can push this buffer into my socket.

21:27.000 --> 21:29.000
Final detail.

21:29.000 --> 21:35.000
Some messages are slightly different, but that would be a shame to redefine my messages just for a small difference.

21:35.000 --> 21:39.000
For example, I can ask to switch the LED off.

21:39.000 --> 21:41.000
I don't have details in this case.

21:41.000 --> 21:42.000
No problem.

21:42.000 --> 21:45.000
I can deserialize options in rest.

21:45.000 --> 21:48.000
I am turning my details field here into option.

21:48.000 --> 21:53.000
And so when I do from slice, I may or may not have some details.

21:53.000 --> 21:57.000
And then it's up to me to perform the relevant behavior on this.

21:57.000 --> 22:04.000
So, after wrestling with lifetimes and compiler issues, this one was very nice.

22:04.000 --> 22:06.000
All right.

22:06.000 --> 22:10.000
I even have a few minutes to perform a small demo.

22:11.000 --> 22:14.000
I have the buzzer. I have the controller here.

22:14.000 --> 22:15.000
I will pour it up.

22:15.000 --> 22:18.000
The controller.

22:18.000 --> 22:24.000
First demo was nice enough to even make a t-shirt in sync with my talk.

22:24.000 --> 22:28.000
So, let's play the controller.

22:28.000 --> 22:32.000
So, this one will host all the logic for the game.

22:32.000 --> 22:36.000
Meaning the Wi-Fi access points.

22:36.000 --> 22:41.000
The small web server, TCP servers, the game interface and all.

22:41.000 --> 22:43.000
I will open a console here.

22:43.000 --> 22:48.000
I will switch to my project directory.

22:48.000 --> 22:51.000
So, here I have all my rest code.

22:51.000 --> 22:55.000
The base has been generated with ESP Generates.

22:55.000 --> 22:57.000
We won't take a look at the code.

22:57.000 --> 22:58.000
This is not the interesting part.

22:58.000 --> 23:01.000
What I will rather do is take my buzzer here.

23:01.000 --> 23:03.000
Plug USB-C.

23:03.000 --> 23:07.000
So, the chip I have selected as USB-C, which is nice.

23:07.000 --> 23:13.000
Plug the other end on my computer where I can.

23:13.000 --> 23:18.000
So, I hope everything is booty.

23:18.000 --> 23:20.000
I will type Kaggle Run.

23:20.000 --> 23:24.000
So, this one will refresh my ESP chip.

23:24.000 --> 23:26.000
And it will also start monitoring the logs.

23:26.000 --> 23:29.000
I made it on the serial line through USB.

23:29.000 --> 23:32.000
So, that's really useful in there.

23:32.000 --> 23:39.000
I will even provide this small ESP log equal my crate to have the debug logs output.

23:39.000 --> 23:41.000
So, let's do this.

23:41.000 --> 23:43.000
No serial.

23:43.000 --> 23:44.000
Oh.

23:44.000 --> 23:47.000
Brace for the demo effect.

23:47.000 --> 23:50.000
Okay.

23:50.000 --> 23:56.000
So, the flash was super fast because it is comparing what is already flashed.

23:56.000 --> 23:58.000
And I had the proper firmware.

23:58.000 --> 24:02.000
And so, here we see the logs in my thing here.

24:02.000 --> 24:07.000
We have to push a button here to make the controller start.

24:07.000 --> 24:12.000
And the first log we are seeing are coming from the dedicated Wi-Fi task.

24:12.000 --> 24:15.000
For example, trying to connect to my controller.

24:15.000 --> 24:17.000
So, it is not started yet.

24:17.000 --> 24:19.000
It should be in a few seconds.

24:19.000 --> 24:24.000
In the meantime, I will try to open a browser.

24:24.000 --> 24:31.000
And access nbc.local slash admin.

24:31.000 --> 24:35.000
So, this is a web page or state on the controller.

24:35.000 --> 24:38.000
We see that the browser has managed to connect.

24:38.000 --> 24:43.000
And so, we have some logs from my JSON passing module here.

24:43.000 --> 24:47.000
Telling that it has received some patterns command.

24:47.000 --> 24:52.000
And so, I will try to show at the same time if I erase you in the game.

24:52.000 --> 24:56.000
Here, and I try to pair the button.

24:56.000 --> 24:59.000
You will see that when I press the button.

24:59.000 --> 25:03.000
There are multiple things happening on the browser side.

25:03.000 --> 25:06.000
The browser has sent an identifiable message.

25:06.000 --> 25:10.000
And we have received some specific pattern.

25:10.000 --> 25:17.000
Please start doing a wave pattern so that the team knows about that the browser is ready.

25:17.000 --> 25:20.000
And so, from there, we can start to play.

25:20.000 --> 25:26.000
And thanks to this whole tooling, I can monitor finally and debug finally all the messages

25:26.000 --> 25:30.000
exchange between my browser and the controller.

25:30.000 --> 25:31.000
So, that's it for the demo.

25:31.000 --> 25:35.000
We won't have time to play a whole game obviously.

25:35.000 --> 25:37.000
Two clothes on this.

25:37.000 --> 25:39.000
I have nvp working.

25:39.000 --> 25:43.000
There are a few things that I want to clarify on this project.

25:43.000 --> 25:45.000
The binary is quite fat currently.

25:45.000 --> 25:48.000
And that's a shame for a no SD program.

25:48.000 --> 25:52.000
We have to improve rest in geometric use,

25:52.000 --> 25:55.000
error management and all.

25:55.000 --> 25:59.000
If you are interested in the project, you have the GitHub link here.

25:59.000 --> 26:04.000
Do not hesitate to take a look to criticize the code or to send PS.

26:04.000 --> 26:05.000
Thank you.

26:05.000 --> 26:09.000
Thank you.

