Skip to content

ESPHome 2026.6.0 - June 2026

ESPHome 2026.6.0 raises the default WiFi security mode on ESP8266 to WPA2, finally makes WiFi and ethernet enable_on_boot: false reclaim the 15–30 KB and 3–8 KB of internal SRAM they were always supposed to, and delivers up to 4.5× faster LVGL config validation that the new device builder relies on. A wide audio-stack modernization brings zero-copy ring buffers, any-bit-depth mixing, and a new router speaker, while a multi-PR effort prepares the codebase for ESP-IDF 6 and native RISC-V clang-tidy. The release also adds a new motion IMU framework with BMI270 and LSM6DS drivers, two USB-serial drivers, a PCM5122 audio DAC, YAML frontmatter, and a top-level build_flags option that finally works on native IDF.

  • If you use an ESP8266 on a legacy WPA-only (TKIP) router, pin min_auth_mode: WPA under wifi: or the device will stop associating
  • If you use the dsmr electricity_switch_position sensor, move it from sensor: to text_sensor:
  • If you use the nextion display with dump_device_info: true, remove that option (device info is always logged now)
  • If you still load components from a custom_components/ folder, migrate them to external_components:
  • If your time: component uses platform: homeassistant with an explicit timezone:, note that Home Assistant will no longer override your configured zone
  • If you use the dlms_meter component with the provider: option, expect a deprecation warning; the option is now ignored and will be removed in 2026.11.0
  • If you maintain external components calling mark_failed("...") or status_set_error("..."), switch to mark_failed(LOG_STR("...")) / status_set_error(LOG_STR("..."))
  • If you maintain external components using cv.only_with_esp_idf or CORE.using_esp_idf, replace them with cv.only_on_esp32 / CORE.is_esp32
  • If you have lambdas calling text_sensor->raw_state, switch to text_sensor->get_raw_state()
  • If you have lambdas referencing the mipi_dsi::MIPI_DSI C++ type, rename it to mipi_dsi::MipiDsi

ESP8266 Default WiFi Security Raised to WPA2

Section titled “ESP8266 Default WiFi Security Raised to WPA2”

