Cool. Let me start. My name is this here. I work at Grafana in the AI team, which is why I'm
giving a talk at the embedded track. I'm going to be talking about how I'm interacting with
Tesla V. Cos locally, no internet, no nothing, over Bluetooth, low energy using ESP. Before
I start, whenever we say Tesla, obviously we have to mention the richest man on the planet.
So next time, I'll be a good European citizen and by a German car, because German
car brands never did anything controversial.
Let's start. Cool. Where did this start? It started with home assistance. About two
years ago, I got into home assistance. If you haven't got into home assistance, don't
because it's a rabbit hole. But I had an electric car, I had solar panels, I had a home
battery, and I was like, there's something cool I can do here, right, with all these
things. So I'm doing something called dynamic charging, which means like I'm using my solar
excess, I'm using the battery, if I need to be some or quick to boost the charging speed,
I can do load balancing. So if I, you know, somebody is turning on the furnace, it can
like lower the amps going to the car, overload protection, which means like the house
doesn't go over, in my case, like 9.2 kilobits maximum, I can do off-peak charging, and
also in Belgium, I live in Belgium, by the way. We have this thing called capacity tire
of limits, which is a great thing that our government did. And it means like, you know,
if you have an electric car and you're charging, you need to make sure that you don't charge
too much at the same time. It checks every 50 minutes, how much you've used, and uses
that to basically you pay something extra every year. All of the system is hooked up, like,
you know, in a home assistance, I've got like a few settings that I use. And I just update
up to every 10 seconds. Every 10 seconds, I go, how much amps should I be sending to the car,
whether it's plugged in, whether I have solar, whether I have software in my battery. So if you
count it up, that's about like 8,000 more than 8,000 commands per day. And this was working
all fine, right? My home assistance was going to the Tesla Cloud, the Tesla Cloud would send
the command to the car, and every time there was an update, I would update the amps, use the
Tesla API to send that to my car. But then sometime last year, Tesla introduced rate limits,
right? And they would quite severe, right? They introduced rate limits, where you could only send
50 commands per day to the car. I was sending more than 8,000. So obviously, this was not going to work.
So I was like, okay, what can I do? Well, before this, I started getting into like ESP 32 devices,
and they're quite nifty, you know, they're low cost, they're low power, they're pretty small,
so you can like place them anywhere in your home. And they've got Bluetooth low NG built in,
which is the protocol that Tesla uses even in their app to communicate with the car.
But that does come with this challenges, right? There's only like two megabytes of flash,
so it's quite limited. Not a lot of RAM. It's quite low power. It's just a single core running at
160 megahertz. But I'm like, you know, ESP home, doing ESP on with custom C++ is not the easiest thing
in the world, but we gave it a go. The good news, the good news is that Tesla actually open
source their entire vehicle command. So they have their entire vehicle protocol, how to communicate
with the car in an open source app actually to license to get repo, which is great, right?
That this provide me a starting point. The only problem is like this was written in GoLang,
and obviously doing GoLang on ESP 32. Well, technically possible, not the greatest idea in the world.
One thing, well, the first thing you need to know about Tesla, actually has like two subsystems in the car,
right? So there's a system called Vehicle Security, PCSec, and there's a system called Infotainment.
Usually, like you're always talking to this PCSec subsystem first, it controls the locks,
controls most start, it controls things like opening the trunk. You can also get some like simple
data about the car, like, you know, is there a user present, are the doors unlocked or not,
and it is the car awake or not, which is important. And the main thing that this system is always
on, right? It's never go sleep, it's always listening. Infotainment is where the interesting
commands are, right? Like the charging commands, they all live in infotainment. If you want to heat
your car, death lives in infotainment, if you need more data about the car, like what's the current
charging percentage? That lives in infotainment as well. And that's a recent change. That is one nice thing
about Tesla cars is that you do get, I get more updates on it even on my iPhone, and like they added
this in the recent update, just three months ago. The only thing with infotainment is like it consumes a lot of
power, so it will go to sleep when it is not active. One more thing to note, each of these domains,
they have their own public key, so they have their own separate tank shake, and also a separate
session that you need to like authenticate with for each of the two. What else? This is kind of what
it looks like when it's all finished, right? Like I own my ESP home device, there's a pair button,
you click it, you go to your car, and suddenly this thing pops up, right? It says, oh, a new
phone key wants to be added. When you add it, it actually shows up as an actual key in the car.
So depending on like your permissions, you can even like drive the car within the ESP device,
which is maybe cool, but also a security risk potentially. You get a few controls,
like you know, you can change the charging apps, charging limit, this, like I've only implemented
a few, but really we can implement all of the, like you can do the same thing you can do on the app,
including driving off with the car. This is what the vehicle protocol actually looks like, right?
Like this is what the message is, look like that you sent to the car, but also the message is that
you get back from the car. Tesla has this thing called a universal message, and this is what
looks like. It's encoded in ProtoBuff. For those that don't know about ProtoBuff, it's a binary format,
kind of like imagine like Jason, but in binary format, so very efficient, and also it's strongly
typed. So you know exactly what you're going to get at that point at that bite, and you know,
so know how to encode and decode it. If you look at this message, for example, you know,
you can see that like you know, kind of try to highlight it to give you an idea of what that looks like.
You have a two destination. In this case, I'm sending a command to the Infotainment domain.
You have a from destination that is just to tell the car where the message is coming from.
You have a payload. This payload is encrypted, right? So this is a ProtoBuff message.
That thing actually like if you decode it, this is a charging set limit message, and I think in
this case it's like set the charging limit to 82%. And the car needs to figure out how to decode that
using obviously you paired it key before, so it has a private key, but also you have to send a signature
data at this signature data include some stuff you got from the session information. So things like,
you know, every time you try to talk to the car, if you send it and it has an invalid signature,
it will actually thank you back a session information and tell you like, okay, this is the latest
counter, this latest like key identity, and this how you should like, you know, use this to encrypt
the message that you're trying to send. And then finally, a request to you ID, this must be useful for
debugging. You can use this to figure out like, you know, did my request to a true, why did not
go through and so on. On last note, I use Nano PB, Nano PB is really useful for embedded devices.
If you want to do anything with Protobuff, use Nano PB, it's a cool project.
What else ESPBLE? ESP has some built-in Bluetooth low-energy APIs. I'm just giving you like a few
pointers. There's these like events that you will get that you can hook into, and then tell like
in your C++ note, you can basically like do a case statement and then switch between what you should
do. So we have like an event for when the connection is open, we have an event when the connection is closed.
Once we are connected to the car, we can also say like register to notify. We have the link
coming data incoming data also pretty weird. It doesn't always come in one chunk, like sometimes you need
to get like multiple chunks and add them up together, so you need to buffer them, and then also
there's an API to send data. Then the final two things, I know I'm almost at the time, one thing I did
because of this like the chunk incoming messages, and also just to make things easier for myself.
Instead of trying to do everything in that event, I did implement a sort of queue system,
so every time a message comes in, goes into the queue, and then like I can read that part set,
fill in the chunks, same with writing, and same with commands. And the last thing is I'm going to
talk about the command state machine. Like I said, there are two vehicle subsystems, so even if you
want to do something simple, like I want to change the charging amps for the car, charging is in the
infotainment domain, you can only talk to the infotainment domain if the car is awake. So first,
we need to check is the car awake. Cool. If it's not wake up the car, oh wait, I haven't sent a message
to the car for a while, the session info is updated, so now I need to get new session information,
wait for that new session information, update the key information from the session,
now wait for confirmation that the car is awake, then send the command and now wait for the
command to be confirmed. Obviously, just for my own senti, I also have built and retries because
Bluetooth, low energy, it can sometimes, you know, the communication can fail, sometimes the car,
like you send the wake command, the car doesn't immediately wake up, you need to send the second wake command.
And yeah, that's about it. Am I in time? Cool, that is it.