Skip to content

ESPHome 2026.7.0 - July 2026

NOTE

This is a beta release. Details on this page may change before the stable release is published.

ESPHome 2026.7.0 flips the default ESP32 toolchain to native ESP-IDF and lands the first coordinated wave of security infrastructure targeting EN18031 compliance: NVS encryption, OTA downgrade protection, and a new transport-agnostic provisioning component. Broad performance and memory work runs through the release, including a tree-wide single-precision float sweep across roughly 50 components, focused ESP8266 DRAM savings, ccache on by default for ESP-IDF, and shared machine-global toolchain caches.

On the feature side, the release brings a major Modbus overhaul with a rewritten parser and heap-free send path, substantial LVGL expansion (animations, dynamic rotation, boot pausing), gigabit Ethernet on the new ESP32-S31, ESP-NOW v2 payloads, RTC-backed preferences on ESP32, 11 new components covering touch controllers, e-paper panels, IMUs, and the Divoom Pixoo 64, and Zigbee endpoint merging on the new 2.0.2 SDK. The legacy Tornado web dashboard is retired in favor of the external Device Builder, and Python 3.11 support is dropped.

  • If you have an ESP32 config without an explicit toolchain: setting, it now compiles with native ESP-IDF; add toolchain: platformio to keep the previous behavior
  • If you install ESPHome with pip on Python 3.11, upgrade to Python 3.12 or newer
  • If you install ESPHome with pip and use the built-in esphome dashboard command, install and run esphome-device-builder instead
  • If you have Zigbee devices, you must re-join, re-interview, and re-configure each device after upgrading
  • If you set enabled or coordinator under Zigbee reporting:, remove those keys
  • If you use web_server: version: 1, plan to migrate to v2 or v3 before 2027.1.0
  • If you address web_server URLs by object ID, switch to the entity name
  • If you use packages: !include mypackage.yaml, wrap the include in a list: packages: [!include mypackage.yaml]
  • If you use FOUR_SCAN_16PX_HIGH, FOUR_SCAN_32PX_HIGH, or FOUR_SCAN_64PX_HIGH for hub75 scan_wiring, rename to SCAN_1_4_16PX_HIGH, SCAN_1_8_32PX_HIGH, or SCAN_1_8_64PX_HIGH
  • If you set disable_crc under modbus:, remove it
  • If you set send_wait_time or turnaround_time on a modbus: server, remove those keys
  • If you rely on modbus client timing, note that defaults changed to send_wait_time: 2000ms and turnaround_time: 600ms
  • If you use the generic-ln882hki board, switch to generic-ln882h or generic-ln882h-tuya depending on factory firmware
  • If you use the LN882H wb02a board with D1, D7, D8, D9, or default I2C pin aliases, update your pin numbers to match the new mapping
  • If you have lambdas or automations that set light brightness to 0, note that the value is now preserved instead of being clamped to 1.0
  • If two Home Assistant instances share the same bluetooth_proxy, the newest subscriber now wins instead of the oldest
  • If you build for nRF52 boards without a DCDC regulator, DCDC settings are no longer forced and generated code changes slightly
  • If your lambdas call value_accuracy_to_string() or MideaData::to_string(), migrate to the buffer variants (value_accuracy_to_buf() and to_str(buffer))

ESP-IDF Is Now the Default ESP32 Toolchain

Section titled “ESP-IDF Is Now the Default ESP32 Toolchain”

