This project PedroKTFC/esphome-tesla-ble lets you use an ESP32 device to manage charging a Tesla vehicle over BLE. It is a fork of the yoziru/esphome-tesla-ble and uses a similar fork of the yoziru/tesla-ble library.
| Controls | Sensors-1 | Sensors-2 | Diagnostic |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
I’ve put this section at the start because it seems people don’t always read all the way to the end! So please read this section at least.
[!TIP] Always start from the example yaml
tesla-ble-example.yml. This has been tested many times and should work in almost every case.
If the build fails, try the following (assuming you’re building using the Home Assistant ESPHome builder):
[!TIP] If these don’t work, raise an issue and include a copy of your yaml and that part of your log that shows the error and I’ll try to work out what’s going wrong. (If you don’t provide these, I’m afraid I’ll simply ask you for them in the issue, I can’t help without any information.)
These are implemented as switches, covers, buttons or numbers. Where indicated, these use the current sensor value for the control (but be aware that changing a value/state has a delay before it is reflected in the corresponding sensor - it takes time to send the messages to the vehicle to make the control and then read back the new value - it might look like the control has been rejected as the value reverts to the previous value; be patient!).
There are two categories, those available even when asleep and those only when awake.
These are the diagnostic button actions:
There are also several self-explanatory sensors. The BLE Status sensor reports if the ESP board is connected to the car. By default this reports the car as disconnected if the car isn’t seen for more than 5 seconds.
[!TIP] There is a subsitution value
ble_presence_timeoutavailable to change this if you wish. For example, to change it to two minutes use ` ble_presence_timeout: 120s`.
There are five number and two switch actions that allow the dynamic update of the polling parameters (see below). These are disabled by default as I recommend they should be changed through yaml but they are useful for tuning/debugging your setup. If enabled, their setting takes priority over the yaml definition and they are preserved over a reboot. Note there is no equivalent to the update_interval parameter - this can still only be updated through yaml (and so a re-build). The following lists them with the equivalent polling parameter:
See below for build instructions for different board types.
There are several parameters that determine the polling activity which are described in the table below. The polling engine loops every update_interval seconds and, as a minimum, polls the car’s VCSEC system. All other polls are based on this so that if any of the other parameters are not multiples of update_interval, the timings will be longer than expected. For example, if update_interval is set to 30s and poll_data_period is set to 75s, then the effective poll_data_period will be 90s.
| Name | Type | Default | Supported options | Description |
|---|---|---|---|---|
update_interval |
number | 10s | any interval | This is the base polling rate in seconds. No other polls can happen faster than this even if you configure them shorter. The base polling checks the overall status using the car’s VCSEC system (Vehicle Controller and Safety Electronics Controller, the central electronic control unit of a Tesla vehicle). It is polled at this rate and does not wake the car when asleep or prevent the car from going to sleep. |
post_wake_poll_time |
number | 300 | >0 seconds | If the vehicle wakes up, it will be detected and the vehicle will be polled for data at a rate specified in poll_data_period for at least this number of seconds. After this, polling will fallback to a rate specified in poll_asleep_period. E.g. Suppose post_wake_poll_time=300, poll_data_period=60 and poll_asleep_period=120. In this case, when the care awakes, initially data will be polled each 60s for the first 300s. Then polling will continue each 120s. |
poll_data_period |
number | 60 | >0 seconds | The vehicle is polled every this parameter seconds after becoming awake for a period of post_wake_poll_time seconds. Note the vehicle can stay awake if this is set too short. |
poll_asleep_period |
number | 60 | >0 seconds | The vehicle is polled every this parameter seconds while being asleep and beyond the post_wake_poll_time after awakening. If set too short it can prevent the vehicle falling asleep. |
poll_charging_period |
number | 10 | >0 seconds | While charging, the car can be polled more frequently if desired using this parameter. |
ble_disconnected_min_time |
number | 300 | >0 seconds | Sensors will only be set to Unknown if the BLE connection remains disconnected for at least this time (useful if you have a slightly flakey BLE connection to your vehicle). Setting it to zero means sensors will be set to Unknown as soon as the BLE connection disconnects. |
fast_poll_if_unlocked |
number | 0 | 0, >0 | Controls whether fast polls are enabled when unlocked. If the vehicle is unlocked (and fast_poll_if_unlocked > 0), it will be polled at update_interval until it is locked. This could be useful if you wish to quickly detect a change in the vehicle (for example, I use it to detect when it is put into gear so I can trigger an automation to open my electric gate). Set to 0 to disable, any value > 0 to enable. |
wake_on_boot |
number | 0 | 0, >0 | Controls whether the car is woken when the board restarts. Set to 0 to not wake, any value > 0 to wake. |
Note that while a user is present in the car (recall this is a VCSEC status so is polled for even when the car is asleep), polling will occur at update_interval and all sensors updated.
By default the car reports distances in miles and pressures in bars, so this integration returns these units. In Home Assistant you can edit any sensor and select the preferred unit of measurement there.
Recommended path
Alternative
Recommended path
Use an appropriate BLE app on your phone (eg BLE Scanner) to scan for the BLE devices nearby (so be close to your car). You should see your car in the list of devices (its name will begin with an ‘S’) with the MAC address displayed.
Copy and rename secrets.yaml.example to secrets.yaml and update it with your WiFi credentials (wifi_ssid and wifi_password) and vehicle VIN (tesla_vin) and BLE MAC adress (ble_mac_address).
Note the car’s VIN is displayed in the windscreen, the Tesla app and (probably) your registration documents. In my case it begins with “LRW…”. It is not the BLE beacon name you get when determining the BLE MAC address.
Alternative
Build the scanner in the ble-scanner.yml file. Once built, it will start scanning and print out the MAC address of any Tesla vehicles found in the logs. Building does take some time.
The following is the original method. I have never tried this and I do not maintain the associated file. I therefore do not recommend this but have left it here in case there are any people left who still use it.
secrets.yaml.example to secrets.yaml and update it with your WiFi credentials (wifi_ssid and wifi_password) and vehicle VIN (tesla_vin).tesla_ble_listener package in packages/base.yml by uncommenting the listener: !include listener.yml line.Note: The vehicle must be in range and awake for the BLE MAC address to be discovered. If the vehicle is not awake, open the Tesla app and run any command
[00:00:00][D][tesla_ble_listener:044]: Parsing device: [CC:BB:D1:E2:34:F0]: BLE Device name 1 [00:00:00][D][tesla_ble_listener:044]: Parsing device: [19:8A:BB:C3:D2:1F]: [00:00:00][D][tesla_ble_listener:044]: Parsing device: [19:8A:BB:C3:D2:1F]: [00:00:00][D][tesla_ble_listener:044]: Parsing device: [F5:4E:3D:C2:1B:A0]: BLE Device name 2 [00:00:00][D][tesla_ble_listener:044]: Parsing device: [A0:B1:C2:D3:E4:F5]: S1a87a5a75f3df858C [00:00:00][I][tesla_ble_listener:054]: Found Tesla vehicle | Name: S1a87a5a75f3df858C | MAC: A0:B1:C2:D3:E4:F5
tesla_ble_listener package in packages/base.yml and running
make clean
For an example ESPHome dashboard, see tesla-ble-example.yml. Please always start from this. I strongly recommend building this using the ESPHome Device Builder add-on in Home Assistant as this makes building and re-building (eg for updates) much easier.
Various board types have been shown to work with this project. Always start from tesla-ble-example.yml. Some boards require additional/changed yaml, please refer to the wiki.
The tesla-ble-example.yml file is setup to be used with a standard ESP32 device.
The following are instructions if you use make. I have never used these so cannot vouch for their accuracy (as I said above, it’s far easier to use the ESPHome Device Builder add-on in Home Assistant). I welcome any feedback on improving/correcting these instructions - please raise an issue for it.
secrets.yaml.example to secrets.yaml and update it with your WiFi credentials (wifi_ssid and wifi_password) and vehicle details (ble_mac_address and tesla_vin)Build the image with ESPHome. Alternate boards are listed in the boards/ directory.
make compile BOARD=m5stack-nanoc6
Upload/flash the firmware to the board.
make upload BOARD=m5stack-nanoc6
After flashing, you can use the log command to monitor the logs from the device. The host suffix is the last part of the device name in the ESPHome dashboard (e.g. 5b2ac7).
make logs HOST_SUFFIX=-5b2ac7
For updating your device, you can OTA update over local WiFi using the same host suffix:
make upload HOST_SUFFIX=-5b2ac7
Note: the make commands are just a wrapper around the
esphomecommand. You can also use theesphomecommands directly if you prefer (e.g.esphome compile tesla-ble-m5stack-nanoc6.yml)
secrets.yaml file when prompted.secrets.yaml is correct. IT IS ESSENTIAL THESE ARE CORRECT - YOUR CAR WILL NOT PAIR OTHERWISE.Note: if the popup does not appear, you may need to press “Pair BLE key” and tap your card again

[optional] Rename your key to “ESPHome BLE” to make it easier to identify