ESP8266 now defaults to min_auth_mode: WPA2, matching the ESP32 default that has shipped for years. ESPHome has been printing a deprecation warning on every ESP8266 config without an explicit min_auth_mode since 2026.1, calling out exactly this flip. With ~40% of ESPHome installs running on ESP8266 hardware, this is the broadest platform-wide change in the release (#16682 by @swoboda1337).

Configurations connecting to modern WPA2/WPA3 access points need no change. Devices on legacy WPA-only (TKIP) routers must pin the old behavior explicitly:

wifi:
min_auth_mode: WPA

WiFi and Ethernet Now Truly Free Their Memory When Disabled at Boot

Section titled “WiFi and Ethernet Now Truly Free Their Memory When Disabled at Boot”

enable_on_boot: false on wifi: and ethernet: previously skipped only the start() call, leaving the entire driver resident in DMA-capable internal SRAM. Two PRs by @kbx81 split the heavy allocation work into a lazy-init path that only runs when the interface is actually enabled, so a dormant interface now costs zero internal RAM.

Reclaimed memory on ESP32:

  • WiFi: roughly 15–30 KB of DMA-capable internal SRAM freed when enable_on_boot: false (#16606). Field-tested on ESP32-S3 with W5500 SPI ethernet
    • I2S audio + bluetooth_proxy: free internal SRAM under peak load went from ~14 KB to ~32 KB, with min-free measurements reaching 78 KB in some configurations.
  • Ethernet: roughly 3–8 KB freed when enable_on_boot: false, matching parity with the WiFi lifecycle (#16607). Brings ethernet.enable / ethernet.disable actions and ethernet.connected / ethernet.enabled conditions, mirroring the WiFi automation surface.

This is groundwork for running WiFi and ethernet side by side in a single configuration: each interface can now be brought up on demand without paying for the one that is not in use.

The W5500 SPI driver also got a CPU win in #16596 by @kahrendt: large frame transfers now go through an interrupt-driven DMA path instead of busy-waiting the CPU. Measured streaming 48 kHz 24-bit FLAC over W5500, ethernet task CPU usage dropped from ~5% to ~3.8%, roughly a quarter lower.

LVGL Configuration Validation Up to 4.5× Faster

Section titled “LVGL Configuration Validation Up to 4.5× Faster”

The new device builder UI revalidates configurations on every save, which made esphome config latency a direct UX cost. LVGL configs were the worst offender. A five-PR series by @bdraco attacks the hot path in LVGL schema construction:

  • Memoize and lazily build container_schema (#16567) - repeated validation median dropped from 210 ms to 17 ms on a representative LVGL config.
  • Build widget update action schemas lazily (#16569) - saves roughly 200 ms at lvgl import time.
  • Merge dict-extend chains (#16614) - 2.81× speed-up on read_config (0.246 s → 0.087 s on the lvtest host.yaml).
  • Memoize obj_schema by widget type (#16615) - 2.14× speed-up stacked on top.
  • Build automation_schema event validators lazily (#16633)
    • 4.5× reduction in per-call cost (281 ms → 63 ms across 29 widget types in a microbench).

The user-visible effect: every save in the device builder is noticeably snappier, especially on configurations with large LVGL screens.

@kahrendt led a wide-ranging audio rework this cycle, replacing the allocate-and-copy AudioSourceTransferBuffer pattern with a zero-copy RingBufferAudioSource across the critical audio paths.

Zero-copy ring-buffer rollout eliminates one allocation and one extra copy per chunk of audio processing:

  • resampler (#16560)
  • AudioDecoder for the speaker media player (#16564)
  • micro_wake_word (#16595)
  • voice_assistant (#16597) - also drops two 1024-byte send buffers in favor of reading directly from the ring buffer

Mixer supports any bit depth (#16524). The mixer speaker now accepts 8, 16, 24, or 32 bits per sample, lifting the last remaining 16-bit-only restriction from the audio stack. Backed by esp-audio-libs v3.1.0 / v3.2.0, with the upstream library using template specializations to keep the new code paths as fast as the old 16-bit-only version.

Resampler bit-depth pass-through (#16892). Now that the mixer handles any bit depth, the resampler defaults to passing the input audio's bit depth through unchanged rather than auto-converting to match the output speaker. This avoids burning CPU cycles in the resampler when the downstream mixer would do a faster conversion anyway.

New router speaker component (#16592) for switching between output speakers at runtime via the router.speaker.switch_output action. A typical use case is switching between SPDIF and analog I2S outputs live from a select entity, with audio staying in sync after the switch. See router for details.

micro_wake_word task stack can live in PSRAM (#16632), saving roughly 3 KB of internal SRAM on the ESP32-S3 with no measurable performance impact. Set task_stack_in_psram: true.

PSRAM task-stack handling consolidated (#16628) so audio_file, audio_http, mixer, resampler, sendspin, and speaker.media_player all share the same validation pattern, with a bug fix for task_stack_in_psram: false on the speaker media player.

A multi-PR effort by @swoboda1337 makes static analysis substantially better at catching real-firmware bugs:

  • script/clang-tidy now supports RISC-V targets natively (#16809)
    • clang's upstream RISC-V backend can now analyze ESP32-C3/C6/H2/P4 builds instead of falling back to the 32-bit x86 stand-in that was used for the Xtensa path.
  • Native ESP-IDF clang-tidy is now the comprehensive pass (#16823). The arduino toolchain has a blind spot where its headers pull std:: float math overloads into the global namespace, hiding performance-type-promotion-in-math-fn findings. The IDF toolchain catches them.
  • Float-to-double promotion fixed across the codebase (#16812) - display, daikin_arc, nau7802, sgp4x, thermopro_ble, tuya all switched from C <math.h> to the float-typed std:: overloads, keeping math in float on 32-bit MCUs instead of needlessly promoting to double.
  • clang-tidy passes on ESP-IDF 6 (#16850) - sdkconfig pinned to newlib, GCC-only flags stripped, ledc HAL guard added under static analysis. This is the foundation for upcoming ESP-IDF 6 support.
  • arduino-esp32 stub for managed IDF components (#16695)
    • on PlatformIO, components like FastLED that declare REQUIRES arduino-esp32 now resolve to a stub that re-exports the framework via CMake INTERFACE, instead of the IDF Component Manager trying to download a duplicate.
  • 100% patch coverage gating (#16827 by @jesserockz) - new PRs must cover every changed line. The project-level coverage stays informational so contributors are not penalized for pre-existing untested code.

@clydebarrow landed a coordinated IMU stack: a generic motion hub component that provides acceleration, angular rate, and derived pitch/roll values, plus actions for automatic pitch/roll calibration (#16226). Two concrete drivers ride on top:

  • Bosch BMI270 (#16202) - used in M5Stack Tab5 and Espressif's EchoEar
  • STMicro LSM6DS3TR-C (#16232) - used in the Seeed ReTerminal D1001

New sensors and DACs:

  • PCM5122 audio DAC by @remcom (#15709) - the Texas Instruments stereo I2S DAC popular in Raspberry Pi HATs, with mute, digital volume, and four configurable GPIO pins exposed through the standard pin schema.
  • XDB401 pressure sensor by @RT530 (#15108) - I2C pressure and temperature from the XIDIBEI XDB401.

USB-serial drivers by @p1ngb4ck:

  • FTDI FT23XX family (#14587) - covers FT232R, FT2232C, FT2232H, FT4232H, FT232H, FT230X, and AM/BM variants; chip type auto-detected from the USB descriptor; multi-channel chips supported as separate channels.
  • Prolific PL2303 family (#16885) - covers the legacy PL2303H/HX through the modern G-series; baud rate encoding selected per chip type.

New display: WAVESHARE-ESP32-S3-TOUCH-AMOLED-2.16 added to the mipi_spi driver (#16887 by @clydebarrow).

@Tomer27cz refactored the dlms_meter component to use the external dlms_parser library (#15458), substantially broadening smart-meter support:

  • Dynamic OBIS code schema - define custom sensors, text sensors, or binary sensors by their OBIS code (e.g. "1-0:99.99.9") instead of being limited to the hardcoded property list.
  • Binary sensor support is new.
  • Decryption key now optional - meters that broadcast plaintext are supported directly.
  • Flexible UART baud rate - the 2400-baud requirement is gone; configure the UART to whatever your meter speaks.
  • New configuration variables - auth_key, custom_patterns, skip_crc, and receive_timeout for meters with non-standard behavior.

The legacy schema continues to work and the provider key is now ignored with a deprecation warning, slated for removal in 2026.11.0. Existing configurations should still validate without change.

The companion DSMR component also got a fix and feature pass (#16561 by @PolarGoose), including support for EON Hungary meters, custom auth keys, and automatic hex-string detection in equipment ID fields. Note that electricity_switch_position moved from sensor to text_sensor, which may need a YAML update.

Zephyr IPv6 networking on nRF52 (#16336 by @Ardumine) is the first step toward OpenThread support on the nRF52840 via Zephyr. Adds a Zephyr-specific IPAddress class backed by struct in6_addr, networking Kconfig, and three new nRF52 network test fixtures. IPv6 defaults to enabled on nRF52.

RP2350 / RP2040 variant config (#16602 by @jesserockz) brings the ESP32-style variant option to the rp2040 platform block, so the same platform can target the RP2040 or RP2350 and emits matching USE_RP2040_VARIANT_<VARIANT> build flags. The variant is auto-derived from the board's MCU; specifying both must match.

esp32_hosted PSRAM transport buffers (#16627 by @swoboda1337) - new use_psram: true option moves the esp_hosted transport mempool out of DMA-capable internal RAM and into PSRAM, fixing boot-time sdio_mempool_create asserts on memory-tight ESP32-P4 + LVGL UI configurations.

YAML frontmatter (#16552 by @jesserockz) - a leading ----separated YAML document is now treated as opaque metadata, stripped before validation, and captured per-file on CORE.frontmatter. Future tooling (including the device builder) can consume arbitrary user metadata like author, version, labels:

author: Jesse Hills
version: 1.0.0
labels: [office, climate]
---
esphome:
name: my-node

esphome.build_flags for IDF + PlatformIO (#16629 by @swoboda1337) - a top-level esphome.build_flags list now applies compiler flags on both backends. The existing platformio_options.build_flags was PlatformIO-only; users on native IDF (ESP32-P4, ESP32-H2) needed this.

esphome config --no-defaults (#16718 by @jesserockz) emits only the user-supplied configuration after substitutions and packages resolve, without the hundreds of injected schema defaults. Useful for diffing configs, sharing minimal reproductions in issues, and sanity-checking what was actually typed.

Codeberg short-form Git URLs (#16501 by @Eelviny) - codeberg://owner/repo/path/file.yaml is now a supported source for dashboard_import and short-form packages, alongside github:// and gitlab://.

github:// framework source (#16639 by @swoboda1337) - esp32.framework.source now accepts github://owner/repo@ref and https://github.com/owner/repo.git@ref, doing a git clone --depth=1 --recurse-submodules instead of downloading an archive. This is needed because GitHub archive URLs strip submodules, which ESP-IDF relies on heavily (mbedtls, openthread, tinyusb, …). Primary use case is testing against pre-release ESP-IDF before any tagged release ships a new chip.

Sensitive value redaction (#16690 by @bdraco) is now driven by cv.sensitive() markers in the schema rather than a post-dump regex. WiFi SSIDs are now marked sensitive, joining passwords. External components using the new marker get redaction automatically; the regex fallback stays as a deprecation bridge through 2026.12.0.

State reporting CLI control (#16746 by @clydebarrow) - the logs command gained a --states / --no-states flag and an environment variable for the default, restoring control over whether state changes appear in the log stream.

@jesserockz added two light improvements:

  • light.effect.next and light.effect.previous actions (#16491) cycle through a light's configured effects without having to hardcode effect names. An include_none: true option lets the cycle pass through the un-effected state. The target light must have at least one effect, checked at config validation time.
  • Lambda light effects receive the light as it (#16815) - matches the existing behavior of addressable lambda effects, so simple lambdas can reference the light directly without id(my_light).

@clydebarrow also added a rounded property to LVGL meter arcs (#16669).

  • Display metadata for LVGL validation (#16702) - display drivers now register byte_order, rotation, draw_rounding, has_writer, and has_hardware_rotation metadata, so LVGL can pick byte_order automatically, reject mixed byte orders, and merge draw_rounding requirements from the attached display.
  • Mitsubishi CN105 swing modes (#15653 by @crnjan) - vertical / horizontal / both swing for the Mitsubishi CN105 climate component, with last non-swing vane positions tracked and restored when swing is disabled.
  • SDL display screen selection (#16363 by @clydebarrow) - the host-platform SDL display can now be centered on a specific display when multiple are attached.
  • homeassistant.time honors explicit timezones (#16583 by @clydebarrow) - a timezone: configured locally is no longer silently overridden by Home Assistant's zone.
  • I2C host platform support (#14489 by @jesserockz) - basic I2C bus support when running ESPHome on a Linux host platform, useful for testing and host-side integrations.
  • Nextion device info storage rewrite (#16059 by @edwardtfn) - the connect_info parser was replaced with fixed-size field extraction, eliminating all heap allocations from the comok response. Device info is now always logged in dump_config(); the old dump_device_info YAML option is gone.

This release includes 178 pull requests from over 20 contributors. A huge thank you to everyone who made 2026.6.0 possible:

  • @swoboda1337 - 57 PRs including the ESP-IDF 6 / native RISC-V clang-tidy infrastructure, the ESP8266 WPA2 default flip, removal of long-deprecated core APIs, and extensive ESP32 platform plumbing
  • @kahrendt - 19 PRs including the audio stack modernization (RingBufferAudioSource rollout, any-bit-depth mixer, resampler pass-through, new router speaker) and the W5500 ethernet SPI offload
  • @clydebarrow - 16 PRs including the new motion IMU hub with BMI270 and LSM6DS drivers, LVGL display-metadata validation, and the Home Assistant timezone fix
  • @jesserockz - 9 PRs including YAML frontmatter support, light.effect.next / light.effect.previous actions, the RP2040/RP2350 variant option, esphome config --no-defaults, and 100% patch-coverage enforcement
  • @kbx81 - 4 PRs including the WiFi and ethernet lazy-init RAM reclamation work
  • @p1ngb4ck - 2 PRs adding the FTDI FT23XX and Prolific PL2303 USB-serial drivers
  • @PolarGoose - 2 PRs on DSMR including EON Hungary meter support and the dsmr_parser library update
  • @tomaszduda23 - 2 PRs on the nRF52 native build and network IPv6 enforcement
  • @rtyle - 2 PRs fixing QMP6988 sensor I2C error handling
  • @Tomer27cz - the DLMS meter component overhaul using the external dlms_parser library
  • @Ardumine - Zephyr IPv6 networking support for nRF52
  • @remcom - the new PCM5122 audio DAC component
  • @RT530 - the new XDB401 pressure sensor component
  • @crnjan - swing support for the Mitsubishi CN105 climate component
  • @edwardtfn - the Nextion connect_info heap-allocation rewrite

Also thank you to @bdraco, @Rapsssito, @burundiocibu, @leodrivera, @SoCuul, @david-collett, @chemelli74, @Eelviny, @gnumpi, @GuzTech, @rwrozelle, @exciton, @i-am-no-magic, and @kpfleming for their contributions, and to everyone who reported issues, tested pre-releases, and helped in the community.

  • WiFi (ESP8266): Default min_auth_mode flipped from WPA to WPA2, matching the ESP32 default. The 2026.1 deprecation warning has been calling this out at every config validation. Devices on legacy WPA-only (TKIP) routers must pin min_auth_mode: WPA explicitly under wifi: #16682
  • DSMR: electricity_switch_position moved from sensor: to text_sensor: because Hungarian meters emit it as a string (e.g. ON) rather than a number. Update existing configs to declare the entity under text_sensor: #16561
  • DLMS Meter: Refactored to use the external dlms_parser library, adding dynamic OBIS-code schema, binary sensor support, optional decryption keys, and a configurable UART baud rate (the 2400-baud requirement is gone). The legacy hardcoded property schema continues to work; the provider: option is now ignored with a deprecation warning and will be removed in 2026.11.0 #15458
  • Nextion: The dump_device_info YAML option has been removed. Device info is now always stored and logged in dump_config(). Remove dump_device_info: true from any display: Nextion configs #16059
  • Home Assistant Time: When a timezone: is explicitly configured on a time: component with platform: homeassistant, the zone reported by Home Assistant no longer overrides it. Configurations that relied on HA silently overriding a stale local timezone should remove the local timezone: entry #16583
  • custom_components/ folder removed: The deprecated custom_components/ directory auto-loader has been removed. Use external_components instead. The deprecation warning has been printing since 2025.6 #16679
  • Sensitive value redaction: cv.sensitive() now drives runtime redaction directly via a YAML representer instead of a post-dump regex. WiFi SSIDs are now marked sensitive and will be redacted alongside passwords in esphome config output. No YAML change needed; pass --show-secrets to bypass redaction as before #16690

Lambda users and external component authors who reference internal C++ types should note the following change. The type still behaves the same at runtime, but its name was updated to match the project's identifier-naming convention:

  • MIPI DSI display class renamed: mipi_dsi::MIPI_DSI is now mipi_dsi::MipiDsi. Any lambda or external component that referenced the old type name must use the new spelling. No behavior change #16837

    // Before
    auto *display = static_cast<mipi_dsi::MIPI_DSI *>(...);
    // After
    auto *display = static_cast<mipi_dsi::MipiDsi *>(...);
  • Component::mark_failed / status_set_error const char * overloads removed: use the const LogString * overloads via LOG_STR("...") #16680
  • cv.only_with_esp_idf and CORE.using_esp_idf removed: migrate to cv.only_on_esp32 and CORE.is_esp32; use CORE.using_toolchain_esp_idf for the rare actual toolchain check #16681
  • text_sensor::TextSensor::raw_state public member removed: use get_raw_state() instead #16683
  • nfc::format_uid(span) / nfc::format_bytes(span) heap helpers removed: switch to the stack-buffer variants nfc::format_uid_to(buf, span) / nfc::format_bytes_to(buf, span) with FORMAT_UID_BUFFER_SIZE / FORMAT_BYTES_BUFFER_SIZE #16684
  • seq<> and gens<> tuple-unpack templates removed from core/automation.h: use std::index_sequence / std::index_sequence_for #16685
  • audio::scale_audio_samples deprecated: switch to esp_audio_libs::gain::apply from the bundled esp-audio-libs (Q31 scale factor, byte buffers, explicit bytes_per_sample). Scheduled for removal in 2026.12.0 #16831
  • cv.sensitive() schema marker: external component schemas should now wrap sensitive fields with cv.sensitive(...) for redaction in esphome config output. The old regex-based fallback stays as a deprecation bridge through 2026.12.0 #16690

For detailed migration guides and API documentation, see the ESPHome Developers Documentation.

  • [router] Add a router speaker component to runtime choose output speaker esphome#16592 by @kahrendt (new-component) (new-feature) (new-platform)
  • [motion] Implement hub component for IMUs esphome#16226 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [pcm5122] Add PCM5122 audio DAC component esphome#15709 by @remcom (new-component) (new-feature) (new-platform)
  • [xdb401] XDB401 Pressure Sensor esphome#15108 by @RT530 (new-component) (new-feature) (new-platform)
  • [bmi270] Support Bosch BMI270 IMU esphome#16202 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [lsm6ds] Add motion platform for STMicro LSM6DS IMU esphome#16232 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [router] Add a router speaker component to runtime choose output speaker esphome#16592 by @kahrendt (new-component) (new-feature) (new-platform)
  • [motion] Implement hub component for IMUs esphome#16226 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [pcm5122] Add PCM5122 audio DAC component esphome#15709 by @remcom (new-component) (new-feature) (new-platform)
  • [dlms_meter] dlms_parser library esphome#15458 by @Tomer27cz (new-feature) (breaking-change) (new-platform)
  • [xdb401] XDB401 Pressure Sensor esphome#15108 by @RT530 (new-component) (new-feature) (new-platform)
  • [bmi270] Support Bosch BMI270 IMU esphome#16202 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [lsm6ds] Add motion platform for STMicro LSM6DS IMU esphome#16232 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [nextion] Replace connect_info vector with fixed-size field parser, always log device info esphome#16059 by @edwardtfn (breaking-change)
  • [time][homeassistant] Fix timezone handling esphome#16583 by @clydebarrow (breaking-change)
  • [core] Remove deprecated custom_components folder loading esphome#16679 by @swoboda1337 (breaking-change)
  • [wifi] Default ESP8266 min_auth_mode to WPA2 esphome#16682 by @swoboda1337 (breaking-change)
  • [core] Sensitive redaction via yaml_util representer esphome#16690 by @bdraco (breaking-change)
  • [dmsr] [breaking] Fix decryption that uses custom auth key. Add CRC to telegram sensor. Automatic hex string detection in equipment_id fields. Support EON Hungary smart meters esphome#16561 by @PolarGoose (breaking-change)
  • [dlms_meter] dlms_parser library esphome#15458 by @Tomer27cz (new-feature) (breaking-change) (new-platform)