The default toolchain for the esp32 platform switches from PlatformIO to native ESP-IDF (#16910). Configurations that do not set an explicit toolchain: option will be compiled with ESP-IDF from this release forward. The framework migration notice that had been shown since 2026.1.0 has also been removed now that the default has landed (#17023).

ESP-IDF continues to be the recommended framework for new projects and for any device where memory is tight, particularly Bluetooth proxies and devices with the web server enabled. Configurations that explicitly select PlatformIO with toolchain: platformio continue to build with Arduino as they did before, but new configurations generated by the wizard or from packages will pick up the native ESP-IDF toolchain automatically.

Security and Provisioning Groundwork for EN18031

Section titled “Security and Provisioning Groundwork for EN18031”

This release lands three coordinated pieces of security infrastructure, led by @kbx81, that together move ESPHome toward EN18031 compliance for network-connected consumer devices.

NVS Encryption on ESP32 (#17004)

Opt-in encryption for Non-Volatile Storage using the HMAC peripheral. Keys are derived at runtime from an HMAC key in a user-selected eFuse block, so flash encryption is not required. Supported on the ESP32 variants that ship the HMAC peripheral: S2, S3, C3, C5, C6, H2, and P4. Burning the HMAC key to an eFuse block is a permanent, irreversible operation, so users should read the esp32 documentation carefully before enabling this.

OTA Downgrade Protection (#17315)

Software anti-rollback for signed ESP-IDF OTAs. The version baked into the staged image (from project: version:) is compared against the running version before the boot partition is switched. Covers all OTA sources: native, http_request.ota, and web_server. Requires a signed OTA to be effective.

Provisioning Component (#17152)

A new transport-agnostic provisioning component that manages a provisioning window for devices shipping unprovisioned. Sources such as api and esp32_improv register with the component, and the window is closed on timeout, at which point any provisioning-related API clients are disconnected with DISCONNECT_REASON_PROVISIONING_CLOSED.

Led by @swoboda1337, a tree-wide sweep replaces silent double-promotion patterns with single-precision equivalents across roughly 50 components (#17252, #17253, #17254, #17255, #17256, #17260).

The issue was invisible on ESP32 because ESP-IDF does not enable -Wdouble-promotion: literals like 2.0 and functions like fmod, round, and fabs were quietly promoting single-precision values to double, running the result through the soft-double library on chips without hardware doubles, then narrowing back to float.

Measured Impact:

  • hsv_to_rgb code size: 108 bytes → 69 bytes (-36%) on ESP32
  • Soft-double helper calls eliminated: roughly 8 per call site
  • Components touched: displays, lights, climate, most sensor drivers, openthread, mqtt, speaker, graph, and many more

The final straggler pass (#17260) also rewrites hot expressions such as std::pow(2, sf) in sx126x to a constexpr bit shift, and switches a few call sites to std::numbers::pi_v<float>.

Every byte of RAM matters on ESP8266, and three focused changes by @bdraco reclaim a useful chunk of DRAM without changing runtime behavior.

  • libstdc++ throw message strings (#17341) — Overrides std::__throw_* helpers so the never-read message arguments are dropped. Saves roughly 96 bytes of RAM on a ratgdo build. Crash behavior is unchanged.
  • lwIP glue DHCP stub strings (#17395) — Silent equivalents for dhcp_cleanup() and dhcp_release() stubs. Frees 48 bytes of RAM and 88 bytes of flash, and removes the noisy STUB: dhcp_cleanup log on every WiFi disconnect.
  • dashboard_import package URL (#17127) — Moves the mDNS TXT package_import_url string from .rodata (DRAM) to flash. It was the last mDNS TXT value pinned in RAM.

Build System: ccache and Shared Toolchain Caches

Section titled “Build System: ccache and Shared Toolchain Caches”

Led by @swoboda1337, the ESP-IDF and nRF SDK toolchains gain both compiler-level caching and installation-level sharing.

ccache is now on by default for ESP-IDF builds (#17163, #17136) when the ccache binary is present, using depend mode (depfile hashing instead of preprocessing) and a cache directory under the IDF tools path. Opt out with IDF_CCACHE_ENABLE=0. On the 23-batch CI matrix, summed runner time dropped from 543 to 504 minutes (~7%) and wall time from 154 to 139 minutes.

Toolchains now install into a machine-global cache directory (#17306, #17353). ESP-IDF installs to ~/.cache/esphome/idf and the nRF Connect SDK installs to ~/.cache/esphome/sdk-nrf, so multi-gigabyte toolchain installs are shared across every project on the machine instead of being duplicated per config. Docker and Home Assistant add-on users pin these to persistent volumes, and existing installs re-download once after upgrade.

Config validation got faster too, thanks to import deferral by @frenck: aioesphomeapi.posix_tz deferral cuts esphome config median wall time by roughly 33% on a host config from 445 ms to 297 ms (#17214), and deferring requests imports shaves another ~70 ms (~16%) (#17215).

A new core mechanism (#16826) lets components be renamed without breaking existing YAML configurations. Components declare ALIASES = [...] (and an optional ALIAS_REMOVAL_VERSION), and a pre-pass in config validation rewrites legacy keys while a sys.meta_path finder resolves Python imports for esphome.components.<oldname>. Aliases are discovered by an AST scan so components do not need to be imported to enumerate them.

The first user of the new infrastructure is the rp2 rename (#17145) by @jesserockz, which renames the rp2040 platform to rp2 to reflect its coverage of both RP2040 and RP2350. The legacy rp2040: YAML key and esphome.components.rp2040 imports continue to work as deprecated aliases and will be removed in 2027.7.0. New rp2_2040 and rp2_2350 variant kwargs are added to SplitDefault and require_framework_version, mirroring the ESP32 pattern.

@exciton landed a major rework of the modbus component across multiple PRs.

Client and server split (#11969) — Modbus is split into ModbusClientHub and ModbusServerHub, retiring the role enum entirely. Client components move to ModbusClientDevice (#11987) and the API is finalized before the release (#17434, #17378). External components need to update against the new API.

Rewritten parser — Byte-by-byte parsing is replaced with a buffer-based, frame-length-aware parser that handles peer server responses, unsupported function codes, and custom function codes correctly. Response tracking uses std::optional<ModbusDeviceCommand>, enabling address+function-code matching, multiple devices per address, and two new callbacks: on_modbus_no_response() and on_modbus_not_sent().

Heap-free send path — A new SmallInlineBuffer<8> and StaticVector<uint8_t, MAX_PDU_SIZE> mean that 8-byte Modbus frames (the common case for reads and single-register writes) live inline in the deque node with zero per-frame heap activity (#17282).

Server improvements (#17205) — Multi-register values now match by full span, a new allow_partial_read option is available, overlapping registers are rejected, and the obsolete RAW value type has been removed from server mode.

Default send_wait_time moves from 250ms to 2000ms and turnaround_time from 100ms to 600ms. If you were overriding these to compensate for the old parser, review whether the overrides are still needed.

LVGL: Animations, Rotation, and Runtime Updates

Section titled “LVGL: Animations, Rotation, and Runtime Updates”

@clydebarrow drove a substantial expansion of the lvgl component this release.

  • Animations (#16796) — Full LVGL animation support with from/to interpolation, timing functions (gravity and friends), duration, looping, and auto_start.
  • Dynamic rotation (#16773) — Templated lvgl.display.set_rotation in degrees, new on_landscape and on_portrait triggers, and layout option updates in lvgl.update.
  • Direct mapping syntax (#15863) — Cleaner LVGL text and image src updates using a mapping directly.
  • Boot pausing (#16973) — A new paused config option suppresses LVGL updates on boot. Especially useful for e-paper displays that should not render invalid state before the API connects.
  • Continued activity while display busy (#17374) — When update_when_display_idle is used (typical for e-paper), LVGL now still processes user input and runs timers while the display refresh is in progress. The LVGL refresh interval, previously fixed at 16 ms, is now configurable.

Gigabit Ethernet on ESP32-S31 (#17277) — Adds type: GENERIC and type: YT8531 PHYs for the new RGMII-capable ESP32-S31 variant, which requires ESP-IDF 6.1. The YT8531 handler covers auto-negotiation re-enable and RGMII Tx/Rx delays. New power_pin and phy_registers options are available on the ethernet component.

ESP-NOW v2 payloads (#17360) — The espnow component gains a max_payload_size option that accepts frames up to 1470 bytes (previously capped at 250). The default stays at 250; going to 1470 costs roughly 44 KB of RAM versus about 8 KB at the default. Requires ESP-IDF ≥ 5.4 or Arduino ≥ 3.2.

LN882X MQTT support (#17297) — LN882H boards can finally use the mqtt component. LN882X was previously blocked despite sharing the LibreTiny backend.

Data whitening for SX126x (#17102) — Configurable FSK data whitening (CCITT algorithm) via new whitening_enable and whitening_initial options.

Bluetooth proxy subscriber semantics (#17423) — A later subscriber now takes over the single subscriber slot from a stale one instead of being silently rejected. This fixes the “connected but no advertisements” state that could occur after a Home Assistant restart within the ~150 second keepalive window. Users don’t need to change configs, but the observed behavior does change.

OpenThread on Zephyr/nRF52 and MTD Polling Control

Section titled “OpenThread on Zephyr/nRF52 and MTD Polling Control”

Basic Zephyr/nRF52 support (#16854) — First-cut openthread support on the nRF52 Zephyr platform, by @Ardumine. Handles the “join network” flow.

Runtime poll period control (#11766) — A new set_poll_period action lets a Minimal Thread Device (Sleepy End Device) temporarily switch to radio-always-on for OTA. http_request.ota becomes roughly 10x faster on MTDs, and esphome.ota starts working at all.

@bootc taught the ESP32 preferences backend to honor the in_flash=false flag of make_preference() (#17073), adding RTC-memory-backed preferences in the same way ESP8266 already had them. The shared word-buffer plus checksum format is extracted into preferences_rtc.h.

New configuration surface:

  • safe_mode: storage: rtc or flash
  • wifi: fast_connect: dict form with enabled and storage sub-options
  • preferences: rtc_storage: true

The ESP32-C2 and ESP32-C61 have no RTC RAM and fall back gracefully. This is groundwork for a planned DHCP-lease cache and was validated across ESP32 PICO, S3, C3, and C6 hardware.

New Displays, Touch Controllers, and Peripherals

Section titled “New Displays, Touch Controllers, and Peripherals”

The release adds broad support for new display and touch hardware, largely on M5Stack, Waveshare, and Seeed reTerminal families.

Touch controllerscst328 by @latonita (#8011), st7123 integrated display-touch driver for the M5Stack Tab5 by @miniskipper (#12075), gsl3670 for Seeed reTerminal D1001 by @clydebarrow (#16285), and cst9220 covering CST9220 and CST9217 by @clydebarrow (#16888).

E-paper displays — The epaper_spi component picks up several new panels: Waveshare 7.5” V2 BWR 800×480 by @twisterss (#15719), Seeed reTerminal E1004 13.3” 6-color (T133A01, dual-CS SPI) by @limengdu (#16706), Waveshare 2.13” V4 BWR (SSD1683) by @profplump (#16828), Soldered Inkplate 2 by @arunderwood (#16856), and Seeed reTerminal-sticky by @clydebarrow (#16950). The it8951 e-paper controller for M5Paper and Seeed reTerminal E1003/EE03 (up to 1872×1404, 16-level grayscale) arrives as a new component by @Passific (#15346).

MIPI-SPI displays — M5STACK ATOM3SR by @clydebarrow (#17344) and the Waveshare ESP32-S3-Touch-AMOLED-1.64 (SH8601) by @crimike (#17386).

Divoom Pixoo 64 — A new pixoo component by @jesserockz (#16974) drives the 64×64 RGB LED matrix over SPI and exposes a light platform for panel brightness alongside the image API.

Sensors and peripherals — A ufm01 ScioSense UFM-01 ultrasonic flow meter by @ljungqvist (#16582) reports accumulated flow, flow rate, water temperature, and four diagnostic binary sensors over UART. A qmi8658 6-axis IMU by @clydebarrow (#16889) adds accelerometer, gyroscope, and on-chip temperature sensing with a motion platform. The waveshare_io_ch32v003 I/O expander by @latonita (#10071) covers the CH32V003-based expander shipped on Waveshare’s newer S3 boards, providing EXIO GPIO, PWM backlight control, an ADC battery voltage sensor, and RTC interrupt status.

Audio — The pcm5122 component grows analog gain (0/-6 dB), channel mixing (stereo/left/right/swapped), configurable volume range, a standby/powerdown switch, and an XSMT enable pin, along with a fix for a clock register page bug that had been silently corrupting clock setup (#17313) by @remcom. The i2s_audio speaker now accepts wider streams (e.g. 24-bit into a 16-bit device) and narrows them in place using esp-audio-libs’ pcm_convert::copy_frames (#16821).

@jesserockz restructured image: into a platform component (#17416). The new form uses platform: file, platform: animation, and platform: online_image, with animation becoming a proper sub-component of the new file platform. The legacy top-level image:, animation:, and online_image: keys continue to work through 2027.1.0 with copy-paste migration warnings shown at validation time.

@luar123 bumped the zigbee component to the new Zigbee SDK 2.0.2 for better ESP-IDF compatibility and picked up ESP32-H4, H21, and S31 variants (compile-only for now) (#16869). The dedicated Zigbee storage partition has been retired in favor of the default NVS, and reporting configuration is simplified: the enabled/coordinator distinction is gone.

A follow-up (#17402) merges endpoints of components on ESP32 and lets users manually combine them. This enables single-endpoint devices with multiple sensors, matching Zigbee standard expectations. Both PRs require existing Zigbee devices to be re-joined, re-interviewed, and reconfigured after upgrading.

@clydebarrow added a warning when a YAML merge (<<:) silently drops a key (#17246). Two top-level api: blocks combined via <<: would previously drop one without any indication; ESPHome now prints the source location, explains that a merge is happening, and suggests packages: for a deep merge instead. Toggle with esphome: merge_warnings: false.

  • Legacy web dashboard removed (#17124) — The built-in Tornado-based dashboard is gone in favor of the external ESPHome Device Builder. The dashboard CLI command remains but is hidden and prints a migration hint. Docker and Home Assistant add-on users are unaffected: they already route to Device Builder.
  • Python 3.11 support dropped (#17280) — Minimum Python version is now 3.12. Home Assistant add-on and Docker images are already on 3.12.
  • PSRAM for ESP32-S31 and H4 (#17192) — Both new variants gain PSRAM wiring: S31 octal at 40/100/200/250 MHz and H4 quad at 32/64 MHz. Values come from the esp_psram Kconfig on ESP-IDF release/v6.1, and octal-mode validation is now data-driven rather than hardcoded to S3.
  • Host platform preferences directory (#11160) — A new ESPHOME_PREFDIR environment variable overrides where the host platform stores preferences, useful when running ESPHome as a system service where HOME may not be set.
  • Web server SSE optimization (#17400) — Logger’s known message length is now threaded through the SSE send path, avoiding strlen and strchr rescans on every log event. No wire changes.
  • WiFi roaming scan suppression (#17012) — A new internal API lets components request that post-connect roaming scans be paused. First user is sendspin, which now suppresses roaming scans while playing to prevent audible hiccups (#17133).
  • Runtime UART reconfiguration (#16990) — Baud rate, parity, and other UART settings can now be changed at runtime on open channels without reconnecting. Landed for both the standard uart and usb_uart components.
  • Light brightness on turn-off preservation (#17103) — Setting brightness to 0 no longer silently clamps to 1.0. If a subsequent turn-on has no explicit brightness and the current brightness is 0, brightness is set to 1.0 at turn-on time instead.
  • coex/sdkconfig reconciler (#17008) — A single reconciler now handles WiFi/Ethernet/BLE coexistence sdkconfig flags on ESP32, killing conflicting values (for example ethernet versus esp32_ble_tracker on CONFIG_SW_COEXIST_ENABLE). Behavior is preserved and internal helpers gain semantic names such as request_wifi, request_ethernet, and request_software_coexistence.
  • Visual editor visibility hints (#17449) — Build-system and framework internals are now marked with cv.Visibility so the Device Builder visual editor can hide them from users who edit YAML from the browser.

This release includes 217 pull requests from over 30 contributors. A huge thank you to everyone who made 2026.7.0 possible:

  • @swoboda1337 - 45 PRs including making ESP-IDF the default esp32 toolchain, the tree-wide single-precision float math sweep, wiring up ESP32-S31/H4/H21 support, ccache and shared toolchain caches, gigabit ethernet, ESP-NOW v2 payloads, and dropping Python 3.11
  • @jesserockz - 45 PRs including the generic component alias infrastructure, the final class sweep across 21 batches, the [pixoo] Divoom Pixoo display component, the [rp2] platform rename, the [image] platform restructure, and removing the legacy web dashboard
  • @clydebarrow - 17 PRs including LVGL animations, dynamic rotation, boot pausing and continued-activity-while-display-busy, the new [gsl3670] and [cst9220] touchscreens, the [qmi8658] IMU motion platform, the [mipi_spi] M5STACK ATOM3SR, YAML merge-drop warnings, and preserving light brightness on turn-off
  • @exciton - 9 PRs including the major [modbus] parser rewrite and client/server hub split, heap-free send path, register-range fixes with partial reads, and the finalized API surface
  • @tomaszduda23 - 8 PRs building out native nRF52 builds: native SDK support, upload flow, config-input rebuild triggers, non-nRF52840 board support, libc selection, and OTA error reporting
  • @kahrendt - 6 PRs including WiFi roaming-scan suppression, the [sendspin] playback integration, [i2s_audio] stream narrowing, and microMP3 bumps
  • @Ardumine - 5 PRs extending nRF52/Zephyr networking: BSD socket support, basic OpenThread, mDNS, [api] support, and enlarged Zephyr net buffers
  • @kbx81 - 4 PRs including ESP32 NVS encryption, OTA downgrade protection, the new [provisioning] component, and the ESP32 network/coexistence sdkconfig reconciler
  • @p1ngb4ck - 4 PRs including [usb_uart] per-device baud caps, FTDI RX stability fixes, and a vector pop_back helper
  • @luar123 - 3 PRs including the [zigbee] SDK 2.0.2 bump and endpoint merging on esp32
  • @frenck - 3 PRs deferring aioesphomeapi and requests imports to speed up config validation, and refining ESP32-S3 PSRAM pin warnings
  • @latonita - 2 PRs including the new [cst328] touchscreen and the [waveshare_io_ch32v003] I/O expander
  • @rwrozelle - 2 PRs including the [openthread] set_poll_period action for MTDs and a [socket] wake-request gate fix
  • @anunayk - 2 PRs including Zephyr GPIO interrupts and [ble_nus] atomic log framing
  • @remcom - 2 PRs including the [pcm5122] analog gain, channel mixing, and standby/powerdown work, plus [audio_file] MP3 detection fixes
  • @miniskipper - the new [st7123] touch controller component for the M5Stack Tab5
  • @Passific - the new [it8951] e-paper controller component
  • @ljungqvist - the new [ufm01] ultrasonic flow meter component
  • @bootc - RTC-backed preferences on ESP32, honoring the in_flash flag

Also thank you to @bdraco, @haku, @Eelviny, @twisterss, @ddrown, @limengdu, @profplump, @arunderwood, @kyvaith, @jspiros, @guillempages, @zeroflow, @mikelawrence, @jclehner, @berikv, @Bl00d-B0b, and @crimike for their contributions, and to everyone who reported issues, tested pre-releases, and helped in the community.

  • ESP32: ESP-IDF is now the default toolchain when no explicit toolchain: is set. Add toolchain: platformio to your esp32: block to keep building with PlatformIO #16910
  • Python: Minimum supported Python bumped to 3.12. Home Assistant add-on and Docker are unaffected; only direct pip installs on 3.11 need to upgrade #17280
  • nRF52: The Zephyr DCDC settings are no longer forced by ESPHome, which slightly changes generated code depending on board settings and allows building for boards without DCDC #17373
  • Legacy Dashboard: The built-in Tornado web dashboard has been removed. Users installing via pip should install and run esphome-device-builder instead. Docker and Home Assistant add-on users are unaffected #17124
  • Bluetooth Proxy: The newest advertisement subscriber now takes over the single subscriber slot from a stale one instead of being rejected. Fixes “connected but no advertisements” after a Home Assistant restart within the ~150 second keepalive window #17423
  • Hub75: The deprecated scan_wiring names FOUR_SCAN_16PX_HIGH, FOUR_SCAN_32PX_HIGH, and FOUR_SCAN_64PX_HIGH have been removed. Use SCAN_1_4_16PX_HIGH, SCAN_1_8_32PX_HIGH, and SCAN_1_8_64PX_HIGH instead #17118
  • Light: Setting brightness to 0 no longer silently clamps to 1.0. If a subsequent turn-on has no explicit brightness and the current brightness is 0, brightness is restored to 1.0 at turn-on time instead #17103
  • LibreTiny (LN882H): generic-ln882hki board removed; use generic-ln882h or generic-ln882h-tuya depending on factory firmware. Default LN882H log UART is now UART1. LN882H partition layouts changed (on-device OTA migration handled by LibreTiny). On the wb02a board, pin aliases shifted (D1 → GPIO6, D7 → GPIO5, D8 → GPIO9, D9 → GPIO24, new D10 → GPIO25) and default I2C pin order changed #17288
  • Modbus: The disable_crc option has been removed, along with send_wait_time and turnaround_time from server mode. Client-mode defaults were raised: send_wait_time 250ms → 2000ms, turnaround_time 100ms → 600ms #11969
  • Packages: The single-package !include form is removed. Wrap the include in a list: packages: [!include mypackage.yaml] #17119
  • Web Server: The deprecated object ID URL matching fallback has been removed. URLs are matched by entity name only #17113
  • Web Server: Version 1 is deprecated. A configuration warning is emitted when version: 1 is set; removal is targeted for 2027.1.0. Migrate to v2 (the default) or v3 #17109
  • Zigbee: The Zigbee SDK bump to 2.0.2 changes the storage layout, so devices must be re-joined and reconfigured after upgrading. The reporting: config values enabled and coordinator are no longer valid #16869
  • Zigbee: Endpoint merging now combines endpoints of components by default and lets users manually combine them. Existing configurations require re-joining, re-interviewing, and re-configuring #17402

Users with lambdas that call internal string-formatting helpers should note the following removals. Both methods were deprecated 6 months ago in favor of buffer-based variants that avoid std::string allocation.

  • Core: value_accuracy_to_string() has been removed. Use value_accuracy_to_buf(), which writes into a caller-provided buffer. #17116

    Before:

    std::string s = value_accuracy_to_string(value, accuracy);

    After:

    char buf[32];
    value_accuracy_to_buf(buf, sizeof(buf), value, accuracy);
  • Remote Base (Midea): MideaData::to_string() has been removed. Use to_str(buffer) instead, which formats into a caller-provided buffer. #17117

    Before:

    std::string s = data.to_string();

    After:

    char buf[32];
    data.to_str(buf);
  • Dashboard Import (ESP8266): package_import_url is now stored as a PROGMEM flash literal (ProgmemStr) rather than a plain const char * in DRAM. Existing consumers already read it as a flash pointer (mDNS via MDNS_STR_ARG, MQTT via ArduinoJson’s __FlashStringHelper overload), so this is a transparent change on ESP8266 and a no-op on other platforms. Lambdas that read package_import_url on ESP8266 should not dereference it as a plain const char *. #17127

  • Modbus API split: Modbus is split into ModbusClientHub and ModbusServerHub; ModbusDevice::set_parent() now takes ModbusClientHub *; Modbus::register_device() removed (#11969, #11987, #12376)
  • Modbus API naming: Public API surface renamed and finalized before release (#17378, #17434)
  • Modbus function code comparisons: Ordering operators (<, <=, >, >=) between ModbusFunctionCode and uint8_t removed. Cast explicitly or use helpers::is_function_code_*() #11969
  • Select state member removed: Use current_option() or active_index() instead #17027
  • Scheduler std::string overloads removed: App.scheduler.set_timeout(std::string, ...) and related std::string-name overloads are gone; pass const char * names #17111
  • get_object_id() and get_compilation_time() removed: Previously deprecated core helpers deleted #17112
  • GPIOPin::dump_summary() returning std::string removed: Overrides must return via the buffer form #17115
  • UART load_settings(bool) is now pure virtual: All UARTComponent subclasses must implement runtime settings updates #16990
  • API pre-1.14 object_id backward-compat removed: Old client fallback path deleted #17108
  • Preferences RTC helpers moved: Word-buffer + checksum format extracted to preferences_rtc.h and shared between ESP32/ESP8266 #17073
  • Network use_address logging changes: Runtime MAC-suffix expansion moved into the network component #17432
  • Configurable classes marked final: Roughly 20 batches of components add final to their runtime-instantiated concrete classes to allow devirtualization (#16952-#16972, #17129, #17130, #17147)
  • rp2040 component renamed to rp2: Python imports esphome.components.rp2040 and the rp2040: YAML key continue to work as deprecated aliases through 2027.7.0 via the new alias infrastructure (#17145, #16826)

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

  • [ufm01] Add UFM-01 ultrasonic flow meter component esphome#16582 by @ljungqvist (new-component) (new-feature) (new-platform)
  • [waveshare_io_ch32v003] Waveshare I/O Expander component esphome#10071 by @latonita (new-component) (new-feature) (new-platform)
  • [it8951] Add IT8951 e-paper controller support to epaper_spi esphome#15346 by @Passific (new-component) (new-feature) (new-platform)
  • [qmi8658] Motion platform for QMI8658 IMU esphome#16889 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [cst9220] Add CST9220 and CST9217 touchscreen support esphome#16888 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [pixoo] Add Divoom Pixoo display component esphome#16974 by @jesserockz (new-component) (new-feature) (new-platform)
  • [st7123] add ST7123 touch controller component (M5Stack Tab5) esphome#12075 by @miniskipper (new-component) (new-feature) (new-platform)
  • [cst328] Touch screen (Waveshare ESP32-S3-Touch-LCD-2.8) esphome#8011 by @latonita (new-component) (new-feature) (new-platform)
  • [provisioning] Add provisioning window esphome#17152 by @kbx81 (new-component) (new-feature)
  • [image] Restructure into a platform component esphome#17416 by @jesserockz (new-component) (new-feature)
  • [gsl3670] Add new touchscreen component esphome#16285 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [ufm01] Add UFM-01 ultrasonic flow meter component esphome#16582 by @ljungqvist (new-component) (new-feature) (new-platform)
  • [waveshare_io_ch32v003] Waveshare I/O Expander component esphome#10071 by @latonita (new-component) (new-feature) (new-platform)
  • [it8951] Add IT8951 e-paper controller support to epaper_spi esphome#15346 by @Passific (new-component) (new-feature) (new-platform)
  • [qmi8658] Motion platform for QMI8658 IMU esphome#16889 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [cst9220] Add CST9220 and CST9217 touchscreen support esphome#16888 by @clydebarrow (new-component) (new-feature) (new-platform)
  • [pixoo] Add Divoom Pixoo display component esphome#16974 by @jesserockz (new-component) (new-feature) (new-platform)
  • [st7123] add ST7123 touch controller component (M5Stack Tab5) esphome#12075 by @miniskipper (new-component) (new-feature) (new-platform)
  • [cst328] Touch screen (Waveshare ESP32-S3-Touch-LCD-2.8) esphome#8011 by @latonita (new-component) (new-feature) (new-platform)
  • [pcm5122] Add analog gain, channel mixing, volume range, standby/powerdown switch, and XSMT enable pin support esphome#17313 by @remcom (new-feature) (new-platform)
  • [gsl3670] Add new touchscreen component esphome#16285 by @clydebarrow (new-component) (new-feature) (new-platform)