7 min read

How I Set Up an ESP32 BLE Key with my Tesla and Home Assistant for Solar Charging Optimization

TL;DR

I set up an ESP32 M5NanoC6 development kit chip with the esphome-tesla-ble project to connect to my Tesla over Bluetooth. This setup allows the chip to communicate with the car when it’s nearby, using the ESPHome native API to share data with Home Assistant over Wi-Fi. With this integration, I can automate tasks like adjusting charging amperage and starting/stopping charging based on surplus solar energy from my inverter. For now, this guide covers flashing the chip and integrating it with Home Assistant. I’ll follow up with a post to automations designed to optimize charging from excess solar.


Thanks

This wouldn't be possible without Yasir Ekinci who created the tesla-ble library for communicating with Tesla vehicles locally via the BLE API. And, for integrating that work into esphome-tesla-ble so that it works with ESPHome and exposes dashboards in Home Assistant.


Background and Objective

This project uses the esphome-tesla-ble library to enable local BLE communication between an ESP32 and a Tesla, providing an offline alternative to the official Tesla API while avoiding rate limits. The goal is to dynamically manage charging by creating Home Assistant automations, such as adjusting amperage or stopping charging based on solar production. Since the car defaults to the mobile wall charger’s maximum of 32 amps, regulating amperage is essential to prevent exceeding available solar capacity and I needed a way to automate that.


Tested Hardware and Environment

  1. Hardware: ESP32 M5NanoC6 development kit (other models work, but this is the one I used and can confirm is compatible), Tesla Vehicle Key Card.
  2. Environment: Apple Silicon MacBook Pro running macOS Sequoia.
  3. Software: ESPHome Tesla BLE repo by Yoziru, local Home Assistant instance, and ESPHome add-on for Home Assistant.

Flashing the ESP32

The ESP32 chip needs to be flashed twice.

About the First Flash: Enable the BLE Listener
The initial flash enables a BLE (Bluetooth Low Energy) listener on the ESP32. This listener’s purpose is to scan for nearby BLE devices and capture the Tesla’s unique BLE MAC ID. The Tesla emits this MAC ID when you place your key card on the car’s designated holder, signaling the car to start broadcasting BLE data. This step is critical because the Tesla’s BLE MAC ID is required to configure the ESP32 as a BLE key. Without discovering this ID, the ESP32 cannot interact with the Tesla via BLE.

About the Second Flash: Configure and Finalize the ESP32
Once the Tesla’s BLE MAC ID is obtained and added to the configuration (secrets.yaml), the BLE listener is no longer needed. The second flash:

1. Disables the BLE listener to stop scanning for devices (which would interfere with normal operations).

2. Configures the ESP32 to use the discovered Tesla BLE MAC ID to authenticate and act as a BLE key.

3. Finalizes the firmware, allowing the ESP32 to communicate with the Tesla and control features such as charging and amperage settings.


The following steps assume you already have Home Assistant set up and have an ESP32 M5NanoC6 chip.

Flashing the chip and integrating it with Home Assistant

1. Set up your Python environment and clone the ESPHome Tesla BLE repository:

# Create a new Python 3.11 virtual environment named 'esphome-tesla-ble'
python3.11 -m venv esphome-tesla-ble

# Change into the newly created virtual environment directory
cd esphome-tesla-ble

# Activate the virtual environment
source bin/activate

# Clone the yoziru/esphome-tesla-ble repository from GitHub
git clone https://github.com/yoziru/esphome-tesla-ble

# Change into the cloned repository directory
cd esphome-tesla-ble

# Install the required Python dependencies from the requirements file
pip install -r requirements.txt

2. Configure secrets.yaml

Before compiling, create and populate a secrets.yaml file at esphome-tesla-ble/esphome-tesla-ble file with your Wi-Fi credentials, an API encryption key, default BLE macID, and your Tesla VIN:

wifi_ssid: "my_wifi"
wifi_password: "my_password"
wifi_hotspot_password: "my_hotspot_password"
ota_password: ""
api_encryption_key: "my_encryption_key" # random key from https://esphome.io/components/api.html#configuration-variables
ble_mac_address: "A0:B1:C2:D3:E4:F5"
tesla_vin: "my_tesla_vin"

3. Enable the BLE Listener

In the tesla-ble-m5stack-nano6.yml configuration file, enable the BLE listener by uncommenting the line so it looks like this:

listener: !include packages/listener.yml

This instructs the ESP32 to run in “listening mode” after the first flash.

4. Compile the Firmware

Run the following command inside esphome-tesla-ble/esphome-tesla-ble to compile the firmware for the M5NanoC6 board:

make compile BOARD=m5stack-nanoc6

This will generate the firmware binary tailored to your ESP32 board with the BLE listener enabled.

Note: If you're using a different chip than me you could try just pointing at the yaml you're using and compile like this esphome compile tesla-ble-esp32-generic.yml

