This repository provides an ESPHome custom component that exposes the most important control features of the ESP32-EVSE charging controller. It's mainly intended to be used in a custom HMI screen based on ESPHome and LVGL.
It was developed and tested with board ESP32-S2 EVSE DIY ALPHA (aka. esp32s2-evse-d-a) in fixed cable configuration. The communication implements the AT Commands.
Why would you complement ESP32-EVSE with another ESP32 running ESPHome? You can extend its functionality independently, increasing flexibility:
- make HMI/graphical UI rendered via LVGL, on an ESP32-based screen, with fully open source resources (no proprietary editor needed)
- optinally connect to Home Assistant via native API (or MQTT to other systems), exposing the EVSE as a bunch of sensors and controls
- implement any custom authorization like RFiD readers etc.
- multiple UARTs can be configured (eg one talking to EVSE, other talking to smart meter etc), make own Dynamic Load Management through HA or other ESPHome components (eg use data from other meters in various ways; freely implement DLM logic either in HA or in ESPHome)
- can use free GPIOs or the display for anything else
- has Bluetooth and with it you could pair with your car and implement additional related features (eg open charging flap automatically, poll battery status, temperature; garage door control etc, which wouldn't have to interfere with EVSE board at all)
- the EVSE not having to deal with any of the above, can keep working independently as a mission critical piece of hardware
You need at least ESPHome 2026.3.0.
Use an ESP32-based board supported by ESPHome. The component communicates with ESP32-EVSE (min. version 2.0.1) via UART at 115200 baud rate. Check out the HMI screen based on ESPHome and LVGL repository for example display hardware configurations.
Enter your ESP32-EVSE web UI and in Settings > Serial, select for the UART port Mode: AT Commands. Baud rate: 115200, Data bits: 8, Stop bits: 1, Parity: Disable. Press Submit.
With the esp32s2-evse-d-a board you can use a 4-pin cable with 2.5mm JST wired correctly for RX/TX/GND/5V:
| ESP32-EVSE S2 DA U6 UART (2.5mm JST) |
|---|
| 1: GND |
| 2: TX |
| 3: RX |
| 4: +5V |
Use cable as short as possible.
Configure the UART as per ESPHome docs, and instantiate the EVSE component and link it to the configured UART bus:
uart:
id: evse_uart
tx_pin: GPIOXX
rx_pin: GPIOXX
baud_rate: 115200
stop_bits: 1
parity: NONE
esp32evse:
id: evse
uart_id: evse_uart
update_interval: 60s # Optional: adjust how often the component polls the charger (10s–10min), defaults to 60s.sensor:
- platform: esp32evse
esp32evse_id: evse
emeter_power:
name: "EVSE Power"
emeter_charging_time:
name: "EVSE Charging Time"
emeter_session_time:
name: "EVSE Session Time"
energy_consumption:
name: "EVSE Session Energy"
total_energy_consumption:
name: "EVSE Total Energy"
voltage_l1:
name: "EVSE Voltage L1"
voltage_l2:
name: "EVSE Voltage L2"
voltage_l3:
name: "EVSE Voltage L3"
current_l1:
name: "EVSE Current L1"
current_l2:
name: "EVSE Current L2"
current_l3:
name: "EVSE Current L3"
temperature_high:
name: "EVSE Temperature High"
temperature_low:
name: "EVSE Temperature Low"
wifi_rssi:
name: "EVSE Wi-Fi RSSI"
heap_used:
name: "EVSE Heap Used"
heap_total:
name: "EVSE Heap Total"
uptime:
name: "EVSE Uptime"If your installation only uses a single temperature sensor, expose it via the combined temperature key instead of the individual high/low entries:
temperature:
name: "EVSE Temperature"binary_sensor:
- platform: esp32evse
esp32evse_id: evse
pending_authorization:
name: "EVSE Pending Authorization"
charging_limit_reached:
name: "EVSE Charging Limit Reached"
wifi_connected:
name: "EVSE Wi-Fi Connected"
pilot_fault:
name: "EVSE Fault Pilot"
diode_short_fault:
name: "EVSE Fault Diode Short"
lock_fault:
name: "EVSE Fault Lock"
unlock_fault:
name: "EVSE Fault Unlock"
rcm_triggered_fault:
name: "EVSE Fault RCM Triggered"
rcm_self_test_fault:
name: "EVSE Fault RCM Self-Test"
temperature_high_fault:
name: "EVSE Fault Temperature High"
temperature_sensor_fault:
name: "EVSE Fault Temperature Sensor"
timeout_fault:
name: "EVSE Fault AT Timeout"The fault sensors above expose individual bits from the EVSE's AT+ERROR status mask except timeout_fault which is triggered when communication between ESPHome and EVSE times out.
text_sensor:
- platform: esp32evse
esp32evse_id: evse
state:
name: "EVSE State (J1772)"
device_name:
name: "EVSE Device Name"
device_time:
name: "EVSE Device Time"
wifi_sta_ssid:
name: "EVSE Wi-Fi SSID"
wifi_sta_ip:
name: "EVSE Wi-Fi IP"
wifi_sta_mac:
name: "EVSE Wi-Fi MAC"
chip:
name: "EVSE MCU"
build_time:
name: "EVSE Build Time"
version:
name: "EVSE Firmware Version"
idf_version:
name: "EVSE IDF Version"switch:
- platform: esp32evse
esp32evse_id: evse
enable:
name: "EVSE Charging Enable"
available:
name: "EVSE Available"
request_authorization:
name: "EVSE Request Authorization"
three_phase_meter:
name: "EVSE Three-Phase Meter"button:
- platform: esp32evse
esp32evse_id: evse
authorize:
name: "EVSE Authorize"
restart:
name: "EVSE Restart"
start_ap:
name: "EVSE Start Wi-Fi AP"number:
- platform: esp32evse
esp32evse_id: evse
charging_current:
name: "EVSE Charging Current"
default_charging_current:
name: "EVSE Default Charging Current"
maximum_charging_current:
name: "EVSE Maximum Charging Current"
consumption_limit:
name: "EVSE Consumption Limit"
default_consumption_limit:
name: "EVSE Default Consumption Limit"
charging_time_limit:
name: "EVSE Charging Time Limit"
default_charging_time_limit:
name: "EVSE Default Charging Time Limit"
under_power_limit:
name: "EVSE Under Power Limit"
default_under_power_limit:
name: "EVSE Default Under Power Limit"- Rename entities to match your automation platform naming convention.
- Use
internal: truefor fast updating sensors (voltage and current) you might not need in the Home Automation system to avoid database overload. - Adjust the
maximum_charging_currentto match the electrical limits of your installation (eg. addmax_value: 32parameter if you have 32A breakers in the branch protecting the EVSE, for cascaded breakers use the value of the lowest one). - Omit the entities you don't want to use, to reduce resource usage on the device.
ESP32-EVSE is able to periodically push values without waiting for query commands.
The component exposes dedicated automation actions that wrap the AT+SUB
and AT+UNSUB commands. Check out the
AT Commands documentation
for details.
Example: To subscribe the emeter_power sensor to push updates every second (use any
valid ESPHome time
bigger than 100ms):
on_...:
- esp32evse.emeter_power.subscribe: 1sProvide never to stop receiving updates for the same entity:
on_...:
- esp32evse.emeter_power.subscribe: neverAnd use esp32evse.unsubscribe_all to clear every active subscription in one
shot:
on_...:
- esp32evse.unsubscribe_all:Note: A few subscription actions control multiple sensors because the EVSE reports them together:
esp32evse.temperature.subscribedrives bothtemperature_highandtemperature_lowesp32evse.heap.subscribeupdatesheap_usedandheap_totalesp32evse.voltage.subscribeupdates all phase-specific voltage measurementsesp32evse.current.subscribeupdates all phase-specific current measurementsesp32evse.error.subscribedrives all the fault binary sensors
With esp32evse.force_update: acttion you can trigger updating all the entities on demand.
The component implements the on_ready trigger to detect when ESP32-EVSE is ready to communicate. This is useful when the EVSE board reboots independently from the ESPHome device. If ESP32-EVSE is configured to use AT Commands, when loading the interface it will send the RDY message to the AT client to inform about readyness of operation.
For example the configuration below will re-establish the subscriptions needed for usual operation:
esp32evse:
...
on_ready:
- esp32evse.unsubscribe_all:
- esp32evse.force_update:
- esp32evse.state.subscribe: 500ms
- esp32evse.enable.subscribe: 500ms
- esp32evse.error.subscribe: 3s