5. Flash the ESP32 the first time

Now upload the compiled firmware to the ESP32 from esphome-tesla-ble/esphome-tesla-ble:

  • Connect the ESP32 to your computer via USB.
  • Run the upload command
make upload
  • When prompted, select the USB port for your ESP32 (e.g., /dev/cu.usbmodem1101).

6. In your terminal note down the ESP32 Device Name Suffix

After flashing, the ESP32 will reboot and appear with a name like tesla-ble-<suffix>. The <suffix> is a unique identifier, such as 5ae9cc. Note this suffix, as you’ll use it to monitor logs in a future step.

7. Locate the ESP32’s IP Address on Your Network

Using a network scanner, or by logging in to your router’s admin interface, check for the ESP32 device on your Wi-Fi network and note its IP Address as you may need it to add the device manually to Home Assistant if it’s not auto-discovered:

  • Manufacturer: Espressif Inc.
  • MAC Address: May start with 40:4C:CA
  • Name: Might appear as tesla-ble-<suffix>.lan (though this may not resolve due to your network config, eg using stuff like Tailscale).

Note: If you end up having to manually add the ESP device by its IP address you might want to consider setting the ESP device with a reserved IP address on your router.

8. Install the ESPHome add-on to Home Assistant

In Home Assistant, I navigated to Settings > Devices & Services, I tapped on Add Integration and searched for and installed the ESPHome addon.

9. Add the ESPHome device to Home Assistant and Configure

My ESP32 immediately appeared as a device ready to be added. If you don't see yours you can add it by its IP Address.

After adding the device, I entered my encryption key when prompted.

Then, I scrolled to the configured devices, selected ESPHome, and enabled debug logging. This allows me to use the logs in Home Assistant to debug but I stuck with my terminal for debugging.

Under the 1 device section, I accessed the diagnostics menu, enabled the BLE Connection, and confirmed that pressing the physical button on the ESP32 temporarily toggled the diagnostics Button status to “On.”

10. Monitor Logs to Discover Tesla BLE MAC ID

Open a new terminal tab. With the ESP32 in listening mode, you can now monitor its logs to find your Tesla’s BLE MAC ID:

  • Run the following command in the terminal:
make logs HOST_SUFFIX=-<suffix>

Note: Replace <suffix> with the unique identifier from Step 6 (e.g., mine would be make logs HOST_SUFFIX=-5ae9cc).

11. Take your computer, ESP32, and Tesla key card to your vehicle

Sitting inside the car being sure your chip can get wifi, place your Tesla key card on the armrest holder, and monitor the logs. The Tesla should begin to broadcast its BLE MAC ID, which will be displayed in the terminal output.

[20:04:45][I][tesla_ble_listener:050]: Found Tesla vehicle | Name: [VIN_REDACTED]
MAC: BO:F8:XX:XX:XX

12. Update Secrets.yaml with BLE macID

Update secrets.yaml file at esphome-tesla-ble/esphome-tesla-ble and replace the ble_mac_address field with your macID (eg BO:F8:XX:XX:XX):

ble_mac_address="BO:F8:XX:XX:XX"

13. Disable the BLE Listener

In the tesla-ble-m5stack-nano6.yml configuration file, disable the BLE listener by commenting the line so it looks like this:

# listener: !include packages/listener.yml

This instructs the ESP32 to stop running in “listening mode” since it's no longer necessary.

14. Flash the ESP32 the second time

make clean
make compile BOARD=m5stack-nanoc6
make upload

When prompted, select the USB port for the ESP32 (e.g., /dev/cu.usbmodem1101).

15. Pair the ESP32 as a Tesla Key

  • Return to Home Assistant and navigate to the ESPHome diagnostics screen.
    • Settings > Devices & Services, scroll to the configured section and find ESPHome and tap on 1 device
  • On the ESPHome diagnostics card tap the text that says Press next to "Pair BLE Key".
  • Place your Tesla key card on the armrest again and accept the pairing request from the car. After accepting, rename the key to something memorable like ESPHome Key since it will otherwise be called Unknown device.
M5nanoC6 ESP chip paired as a keycard with Tesla

16. Confirm integration works in Home Assistant

  • On the ESPHome diagnostics screen attempt to adjust the controls such as charging amps and confirm it updates in realtime in the car charging UX.

Results

After completing these steps, the ESP32 successfully connected to Home Assistant and began sending and receiving data from the Tesla. It's now possible to view Tesla sensors and controls in Home Assistant:

  • Wake Vehicle
  • Set charging amps
  • Set charging limit (percent)
  • Turn on/off charging
  • BLE information sensors
    • Asleep / awake
    • Doors locked / unlocked
    • User present / not present
    • Charging flap open / closed (only when vehicle is awake)
    • BLE signal strength

Next Steps

  • Create Automations: Set up Home Assistant automations to dynamically manage Tesla charging based on solar production.