<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0"><channel><title>ESPHome - Smart Home Made Simple - Blog</title><description/><link>https://esphome.io/</link><language>en</language><atom:link rel="self" href="https://esphome.io/blog/rss.xml"/><atom:link rel="prev-archive" href="https://esphome.io/blog/rss/2026-08.xml"/><item><title>ESPHome 2026.9.0: Faster builds and encrypted OTA</title><link>https://esphome.io/blog/2026/09/16/esphome-2026-9/</link><guid isPermaLink="true">https://esphome.io/blog/2026/09/16/esphome-2026-9/</guid><description>ESPHome 2026.9.0 parallelizes PlatformIO installs, lays the groundwork for a native ESP8266 toolchain, adds Noise-encrypted OTA updates, and frees ESP8266 RAM.</description><pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;This is a beta release. Details on this page may change before the stable release is published.&lt;/p&gt;
&lt;/div&gt;


&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/d01/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/d01.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;D0​1​&lt;/div&gt;&lt;div&gt;Particulate&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/sfa40/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/sfa40.webp&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;SFA4​0​&lt;/div&gt;&lt;div&gt;Formaldehyde ​&amp;#x26;​ ​Temperature ​&amp;#x26;​ ​Humidity&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/ds1603l/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ds1603l.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;DS1​6​0​3​L&lt;/div&gt;&lt;div&gt;Acoustic ​distance&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/mk2pvrouter/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/mk2pvrouter.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Mk2​PVRouter&lt;/div&gt;&lt;div&gt;Surplus ​Energy ​Diverter&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/display/snapshot/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/file-image-outline.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Snapshot&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/climate/template/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/description.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Template ​Climate&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.9.0 focuses on foundational build system and platform work: the scaffolding for an ESP8266
native toolchain lands across five infrastructure PRs, PlatformIO installs are parallelized end to end (the
package phase drops from 36% of build time to 25% on CI benchmarks, and the docker image preinstall from
~100s to ~46s), and a sweep across 60 files pushes 211 conditional log string literals off ESP8266 RAM into
flash.&lt;/p&gt;
&lt;p&gt;Beyond the platform work, this release adds Noise (ChaCha20-Poly1305) encryption for OTA updates, brings
Improv provisioning to Ethernet-only boards, teaches WiFi provisioning to shut down the AP and captive portal
when the window closes, and rewrites IR transmission on Beken and Realtek chips to run from a hardware timer
interrupt instead of a busy-wait. The multi-release modbus overhaul continues with a heap-free write path, a
consolidated range-join option, and continuous polling. Six new components (ds1603l, d01, sfa40, mk2pvrouter,
snapshot, noise) and roughly a dozen feature additions to existing components round out the release. The bundled
Device Builder masks credentials in the YAML diff view, boots ESP32-C6 boards after a browser flash, and lets paired
build servers recover from an address change on their own.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;If you have a device with a custom MAC burned into the ESP32 eFuses and use Ethernet, Bluetooth, or 802.15.4,
expect a new MAC on those interfaces after upgrading; update DHCP reservations, ACLs and Bluetooth pairings&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;custom_command:&lt;/code&gt;, rename it to &lt;code dir=&quot;auto&quot;&gt;custom_pdu:&lt;/code&gt; and drop the leading device
address byte from the payload&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;register_count:&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;force_new_range:&lt;/code&gt;, migrate to &lt;code dir=&quot;auto&quot;&gt;reuse_previous_range:&lt;/code&gt; and
re-verify any FP32 packed as &lt;code dir=&quot;auto&quot;&gt;register_count: 1&lt;/code&gt; + &lt;code dir=&quot;auto&quot;&gt;response_size: 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;skip_updates:&lt;/code&gt; on a sensor, split the slow registers onto a second
&lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; with the same &lt;code dir=&quot;auto&quot;&gt;address:&lt;/code&gt; and a slower &lt;code dir=&quot;auto&quot;&gt;update_interval:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;switch&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; with a non-zero &lt;code dir=&quot;auto&quot;&gt;offset:&lt;/code&gt; on holding registers, re-verify the
target register (writes now land at &lt;code dir=&quot;auto&quot;&gt;address + offset/2&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;address + offset&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;If you have a &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;switch&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;write_lambda&lt;/code&gt; that inverts the returned bool to flip the displayed
state, publish the state explicitly or invert in the read &lt;code dir=&quot;auto&quot;&gt;lambda&lt;/code&gt; instead&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;homeassistant.event&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;variables:&lt;/code&gt; with lambda source, tag the value with &lt;code dir=&quot;auto&quot;&gt;!lambda&lt;/code&gt; to silence the new
deprecation warning&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;esp32_hosted&lt;/code&gt;, remove any pinned ESP-IDF version below 5.3 or bump the pin to 5.3 or newer&lt;/li&gt;
&lt;li&gt;If you use one of the affected UART components (&lt;code dir=&quot;auto&quot;&gt;cm1106&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;daly_bms&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;hrxl_maxsonar_wr&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;hydreon_rgxx&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;mhz19&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pylontech&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;teleinfo&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;vbus&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;wl_134&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;cse7761&lt;/code&gt;) with non-default UART settings, expect a
configuration error and adjust the UART bus to the component’s required baud rate and parity&lt;/li&gt;
&lt;li&gt;If you use API user-defined actions with long variable names or descriptions on ESP8266, keep each action’s total
name and metadata text under 384 bytes or split into smaller actions&lt;/li&gt;
&lt;li&gt;If you have lambdas calling &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;ModbusCommandItem&lt;/code&gt; factories or &lt;code dir=&quot;auto&quot;&gt;queue_command()&lt;/code&gt;, migrate to the
entity write helpers or &lt;code dir=&quot;auto&quot;&gt;modbus_client&lt;/code&gt; actions before the 2027.3.0 removal&lt;/li&gt;
&lt;/ul&gt;


&lt;div&gt;&lt;h2 id=&quot;esp8266-native-toolchain-foundation&quot;&gt;ESP8266 Native Toolchain Foundation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, this release lays the entire scaffolding for building ESP8266
firmware without PlatformIO. ESPHome now has a shared registry and download layer
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18570&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18570&lt;/a&gt;), a linker-script surgery module and per-board build
metadata ported from &lt;code dir=&quot;auto&quot;&gt;platform-espressif8266&lt;/code&gt; 4.2.1
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18555&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18555&lt;/a&gt;), a toolchain seam that validates a &lt;code dir=&quot;auto&quot;&gt;--toolchain&lt;/code&gt;
choice on every platform (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18556&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18556&lt;/a&gt;), a resumable, sha256-verified
installer for the Arduino ESP8266 core 3.1.2 and xtensa gcc 10.3
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18557&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18557&lt;/a&gt;), and a native library backend that resolves
&lt;code dir=&quot;auto&quot;&gt;cg.add_library()&lt;/code&gt; entries against the framework tree
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18558&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18558&lt;/a&gt;). The infrastructure is standalone in this release
(nothing user reachable calls it yet), but it is the plumbing an ESP8266 build without PlatformIO needs.
About 40% of ESPHome installs still run on ESP8266, so this is the setup work for a substantially faster
build path for those users.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;build-system-parallelization&quot;&gt;Build System Parallelization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The install phase of a PlatformIO build was serial from top to bottom, which showed up most sharply on
Raspberry Pi class hardware and inside the Home Assistant App. This release parallelizes it end to end.
&lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; added a shared batch download runner with one combined progress bar
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18662&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18662&lt;/a&gt;), a prefetch subprocess that resolves and downloads
PlatformIO packages in parallel into PlatformIO’s own cache
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18769&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18769&lt;/a&gt;), and a parallel-extraction install pass that drives
PlatformIO’s own &lt;code dir=&quot;auto&quot;&gt;_install&lt;/code&gt; with one worker per usable core
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18775&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18775&lt;/a&gt;). CI benchmarks on the esp8266-arduino leg show the
package phase drop from 17.1s to 10.3s (36% of the build to 25% of the build) and 296 serial progress frames
collapse to a single combined bar. The docker image build’s own PlatformIO library preinstall got the same
treatment (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18777&lt;/a&gt;), cutting a ~100s step to ~46s on every arch
leg, and the CI compile-test image now compresses with multithreaded zstd instead of gzip
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18812&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18812&lt;/a&gt;), taking another 40s off the pipeline. ESP-IDF native
builds also now cache the discovered component list inside the extracted framework directory
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18752&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18752&lt;/a&gt;), skipping a full CMake configure pass on every rebuild
after an sdkconfig change (~2.2s on desktop, several times more on SBCs).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp8266-ram-savings&quot;&gt;ESP8266 RAM Savings&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A concerted sweep across the codebase pushes conditional log string literals off ESP8266 RAM and into flash,
where the rest of the log format string already lives. &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; scanned every
&lt;code dir=&quot;auto&quot;&gt;ESP_LOG*&lt;/code&gt; call site and converted 211 bare literals across 113 lines in 60 files, wrapping each in
&lt;code dir=&quot;auto&quot;&gt;LOG_STR_LITERAL&lt;/code&gt; so ESP8266 keeps them in flash while other platforms see a no-op
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18907&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18907&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18906&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18906&lt;/a&gt;). A d1_mini with &lt;code dir=&quot;auto&quot;&gt;dht&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;adc&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;resistance&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;wifi&lt;/code&gt; and
&lt;code dir=&quot;auto&quot;&gt;wireguard&lt;/code&gt; drops 80 bytes of RAM from this alone. In the same vein, &lt;code dir=&quot;auto&quot;&gt;str_contains_ignore_case&lt;/code&gt; now keeps its
needle in flash on ESP8266 via a &lt;code dir=&quot;auto&quot;&gt;PSTR&lt;/code&gt; wrapper and an &lt;code dir=&quot;auto&quot;&gt;_P&lt;/code&gt;-family implementation
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18574&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18574&lt;/a&gt;), and the 65-byte base64 alphabet table is gone
entirely, replaced by arithmetic range mapping that saves 64 bytes of RAM and doubles decode speed on host
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18454&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18454&lt;/a&gt;). Every ESP8266 device with API encryption benefits
from the base64 change automatically.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;framework-memory-and-build-efficiency&quot;&gt;Framework Memory And Build Efficiency&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Two coordinated efforts trim per-instance overhead and unused sources across the tree.
&lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt; and &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; drove a series of over 30
PRs moving trivial one-line accessors from &lt;code dir=&quot;auto&quot;&gt;.cpp&lt;/code&gt; files into headers so the compiler can inline them, covering
WiFi, Ethernet, logger, light, select, sensor, text sensor, climate, cover, fan, switch, valve, text,
datetime, thermostat, sprinkler, MQTT, WireGuard, display, safe_mode and more (representative measurements:
32 bytes saved on ESP8266 for wifi scan result accessors, 48 bytes for the remaining wifi accessors, similar
per-component savings across the tree). Separately, &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; extended the
&lt;code dir=&quot;auto&quot;&gt;FILTER_SOURCE_FILES&lt;/code&gt; pattern so binary_sensor click/multi-click sources, all three sensor filter files, and
&lt;code dir=&quot;auto&quot;&gt;esp32/gpio.cpp&lt;/code&gt; are only copied and compiled when the config actually uses them
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18602&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18602&lt;/a&gt;), and picked up other unused sources across
light/JSON schemas, i2s_audio SPDIF, MQTT entity types, uart debug, esp32_ble advertising, time posix TZ and
uptime timestamps (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18675&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18675&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18676&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18676&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18677&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18677&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18678&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18678&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18679&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18679&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18680&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18680&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18746&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18746&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18750&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18750&lt;/a&gt;). A few one-off wins round it out: &lt;code dir=&quot;auto&quot;&gt;APINoiseFrameHelper&lt;/code&gt;
is 104 bytes smaller per open encrypted connection (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18420&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18420&lt;/a&gt;),
the camera image reader is created lazily instead of per connection
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18421&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18421&lt;/a&gt;), and API message-type storage widened to &lt;code dir=&quot;auto&quot;&gt;uint16_t&lt;/code&gt;
without adding per-connection RAM (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18526&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18526&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esphome-device-builder&quot;&gt;ESPHome Device Builder&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This is a smaller cycle for the bundled &lt;a href=&quot;https://github.com/esphome/device-builder&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Device Builder&lt;/a&gt;, and
most of it already reached you through the 2026.8.x patch releases; this section covers everything since the 2026.8.0
release notes.&lt;/p&gt;
&lt;p&gt;The YAML diff view used to render credentials in plain text the moment you flipped the diff toggle. It now masks the
same sensitive values the editor does, with a reveal toggle
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1664&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1664&lt;/a&gt;). A WiFi password containing &lt;code dir=&quot;auto&quot;&gt;#&lt;/code&gt;
made every WiFi write append a second &lt;code dir=&quot;auto&quot;&gt;wifi_password:&lt;/code&gt; line to &lt;code dir=&quot;auto&quot;&gt;secrets.yaml&lt;/code&gt;; the writer now handles quoted values,
heals an already duplicated file, and reports a broken &lt;code dir=&quot;auto&quot;&gt;secrets.yaml&lt;/code&gt; as your file to fix rather than an internal
error (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2624&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2624&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1673&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1673&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;On ESPHome Web, flashing an ESP32-C6, H2 or P4 left the chip in the ROM bootloader instead of booting the new
firmware, so Improv never answered. The reset after flashing now boots the firmware
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1679&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1679&lt;/a&gt;), and &lt;strong&gt;Prepare for first use&lt;/strong&gt; gained
an &lt;strong&gt;Erase the device first&lt;/strong&gt; option so a board that ran other firmware does not come up with stale WiFi credentials
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1680&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1680&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;A paired build server that moves to a new IP on another subnet used to be reachable again only by editing the
endpoint by hand. After five minutes of silence it now dials back to announce its new address, so the pairing heals
itself (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2650&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2650&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In the editor, dot-prefixed top-level keys, the documented way to park YAML anchors, no longer render as bogus cards
or get deleted when you edit the section above them through the structured form
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1689&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1689&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2652&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2652&lt;/a&gt;), and the add-component form stops demanding pins and
dimensions that the selected display model already predefines
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2648&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2648&lt;/a&gt;). &lt;a href=&quot;https://github.com/Daniel085&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Daniel085&lt;/a&gt; brought
the device comment back to the tile card
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1671&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1671&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Under the hood, out-of-band edit detection uses a versioned whole-file fingerprint, so a future algorithm change can
never again trigger a fleet-wide regeneration on upgrade (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2617&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2617&lt;/a&gt;),
the Docker container reaps orphaned processes when running as PID 1
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2636&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2636&lt;/a&gt;), and version history ignores the fake executable bit
Samba puts on files edited from Windows (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2646&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2646&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;encrypted-ota-updates&quot;&gt;Encrypted OTA Updates&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; adds Noise (ChaCha20-Poly1305) encryption to the &lt;code dir=&quot;auto&quot;&gt;esphome&lt;/code&gt; OTA platform
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18489&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18489&lt;/a&gt;), using the same protocol the native API already
uses. Until now the firmware image travelled over the network in plaintext, so a passive listener on the LAN
could capture the WiFi credentials and API encryption key embedded in the image; the SHA256 password only
authenticated the client, it did not make the transfer confidential. A device with an &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; encryption key
now offers OTA encryption with that key and the CLI uses it whenever the device offers, so once a device runs
this release, enabling encryption is an ordinary update; the update that brings older firmware to this release
still travels in plaintext (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18979&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18979&lt;/a&gt;). An
&lt;code dir=&quot;auto&quot;&gt;encryption:&lt;/code&gt; block on the OTA platform is what makes the device require it: both the device and the CLI then
fail closed so an attacker cannot strip encryption and force a plaintext upload. A bare &lt;code dir=&quot;auto&quot;&gt;encryption:&lt;/code&gt; inherits
the &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; encryption key, and a password and encryption are mutually exclusive because the key already
authenticates the uploader. This work
sits on top of a new shared &lt;code dir=&quot;auto&quot;&gt;noise&lt;/code&gt; component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18490&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18490&lt;/a&gt;) that
lifts the noise-c dependency, HWRNG binding, error strings, PSK context, encryption key validation and the
handshake responder out of the api component so both api and ota can share them; there is no user
configuration for &lt;code dir=&quot;auto&quot;&gt;noise&lt;/code&gt; itself.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;improv-serial-beyond-wifi&quot;&gt;Improv Serial Beyond WiFi&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; makes &lt;code dir=&quot;auto&quot;&gt;improv_serial&lt;/code&gt; aware of the whole network stack instead of only
WiFi, so it now works on Ethernet-only boards and other WiFi-less devices
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17598&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17598&lt;/a&gt;). The component depends on &lt;code dir=&quot;auto&quot;&gt;network&lt;/code&gt; instead of
&lt;code dir=&quot;auto&quot;&gt;wifi&lt;/code&gt;, gates every WiFi call behind &lt;code dir=&quot;auto&quot;&gt;#ifdef USE_WIFI&lt;/code&gt;, and implements the new Improv &lt;code dir=&quot;auto&quot;&gt;Get Network State&lt;/code&gt;
RPC (0x07) that reports which interfaces are up and the web server URL for each one. The Improv state machine
still uses WiFi provisioning where WiFi exists; on WiFi-less builds it reports &lt;code dir=&quot;auto&quot;&gt;STOPPED&lt;/code&gt; so clients do not
offer a WiFi form that cannot succeed. &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; additionally adds an optional
&lt;code dir=&quot;auto&quot;&gt;uart_id:&lt;/code&gt; so Improv can run on a dedicated UART bus separate from the logger’s serial port
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18794&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18794&lt;/a&gt;), which also makes the protocol end-to-end testable
via the new host integration test.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;provisioning-shuts-down-when-the-window-closes&quot;&gt;Provisioning Shuts Down When The Window Closes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Also from &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;: the WiFi access point and captive portal are now torn down when
the provisioning window closes, matching the treatment BLE Improv already had
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17466&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17466&lt;/a&gt;). An unprovisioned device that times out is now fully
unprovisionable until it is power-cycled - BLE Improv stops, the captive portal stops, the access point
disappears, and new API clients are turned away. Because a device whose access point is its only network
connection becomes unreachable when the window closes, &lt;code dir=&quot;auto&quot;&gt;provisioning:&lt;/code&gt; now warns at config time when WiFi is
configured with an access point and no station credentials.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;isr-driven-ir-transmission-on-libretiny&quot;&gt;ISR-Driven IR Transmission On LibreTiny&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; rewrites &lt;code dir=&quot;auto&quot;&gt;remote_transmitter&lt;/code&gt; on Beken BK7231N/BK7238 and Realtek RTL8720C
to pace the IR envelope with a hardware timer interrupt chain instead of a priority-boosted busy-wait
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18648&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18648&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18660&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18660&lt;/a&gt;). Interrupts stay enabled throughout, so WiFi and
lwIP tasks run normally during long transmissions and &lt;code dir=&quot;auto&quot;&gt;remote_receiver&lt;/code&gt; decodes the device’s own frames off
the air during a send. &lt;code dir=&quot;auto&quot;&gt;non_blocking:&lt;/code&gt; is now supported on both families (previously ESP32-RMT only): the
send returns immediately after arming the chain and &lt;code dir=&quot;auto&quot;&gt;on_complete&lt;/code&gt; fires from &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt;. Bench measurements on
an RM4 Pro (RTL8720CF) show 25.01-25.09ms repeat gaps for a configured 25ms (tighter than the busy-wait’s
25.02-25.05ms) and 27 captured transmissions all bit-perfect; an FK UFO-R4 (BK7238) measured 16-30us
duty-apply latency and 39/39 bit-perfect NEC envelopes.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;modbus-controller-overhaul&quot;&gt;Modbus Controller Overhaul&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The long-running modbus refactor from &lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; continues with a large batch of
improvements. Writer entities (switch, number, output, select) become their own persistent hub devices with a
heap-free write path that allocates nothing after &lt;code dir=&quot;auto&quot;&gt;setup()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;write_lambda&lt;/code&gt; gets full access to the
underlying device so a coil switch can drive a holding-register write
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18082&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18082&lt;/a&gt;). Range polling moves onto the same
&lt;code dir=&quot;auto&quot;&gt;PollingDevice&lt;/code&gt; architecture (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18071&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18071&lt;/a&gt;), saving 1,756 bytes of
flash on the ESP8266 test config with byte-identical RAM. The &lt;code dir=&quot;auto&quot;&gt;register_count&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;force_new_range&lt;/code&gt; keys are
consolidated into a single tri-state &lt;code dir=&quot;auto&quot;&gt;reuse_previous_range&lt;/code&gt; option
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18085&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18085&lt;/a&gt;) that says how a sensor relates to the range built
just before it (auto/true/false), and &lt;code dir=&quot;auto&quot;&gt;custom_command&lt;/code&gt; is renamed to &lt;code dir=&quot;auto&quot;&gt;custom_pdu&lt;/code&gt; with auto-migration when
the leading byte matches the controller address
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18652&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18652&lt;/a&gt;). A new &lt;code dir=&quot;auto&quot;&gt;continuous:&lt;/code&gt; option on both the client
actions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18542&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18542&lt;/a&gt;) and the controller
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18080&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18080&lt;/a&gt;) makes reads stream back-to-back to fill idle bus
time. Two write-path bug fixes ship as breaking changes: the switch/output write offset is now byte-accurate
(previously doubled) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18787&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18787&lt;/a&gt;) and a switch &lt;code dir=&quot;auto&quot;&gt;write_lambda&lt;/code&gt;
return value now only changes the value written to the device rather than the displayed state
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18788&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18788&lt;/a&gt;), so an active-low relay finally displays the
requested state instead of the inverted one. Users of &lt;code dir=&quot;auto&quot;&gt;custom_command&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;register_count&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;force_new_range&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;skip_updates&lt;/code&gt; should review their configs.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-components-and-hardware-support&quot;&gt;New Components And Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Six new components join the tree:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/ds1603l/&quot;&gt;ds1603l&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/JakeLC15&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@JakeLC15&lt;/a&gt; - a UART ultrasonic
liquid-level sensor with configurable min/max level and volume mapping
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/13133&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13133&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/d01/&quot;&gt;d01&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/ch604&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ch604&lt;/a&gt; - a PM2.5 particulate sensor that
broadcasts its own packets every 1.4 seconds (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17788&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17788&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/sfa40/&quot;&gt;sfa40&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/NoQuarrel&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@NoQuarrel&lt;/a&gt; - the Sensirion SFA40
formaldehyde sensor with temperature and humidity readings
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17815&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17815&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/mk2pvrouter/&quot;&gt;mk2pvrouter&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/FredM67&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@FredM67&lt;/a&gt; - Mk2PVRouter
telemetry over UART, modelled on the TeleInfo component
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/8487&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#8487&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/display/snapshot/&quot;&gt;snapshot&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - a display
platform that draws into memory and writes BMP files, works anywhere the &lt;code dir=&quot;auto&quot;&gt;host&lt;/code&gt; platform runs, and pairs
with a new &lt;code dir=&quot;auto&quot;&gt;headless:&lt;/code&gt; option on the SDL display for documentation captures and CI golden-image tests
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17917&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17917&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;noise&lt;/strong&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; - a shared internal Noise
primitives component that api and the new encrypted OTA both consume; no user configuration
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18490&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18490&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-features-in-existing-components&quot;&gt;New Features In Existing Components&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/time/zigbee/&quot;&gt;zigbee time platform&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; adds a
Zigbee-sourced time provider on ESP32 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18656&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18656&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/water_heater/tuya/&quot;&gt;tuya water_heater&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/iago-veiga&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@iago-veiga&lt;/a&gt; exposes a Tuya-MCU electric water heater as a single
&lt;code dir=&quot;auto&quot;&gt;water_heater&lt;/code&gt; entity, collapsing the previous template-plus-lambda pattern into one block
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17323&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17323&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/climate/template/&quot;&gt;template climate&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/rsre&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rsre&lt;/a&gt; builds a full
climate entity out of ESPHome primitives, with per-field set actions, an &lt;code dir=&quot;auto&quot;&gt;on_control&lt;/code&gt; trigger, an optimistic
mode that applies commands locally, and a &lt;code dir=&quot;auto&quot;&gt;climate.template.publish&lt;/code&gt; action for reporting the device’s own
state (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14455&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14455&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/lvgl/widgets/#list&quot;&gt;lvgl list widget&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;
adds a scrollable container designed to be filled at runtime, with &lt;code dir=&quot;auto&quot;&gt;add_text&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;add&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;remove&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;clear&lt;/code&gt;
actions plus &lt;code dir=&quot;auto&quot;&gt;on_add&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;on_remove&lt;/code&gt; triggers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18018&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18018&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/lvgl/widgets/#table&quot;&gt;lvgl table widget&lt;/a&gt;&lt;/strong&gt; also by
&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; adds a lightweight grid of text elements
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18422&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18422&lt;/a&gt;) and support for LVGL 9.5’s radial and conical
gradients (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18818&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18818&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/image/online_image/&quot;&gt;online_image auto-detection&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/guillempages&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@guillempages&lt;/a&gt; picks up the image format from the server’s &lt;code dir=&quot;auto&quot;&gt;Content-Type&lt;/code&gt;
header (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16337&lt;/a&gt;), plus QOI format support in &lt;code dir=&quot;auto&quot;&gt;runtime_image&lt;/code&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16945&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16945&lt;/a&gt;) and a decoder that stays allocated between images
of the same format (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18488&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18488&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/ethernet/&quot;&gt;ethernet spi_id&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; lets a SPI
ethernet chip (W5500, DM9051, ENC28J60, CH390) attach to an existing &lt;code dir=&quot;auto&quot;&gt;spi:&lt;/code&gt; bus so it can share pins with
other SPI peripherals like a display on boards such as the M5Stack CoreS3
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18530&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18530&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/network/&quot;&gt;network tcp_send_buffer&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; exposes lwIP’s
per-socket send buffer size on ESP-IDF, giving Bluetooth proxies a way to raise the TCP buffer without
paying the RAM cost of &lt;code dir=&quot;auto&quot;&gt;enable_high_performance&lt;/code&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18610&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18610&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/display/waveshare_epaper/&quot;&gt;epaper_spi UC8179&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; adds a monochrome UC8179 driver with three refresh modes and
registers models for the Waveshare 7.5in v2 panel and the Seeed reTerminal E1001
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17568&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17568&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/api/&quot;&gt;api user-defined action metadata&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt; adds optional &lt;code dir=&quot;auto&quot;&gt;description&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;example&lt;/code&gt; fields on API actions
and variables so Home Assistant renders a proper form; ESP8266 configs with unusually long action metadata
may need trimming to fit the 384-byte-per-action limit
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18881&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18881&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/sen6x/&quot;&gt;sen6x algorithm tuning&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt; exposes Sensirion’s VOC/NOx tuning parameters
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18779&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18779&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/emontx/&quot;&gt;emontx AP and F tags&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/FredM67&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@FredM67&lt;/a&gt; adds
apparent power and frequency sensor tags with correct defaults
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18586&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18586&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/climate/climate_ir/#climate_ir_lg&quot;&gt;climate_ir_lg advanced commands&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/ireun&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ireun&lt;/a&gt; adds an &lt;code dir=&quot;auto&quot;&gt;advanced_commands_support&lt;/code&gt; flag that fixes heat/cool temperature
setting, decodes JET mode, adds swing settings and rejects previously misdecoded frames
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/10875&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#10875&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/climate/mitsubishi_cn105/&quot;&gt;mitsubishi_cn105 Fahrenheit&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt; implements the non-linear Fahrenheit mapping the Mitsubishi A/C
hardware actually uses (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15488&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15488&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/cover/hoermann_hcp/&quot;&gt;hoermann_hcp buttons&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/zweckj&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@zweckj&lt;/a&gt; adds venting
and half-open buttons (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18544&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18544&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/media_player/&quot;&gt;audio_http persistent buffer&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/n-IA-hane&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@n-IA-hane&lt;/a&gt; keeps the HTTP decoder ring buffer allocated between playback
sessions to avoid heap fragmentation on memory-tight devices
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18708&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18708&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/bluetooth_proxy/&quot;&gt;rp2_ble_tracker automation&lt;/a&gt;&lt;/strong&gt; by
&lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt; wires the shared BLE automation surface onto the RP2 tracker
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18717&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18717&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;networking-and-diagnostics&quot;&gt;Networking And Diagnostics&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Several targeted changes for network-heavy devices. Bluetooth proxy congestion warnings now fire once per
transaction and once per connection instead of on every drop cycle, ending the log flood a bulk transfer to
opendisplay-style screens produced (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18605&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18605&lt;/a&gt;).
&lt;code dir=&quot;auto&quot;&gt;esp32_ble_tracker&lt;/code&gt; now warns at config time when the scan window exceeds 600ms while WiFi is configured,
because holding the shared radio for over a second at a time starves WiFi and causes disconnects
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18725&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18725&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;espota2&lt;/code&gt; now logs the erase-prepare window
separately from the upload window and reports total OTA time
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18582&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18582&lt;/a&gt;), so users see why there is a silent pause after the
handshake instead of interpreting it as a stall.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp32-custom-efuse-mac-applied-consistently&quot;&gt;ESP32 Custom eFuse MAC Applied Consistently&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; fixes an inconsistency where a custom MAC burned into the ESP32’s eFuses
was only applied to WiFi (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18452&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18452&lt;/a&gt;). The apply now runs in
&lt;code dir=&quot;auto&quot;&gt;app_main()&lt;/code&gt; before any component sets up, so Ethernet, Bluetooth and 802.15.4 all derive their addresses
from the custom base MAC. Only devices with a burned custom eFuse MAC AND Ethernet/Bluetooth/802.15.4 are
affected; on those devices Ethernet, Bluetooth and Thread/Zigbee will change on-wire MAC addresses on
upgrade, so DHCP reservations, MAC filters and BLE pairings may need updating (set
&lt;code dir=&quot;auto&quot;&gt;ignore_efuse_custom_mac: true&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;esp32.advanced&lt;/code&gt; to keep the old behaviour).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;codebase-type-annotations&quot;&gt;Codebase Type Annotations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;, a repo-wide sweep in eleven parts added parameter and
return type annotations to every mid-sized component’s Python code (over 130 components in this batch,
plus a smaller follow-up in &lt;a href=&quot;https://github.com/esphome/esphome/pull/18697&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18697&lt;/a&gt;), landing across
PRs &lt;a href=&quot;https://github.com/esphome/esphome/pull/18338&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18338&lt;/a&gt; through
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18348&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18348&lt;/a&gt;. Because component modules do not use
&lt;code dir=&quot;auto&quot;&gt;from __future__ import annotations&lt;/code&gt;, every annotation is evaluated at import time, so the sweep also had to
add every missing import for the names it introduced; an all-modules import check pins that. No behaviour
changes.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;thank-you-contributors&quot;&gt;Thank You, Contributors&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;This release includes 275 pull requests from over 30 contributors. A huge thank you to everyone who made 2026.9.0
possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; - 25 PRs including the multi-release Modbus overhaul: PollingDevice-based
controller polling, continuous polling, heap-free writer entities, a compile-time register decoder, and the switch to
typed address-based read callbacks across sdm_meter, growatt_solar, havells_solar, kuntze, pzemac, pzemdc, and
selec_meter&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; - 20 PRs including the 12-part sweep adding Python type annotations
across the component tree, the &lt;code dir=&quot;auto&quot;&gt;FINAL_VALIDATE_SCHEMA&lt;/code&gt; return-type migration, the &lt;code dir=&quot;auto&quot;&gt;uart&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;check_uart_settings&lt;/code&gt; move to
final validation, the new UC8179 e-paper driver, and the &lt;code dir=&quot;auto&quot;&gt;ethernet&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;spi_id&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - 15 PRs including the new SDL snapshot and headless display mode,
LVGL list and table widgets, LVGL radial and conical gradients, ESP32-S31 support in &lt;code dir=&quot;auto&quot;&gt;mipi_rgb&lt;/code&gt;, and CodSpeed
benchmark reliability fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; - 9 PRs including the provisioning window shutdown behavior, &lt;code dir=&quot;auto&quot;&gt;improv_serial&lt;/code&gt;
support for Ethernet and non-WiFi interfaces, the ESP32 custom eFuse base-MAC fix, and ISR-driven &lt;code dir=&quot;auto&quot;&gt;remote_transmitter&lt;/code&gt;
on RTL8720C and BK7231N/BK7238&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/guillempages&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@guillempages&lt;/a&gt; - 8 PRs including &lt;code dir=&quot;auto&quot;&gt;runtime_image&lt;/code&gt; format auto-detection, QOI
decoding, MIME types, decoder retention, and BMP dimension validation, plus the portable &lt;code dir=&quot;auto&quot;&gt;str_contains_ignore_case&lt;/code&gt;
helper&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt; - 6 PRs including the WiFi scan list dedupe helper shared with
&lt;code dir=&quot;auto&quot;&gt;improv_serial&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sen6x&lt;/code&gt; VOC/NOx algorithm tuning, description and example metadata on user-defined API actions, and
BK72xx &lt;code dir=&quot;auto&quot;&gt;deep_sleep&lt;/code&gt; wakeup validation&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; - 6 PRs including CI diff-size fallback and max-parallel removal,
&lt;code dir=&quot;auto&quot;&gt;external_components&lt;/code&gt; override logging, and ESP32-S31 ADC and GPIO support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/FredM67&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@FredM67&lt;/a&gt; - 4 PRs including the new &lt;code dir=&quot;auto&quot;&gt;mk2pvrouter&lt;/code&gt; component and &lt;code dir=&quot;auto&quot;&gt;emontx&lt;/code&gt; apparent power
and frequency sensor support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt; - 4 PRs including the &lt;code dir=&quot;auto&quot;&gt;USBUartChannelBase&lt;/code&gt; extraction, moving &lt;code dir=&quot;auto&quot;&gt;CONF_SLOT&lt;/code&gt;
and &lt;code dir=&quot;auto&quot;&gt;CONF_LABEL&lt;/code&gt; into the shared &lt;code dir=&quot;auto&quot;&gt;const&lt;/code&gt; module, and uncovering a silent &lt;code dir=&quot;auto&quot;&gt;safe_mode&lt;/code&gt; error&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt; - 3 PRs including &lt;code dir=&quot;auto&quot;&gt;mitsubishi_cn105&lt;/code&gt; Fahrenheit support, deferred status
requests, and marking configurable classes as final&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt; - 2 PRs including the &lt;code dir=&quot;auto&quot;&gt;IntervalSyncer&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;PollingComponent&lt;/code&gt; refactor and an
&lt;code dir=&quot;auto&quot;&gt;openthread&lt;/code&gt; shutdown fix&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/n-IA-hane&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@n-IA-hane&lt;/a&gt; - 2 PRs including SPI PSRAM DMA for external buffers and an &lt;code dir=&quot;auto&quot;&gt;audio_http&lt;/code&gt;
persistent ring buffer option&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt; - 2 PRs including &lt;code dir=&quot;auto&quot;&gt;rp2_ble_tracker&lt;/code&gt; automation triggers and scan actions
plus a LibreTiny WiFi STA state reset on synchronous connect failure&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JakeLC15&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@JakeLC15&lt;/a&gt; - the new DS1603L ultrasonic liquid-level sensor component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ch604&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ch604&lt;/a&gt; - the new D01 PM2.5 sensor component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/NoQuarrel&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@NoQuarrel&lt;/a&gt; - the new SFA40 formaldehyde sensor component&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also thank you to &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, &lt;a href=&quot;https://github.com/ireun&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ireun&lt;/a&gt;,
&lt;a href=&quot;https://github.com/iago-veiga&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@iago-veiga&lt;/a&gt;, &lt;a href=&quot;https://github.com/leodrivera&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@leodrivera&lt;/a&gt;,
&lt;a href=&quot;https://github.com/JoppyFurr&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@JoppyFurr&lt;/a&gt;, &lt;a href=&quot;https://github.com/DavidvtWout&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@DavidvtWout&lt;/a&gt;,
&lt;a href=&quot;https://github.com/alaraun&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@alaraun&lt;/a&gt;, &lt;a href=&quot;https://github.com/zweckj&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@zweckj&lt;/a&gt;,
&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;, &lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt;,
&lt;a href=&quot;https://github.com/Gafielt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Gafielt&lt;/a&gt;, &lt;a href=&quot;https://github.com/MakerYuichi&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@MakerYuichi&lt;/a&gt;,
&lt;a href=&quot;https://github.com/mfishma&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mfishma&lt;/a&gt;, and &lt;a href=&quot;https://github.com/Zebble&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Zebble&lt;/a&gt; for their contributions, and to
everyone who reported issues, tested pre-releases, and helped in the community.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;custom_command&lt;/code&gt; renamed to &lt;code dir=&quot;auto&quot;&gt;custom_pdu&lt;/code&gt; and now takes the PDU only (function code + data), not
a full frame. The controller’s &lt;code dir=&quot;auto&quot;&gt;address:&lt;/code&gt; and CRC are appended automatically. Configs whose first byte matched the
controller’s &lt;code dir=&quot;auto&quot;&gt;address:&lt;/code&gt; are auto-migrated with a deprecation warning until 2027.3.0; frames targeting a different unit
address must be moved to a sensor on the correct controller. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18652&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18652&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;address: 0&lt;/code&gt; (Modbus broadcast) is now rejected with a validation error. A broadcast is never
answered, so it could never be polled. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18652&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18652&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: The per-sensor &lt;code dir=&quot;auto&quot;&gt;skip_updates&lt;/code&gt; option is retired and has no effect. It logs a deprecation
warning at configuration time (removed in 2027.3.0). To poll some registers less often, add a second
&lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; with the same &lt;code dir=&quot;auto&quot;&gt;address:&lt;/code&gt; and a slower &lt;code dir=&quot;auto&quot;&gt;update_interval:&lt;/code&gt;, and attach the slow sensors to it.
&lt;code dir=&quot;auto&quot;&gt;offline_skip_updates&lt;/code&gt; (controller-level) is unaffected. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18652&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18652&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;register_count&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;force_new_range&lt;/code&gt; are replaced by a new tri-state
&lt;code dir=&quot;auto&quot;&gt;reuse_previous_range&lt;/code&gt; option (&lt;code dir=&quot;auto&quot;&gt;auto&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt;). &lt;code dir=&quot;auto&quot;&gt;force_new_range: true&lt;/code&gt; migrates automatically to
&lt;code dir=&quot;auto&quot;&gt;reuse_previous_range: false&lt;/code&gt; with a deprecation warning (removed in 2027.3.0). A &lt;code dir=&quot;auto&quot;&gt;register_count&lt;/code&gt; matching the
derived width warns as redundant; a divergent one now fails validation with migration instructions. The old vendor
pattern of &lt;code dir=&quot;auto&quot;&gt;register_count: 1&lt;/code&gt; + &lt;code dir=&quot;auto&quot;&gt;response_size: 4&lt;/code&gt; for an FP32 no longer validates. Range splitting is now strictly
address-ordered, so where isolated items were previously sorted first the range may now split at their position.
A &lt;code dir=&quot;auto&quot;&gt;RAW&lt;/code&gt; value or text sensor with a &lt;code dir=&quot;auto&quot;&gt;response_size&lt;/code&gt; now spans &lt;code dir=&quot;auto&quot;&gt;ceil(response_size / 2)&lt;/code&gt; registers, one more than
before for odd values. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18085&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18085&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: Holding-register &lt;code dir=&quot;auto&quot;&gt;switch&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; platforms now apply a non-zero &lt;code dir=&quot;auto&quot;&gt;offset&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;byte_offset&lt;/code&gt;
byte-accurately (&lt;code dir=&quot;auto&quot;&gt;address + offset/2&lt;/code&gt;) instead of doubling it. Configs with a non-zero write offset on these
platforms must re-verify the target register. Odd offsets on these two platforms are now rejected at validation, as
a 16-bit register write cannot target half a register. The &lt;code dir=&quot;auto&quot;&gt;number&lt;/code&gt; platform’s odd offsets are unchanged.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18787&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18787&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: A &lt;code dir=&quot;auto&quot;&gt;switch&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;write_lambda&lt;/code&gt; returning a bool different from &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; now only changes the value
written to the device; the switch reports the requested state. Lambdas that relied on the return value flipping the
displayed state should publish explicitly or invert in the read &lt;code dir=&quot;auto&quot;&gt;lambda&lt;/code&gt; instead. The lambda’s &lt;code dir=&quot;auto&quot;&gt;payload&lt;/code&gt; parameter
changes type from &lt;code dir=&quot;auto&quot;&gt;std::vector&lt;/code&gt; to a fixed-capacity &lt;code dir=&quot;auto&quot;&gt;RegisterValues&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;PduBuffer&lt;/code&gt;; &lt;code dir=&quot;auto&quot;&gt;push_back&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;clear&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;assign&lt;/code&gt;
and indexing still work, but &lt;code dir=&quot;auto&quot;&gt;resize&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;reserve&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;insert&lt;/code&gt; and passing to &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x26;&lt;/code&gt; helpers no longer compile.
A lambda that fills &lt;code dir=&quot;auto&quot;&gt;payload&lt;/code&gt; and returns &lt;code dir=&quot;auto&quot;&gt;{}&lt;/code&gt; now sends the buffer (as documented); previously that combination
sent nothing. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18788&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18788&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18082&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18082&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: For a &lt;code dir=&quot;auto&quot;&gt;custom_pdu&lt;/code&gt; poll, the &lt;code dir=&quot;auto&quot;&gt;address&lt;/code&gt; argument delivered to &lt;code dir=&quot;auto&quot;&gt;on_command_sent&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_online&lt;/code&gt;
and &lt;code dir=&quot;auto&quot;&gt;on_offline&lt;/code&gt; triggers is now &lt;code dir=&quot;auto&quot;&gt;-1&lt;/code&gt; (no decodable address) instead of the sensor’s synthesized address. Automations
filtering on a custom sensor’s synthetic address must test for &lt;code dir=&quot;auto&quot;&gt;-1&lt;/code&gt; instead. The &lt;code dir=&quot;auto&quot;&gt;function_code&lt;/code&gt; argument for a
&lt;code dir=&quot;auto&quot;&gt;custom_pdu&lt;/code&gt; whose first byte has the 0x80 bit set is now reported with that bit masked (0x83 reports as 0x03).
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18071&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18071&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runtime Image&lt;/strong&gt;: The image decoder is now kept allocated between decodes to avoid memory churn when decoding
multiple images of the same format. This adds a small persistent memory overhead for the decoder object; on
memory-constrained devices, reducing runtime image usage or restarting less frequently may be needed.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18488&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18488&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;homeassistant.event&lt;/code&gt; variables are now compiled as lambdas when they use &lt;code dir=&quot;auto&quot;&gt;!lambda&lt;/code&gt; or look like lambda
source; a plain string that looks like lambda source now logs a deprecation warning and will be treated as static
text in 2027.3.0. Tag lambda values with &lt;code dir=&quot;auto&quot;&gt;!lambda&lt;/code&gt; explicitly. &lt;code dir=&quot;auto&quot;&gt;homeassistant.action&lt;/code&gt; now accepts plain static
strings (previously rejected) and sends them as text. A &lt;code dir=&quot;auto&quot;&gt;cv.returning_lambda&lt;/code&gt; value whose only &lt;code dir=&quot;auto&quot;&gt;return&lt;/code&gt; sits inside
a comment, or only matches as a substring like &lt;code dir=&quot;auto&quot;&gt;the_return_value&lt;/code&gt;, now fails validation instead of failing at C++
compile. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18759&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18759&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API&lt;/strong&gt;: User-defined actions now accept optional &lt;code dir=&quot;auto&quot;&gt;description&lt;/code&gt; and per-variable &lt;code dir=&quot;auto&quot;&gt;description&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;example&lt;/code&gt;
metadata using a new mapping form for &lt;code dir=&quot;auto&quot;&gt;variables:&lt;/code&gt;. On ESP8266 only, each action’s action name, variable names,
description and example text must total at most 384 bytes; configs that exceed this fail validation with a message
identifying the action and its size. Other platforms have no limit. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18881&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18881&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API&lt;/strong&gt;: The legacy media player &lt;code dir=&quot;auto&quot;&gt;supports_pause&lt;/code&gt; field is no longer sent. Clients on API 1.11 or newer already use
&lt;code dir=&quot;auto&quot;&gt;feature_flags&lt;/code&gt;, so current Home Assistant is unaffected; only very old clients that never learned &lt;code dir=&quot;auto&quot;&gt;feature_flags&lt;/code&gt;
would lose pause capability. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18801&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18801&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preferences&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;IntervalSyncer&lt;/code&gt; is now a &lt;code dir=&quot;auto&quot;&gt;PollingComponent&lt;/code&gt;, so its interval can be suspended and resumed with
&lt;code dir=&quot;auto&quot;&gt;component.suspend&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;component.resume&lt;/code&gt;. No YAML changes are required; the previous &lt;code dir=&quot;auto&quot;&gt;flash_write_interval: 0&lt;/code&gt;
loop-every-iteration special case was already dead code (coerced to &lt;code dir=&quot;auto&quot;&gt;1ms&lt;/code&gt; by the validator). Lambdas that called
the old &lt;code dir=&quot;auto&quot;&gt;set_write_interval()&lt;/code&gt; still compile via a deprecated shim that forwards to &lt;code dir=&quot;auto&quot;&gt;set_update_interval()&lt;/code&gt;,
removed in 2027.3.0. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14370&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14370&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;platform-changes&quot;&gt;Platform Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32&lt;/strong&gt;: When a custom MAC address is burned into the eFuses, ESPHome now applies it as the system base MAC
before any component runs, so every interface (Wi-Fi, Ethernet, Bluetooth, 802.15.4) derives its address from it.
Previously only Wi-Fi did. Devices with a custom eFuse MAC and Ethernet, Bluetooth, or 802.15.4 will appear on the
network with a new MAC after upgrading: DHCP reservations, ACLs and Bluetooth bonds keyed to the old MAC need to be
updated, and 802.15.4 (Thread/Zigbee) nodes may need to be re-commissioned. Devices without a custom eFuse MAC (the
vast majority) are unaffected; setting &lt;code dir=&quot;auto&quot;&gt;ignore_efuse_custom_mac: true&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;esp32: advanced:&lt;/code&gt; disables the
behavior. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18452&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18452&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 Hosted&lt;/strong&gt;: Now requires ESP-IDF 5.3 or newer. The legacy fallback to esp_hosted 2.0.11 (which had a known
double-free crash on ESP32-P4 + C6) has been removed and older ESP-IDF versions now fail validation with a clear
error. Configs that pin an ESP-IDF version below 5.3 alongside &lt;code dir=&quot;auto&quot;&gt;esp32_hosted&lt;/code&gt; must remove the pin or bump it to
5.3 or newer. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18417&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18417&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART&lt;/strong&gt;: UART settings validation (&lt;code dir=&quot;auto&quot;&gt;baud_rate&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;parity&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;data_bits&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;stop_bits&lt;/code&gt;) for components that require
specific values now happens at configuration time instead of only being logged at runtime. Nine previously
unchecked components (&lt;code dir=&quot;auto&quot;&gt;cm1106&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;daly_bms&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;hrxl_maxsonar_wr&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;hydreon_rgxx&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;mhz19&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pylontech&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;teleinfo&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;vbus&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;wl_134&lt;/code&gt;) and twelve components with incomplete checks now enforce their required UART parameters. Users
with non-default UART settings that a component never supported will now get a configuration error instead of a
runtime log error. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18940&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18940&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;undocumented-api-changes&quot;&gt;Undocumented API Changes&lt;/h3&gt;&lt;/div&gt;

&lt;p&gt;Advanced users with lambdas that touch component internals should note the following C++ changes. These APIs are
not covered by the formal breaking-change policy (they are undocumented public methods), but lambdas often depend on
them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Preferences&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;IntervalSyncer::set_write_interval()&lt;/code&gt; is deprecated in favour of &lt;code dir=&quot;auto&quot;&gt;set_update_interval()&lt;/code&gt; (the
new &lt;code dir=&quot;auto&quot;&gt;PollingComponent&lt;/code&gt; base’s method) and will be removed in 2027.3.0. Existing lambdas calling
&lt;code dir=&quot;auto&quot;&gt;set_write_interval()&lt;/code&gt; continue to compile via a forwarding shim.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/14370&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14370&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: New compile-time helpers &lt;code dir=&quot;auto&quot;&gt;registers_to_value&amp;#x3C;VALUE_TYPE&gt;()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;registers_to_uint32()&lt;/code&gt; are available
in &lt;code dir=&quot;auto&quot;&gt;modbus_helpers.h&lt;/code&gt; for lambdas that know the value type at compile time. The runtime &lt;code dir=&quot;auto&quot;&gt;registers_to_number()&lt;/code&gt;
is unchanged. Prefer the templated form when the type is known, as it inlines to a handful of instructions and
returns the value’s natural type instead of &lt;code dir=&quot;auto&quot;&gt;int64_t&lt;/code&gt;.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18863&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18863&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;ModbusCommandItem&lt;/code&gt;, its factories (&lt;code dir=&quot;auto&quot;&gt;create_read_command&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;create_write_single_command&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;create_custom_command&lt;/code&gt; and friends), &lt;code dir=&quot;auto&quot;&gt;queue_command()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;unqueue_command()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_write_register_response()&lt;/code&gt; and
the &lt;code dir=&quot;auto&quot;&gt;FunctionCode::CUSTOM&lt;/code&gt; alias are deprecated and removed in 2027.3.0. Migrate one-shot writes to the entity
write helpers exposed through &lt;code dir=&quot;auto&quot;&gt;WriterDevice&lt;/code&gt; (available as &lt;code dir=&quot;auto&quot;&gt;item-&gt;&lt;/code&gt; inside a &lt;code dir=&quot;auto&quot;&gt;write_lambda&lt;/code&gt;), or to the
&lt;code dir=&quot;auto&quot;&gt;modbus_client&lt;/code&gt; write actions. Use &lt;code dir=&quot;auto&quot;&gt;FunctionCode::INVALID&lt;/code&gt; for the sentinel value formerly named
&lt;code dir=&quot;auto&quot;&gt;FunctionCode::CUSTOM&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18071&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18071&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;write_lambda&lt;/code&gt; has a stronger &lt;code dir=&quot;auto&quot;&gt;item&lt;/code&gt; pointer now. &lt;code dir=&quot;auto&quot;&gt;item&lt;/code&gt; is the entity’s own persistent
modbus device (not a throwaway command object), and the write helpers plus &lt;code dir=&quot;auto&quot;&gt;item-&gt;queue_pdu()&lt;/code&gt; are the entire
API. A lambda can drive any register, coil, or custom-PDU write through it, regardless of the entity’s own
register type. Before/after for a coil switch writing a holding register:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Before: throwaway ModbusCommandItem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; cmd &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ModbusCommandItem::&lt;/span&gt;&lt;span&gt;create_write_single_command&lt;/span&gt;&lt;span&gt;(parent_, &lt;/span&gt;&lt;span&gt;&lt;span&gt;0x&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, x &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;parent_&lt;/span&gt;&lt;span&gt;-&gt;&lt;/span&gt;&lt;span&gt;queue_command&lt;/span&gt;&lt;span&gt;(cmd);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// After: entity&apos;s own device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;item&lt;/span&gt;&lt;span&gt;-&gt;&lt;/span&gt;&lt;span&gt;write_single_register&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;0x&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, x &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;0x&lt;/span&gt;&lt;span&gt;0001&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;0x&lt;/span&gt;&lt;span&gt;0000&lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;payload&lt;/code&gt; parameter’s type also changes from &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x3C;uint16_t&gt;&lt;/code&gt; to a fixed-capacity &lt;code dir=&quot;auto&quot;&gt;RegisterValues&lt;/code&gt;
(writes) or &lt;code dir=&quot;auto&quot;&gt;PduBuffer&lt;/code&gt; (custom PDUs). &lt;code dir=&quot;auto&quot;&gt;push_back&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;clear&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;assign&lt;/code&gt; and indexing keep working; &lt;code dir=&quot;auto&quot;&gt;resize&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;reserve&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;insert&lt;/code&gt; and passing to &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x26;&lt;/code&gt; helpers no longer compile. Filling &lt;code dir=&quot;auto&quot;&gt;payload&lt;/code&gt; and returning
&lt;code dir=&quot;auto&quot;&gt;{}&lt;/code&gt; now sends the buffer (as the docs have always described); previously that combination sent nothing.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18082&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18082&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;SensorItem::register_count&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;SensorItem::force_new_range&lt;/code&gt; are removed. Lambdas that
read a sensor item’s register span should call &lt;code dir=&quot;auto&quot;&gt;entity_count()&lt;/code&gt; instead; the join behaviour previously encoded in
&lt;code dir=&quot;auto&quot;&gt;force_new_range&lt;/code&gt; is now expressed by the tri-state &lt;code dir=&quot;auto&quot;&gt;reuse_previous_range&lt;/code&gt; option on the following sensor.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18085&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18085&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;RealTimeClock::set_timezone()&lt;/code&gt; (the C++ string-argument overload) and the on-device POSIX TZ string
parser (&lt;code dir=&quot;auto&quot;&gt;parse_posix_tz()&lt;/code&gt; and helpers) are removed. There is no string-based C++ replacement: set &lt;code dir=&quot;auto&quot;&gt;timezone:&lt;/code&gt;
in YAML, or let Home Assistant push a pre-parsed timezone over the API. Home Assistant 2026.3.0 and newer send
the pre-parsed struct; older clients keep the codegen timezone.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18383&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18383&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Core&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;EntityBase::get_device_class_ref()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_device_class()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_unit_of_measurement()&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;get_icon_ref()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;get_icon()&lt;/code&gt; removed. Use &lt;code dir=&quot;auto&quot;&gt;get_device_class_to()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_unit_of_measurement_ref()&lt;/code&gt; and
&lt;code dir=&quot;auto&quot;&gt;get_icon_to()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18375&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18375&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core&lt;/strong&gt;: Deprecated free functions &lt;code dir=&quot;auto&quot;&gt;gamma_correct()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;gamma_uncorrect()&lt;/code&gt; removed. Use
&lt;code dir=&quot;auto&quot;&gt;LightState::gamma_correct_lut()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;LightState::gamma_uncorrect_lut()&lt;/code&gt;.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18376&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18376&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;esp_log_vprintf_()&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;__FlashStringHelper&lt;/code&gt; overload removed; the &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt; overload is
unchanged. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18377&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18377&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;make_name_with_suffix()&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; overloads removed (hard removal, no deprecation cycle). Use
&lt;code dir=&quot;auto&quot;&gt;make_name_with_suffix_to()&lt;/code&gt; with a stack buffer sized via &lt;code dir=&quot;auto&quot;&gt;MAX_NAME_WITH_SUFFIX_SIZE&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;helpers.h&lt;/code&gt;.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18828&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18828&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WiFi&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;WiFiComponent::wifi_ssid()&lt;/code&gt; removed. Use the heap-free &lt;code dir=&quot;auto&quot;&gt;wifi_ssid_to()&lt;/code&gt;.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18378&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18378&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;EthernetComponent::get_eth_mac_address_pretty()&lt;/code&gt; removed. Use
&lt;code dir=&quot;auto&quot;&gt;get_eth_mac_address_pretty_into_buffer()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18379&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18379&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;ModbusDevice::waiting_for_response()&lt;/code&gt; removed. Use &lt;code dir=&quot;auto&quot;&gt;ready_for_immediate_send()&lt;/code&gt;.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18381&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18381&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;queue_pdu()&lt;/code&gt; refuses PDUs with the exception bit (0x80) set; receive parsers treat every 0x80-set
response as the 2-byte spec exception shape; the “no device accepted broadcast” warning is removed; management
codes 0x07/0x0B/0x0C/0x11 may now be broadcast. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18847&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18847&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: New compile-time register decoder &lt;code dir=&quot;auto&quot;&gt;registers_to_value&amp;#x3C;VALUE_TYPE&gt;()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;registers_to_uint32()&lt;/code&gt; in
&lt;code dir=&quot;auto&quot;&gt;modbus_helpers.h&lt;/code&gt;; &lt;code dir=&quot;auto&quot;&gt;registers_to_number()&lt;/code&gt; unchanged. &lt;a href=&quot;https://github.com/esphome/esphome/pull/18863&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18863&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;ModbusCommandItem&lt;/code&gt;, its factories, &lt;code dir=&quot;auto&quot;&gt;queue_command()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;unqueue_command()&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;on_write_register_response()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;FunctionCode::CUSTOM&lt;/code&gt; are deprecated (removed in 2027.3.0). Migrate one-shot
writes to the entity write helpers (&lt;code dir=&quot;auto&quot;&gt;WriterDevice&lt;/code&gt;) or the &lt;code dir=&quot;auto&quot;&gt;modbus_client&lt;/code&gt; actions.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18071&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18071&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus Controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;SensorItem::register_count&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;SensorItem::force_new_range&lt;/code&gt; are removed; every platform
constructor loses its &lt;code dir=&quot;auto&quot;&gt;register_count&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;force_new_range&lt;/code&gt; parameters (replaced by &lt;code dir=&quot;auto&quot;&gt;entity_count()&lt;/code&gt; and
&lt;code dir=&quot;auto&quot;&gt;reuse_previous_range&lt;/code&gt;). &lt;a href=&quot;https://github.com/esphome/esphome/pull/18085&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18085&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Server IDF&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;AsyncWebServerRequest::url()&lt;/code&gt; removed. Use &lt;code dir=&quot;auto&quot;&gt;url_to()&lt;/code&gt;.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18382&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18382&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;/strong&gt;: On-device POSIX TZ string parser removed; &lt;code dir=&quot;auto&quot;&gt;set_timezone()&lt;/code&gt; overloads and &lt;code dir=&quot;auto&quot;&gt;RealTimeClock::apply_timezone_()&lt;/code&gt;
are gone. The &lt;code dir=&quot;auto&quot;&gt;GetTimeResponse.timezone&lt;/code&gt; proto field is marked deprecated and is no longer decoded. Set &lt;code dir=&quot;auto&quot;&gt;timezone:&lt;/code&gt;
in YAML or let Home Assistant push the pre-parsed timezone.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18383&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18383&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;UARTDevice::check_uart_settings()&lt;/code&gt; is deprecated (removed in 2027.3.0). Use
&lt;code dir=&quot;auto&quot;&gt;uart.final_validate_device_schema()&lt;/code&gt; in your component’s Python &lt;code dir=&quot;auto&quot;&gt;FINAL_VALIDATE_SCHEMA&lt;/code&gt; instead.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18940&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18940&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;USB UART&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;USBUartChannel&lt;/code&gt; is now a &lt;code dir=&quot;auto&quot;&gt;final&lt;/code&gt; concrete type deriving from a new &lt;code dir=&quot;auto&quot;&gt;USBUartChannelBase&lt;/code&gt;; subclass
the base if you need to extend channel behaviour. &lt;a href=&quot;https://github.com/esphome/esphome/pull/17472&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17472&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mitsubishi CN105&lt;/strong&gt;: All leaf configurable classes and actions (&lt;code dir=&quot;auto&quot;&gt;MitsubishiCN105Component&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;MitsubishiCN105Climate&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;MitsubishiCN105VerticalVaneDirectionSelect&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SetRemoteTemperatureAction&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;ClearRemoteTemperatureAction&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;VaneControlAction&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;LegacySetRemoteTemperatureAction&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;LegacyClearRemoteTemperatureAction&lt;/code&gt;) are marked &lt;code dir=&quot;auto&quot;&gt;final&lt;/code&gt; and can no longer be subclassed.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18272&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18272&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 IDF&lt;/strong&gt;: The default IDF component exclusion list grew significantly. External components that include
headers from &lt;code dir=&quot;auto&quot;&gt;app_trace&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;console&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp-tls&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_driver_cam&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_driver_gptimer&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_driver_i2c&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;esp_driver_ledc&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_driver_sdio&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_driver_sdm&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_driver_sdmmc&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_driver_sdspi&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;json&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;protobuf-c&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;rt&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sdmmc&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;tcp_transport&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;bt&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_coex&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_hal_ieee802154&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_phy&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_wifi&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;ieee802154&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;wpa_supplicant&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_gdbstub&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esp_http_server&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;nvs_sec_provider&lt;/code&gt; must call
&lt;code dir=&quot;auto&quot;&gt;esp32.include_builtin_idf_component(&quot;&amp;#x3C;name&gt;&quot;)&lt;/code&gt; in &lt;code dir=&quot;auto&quot;&gt;to_code&lt;/code&gt; (or users can add them under
&lt;code dir=&quot;auto&quot;&gt;esp32: framework: advanced: include_builtin_idf_components:&lt;/code&gt;).
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18536&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18536&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18599&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18599&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18604&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18604&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18748&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18748&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 IDF&lt;/strong&gt;: The mbedTLS root certificate bundle is no longer built unless a component asks for it. External
components that call &lt;code dir=&quot;auto&quot;&gt;esp_crt_bundle_attach()&lt;/code&gt; must call &lt;code dir=&quot;auto&quot;&gt;esp32.require_certificate_bundle()&lt;/code&gt; in &lt;code dir=&quot;auto&quot;&gt;to_code&lt;/code&gt; (or
guard the call with &lt;code dir=&quot;auto&quot;&gt;#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE&lt;/code&gt;).
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18747&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18747&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the
&lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.9.0/&quot;&gt;full 2026.9.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2026.8.0: Bluetooth on more chips than ever</title><link>https://esphome.io/blog/2026/08/19/esphome-2026-8/</link><guid isPermaLink="true">https://esphome.io/blog/2026/08/19/esphome-2026-8/</guid><description>ESPHome 2026.8.0 brings Bluetooth to more chips, dramatically faster builds, Ethernet and WiFi together, a major Modbus overhaul, and more.</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/bk72xx_ble/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bluetooth.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;BK7​2​xx ​BLE&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/bk72xx_ble_tracker/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bluetooth.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;BK7​2​xx ​BLE ​Tracker&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/ln882h_ble/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bluetooth.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LN8​8​2​H ​BLE&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/ln882h_ble_tracker/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bluetooth.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LN8​8​2​H ​BLE ​Tracker&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/rp2_ble_tracker/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bluetooth.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;RP2​ ​BLE ​Tracker&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/one_wire/ds248x/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ds248x.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;DS2​4​8​x&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/ld6002b/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ld6002b.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LD6​0​0​2​B&lt;/div&gt;&lt;div&gt;Motion ​&amp;#x26;​ ​Presence&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/cover/hoermann_hcp/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/hoermann_logo.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Hö​rmann ​Cover&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/output/zephyr_pwm/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/pwm.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Zephyr ​PWM&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/modbus_client/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/modbus.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Modbus ​Client&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;the-esphome-starter-kit-is-here&quot;&gt;The ESPHome Starter Kit Is Here&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Before we get to what’s new in this release: the &lt;a href=&quot;https://esphome.io/starter-kit/&quot;&gt;ESPHome Starter Kit&lt;/a&gt; is now available. It’s the
easiest way to start building your own smart home devices, with no soldering, breadboarding, or coding required.
Read the &lt;a href=&quot;https://esphome.io/blog/2026/08/12/the-esphome-starter-kit-is-here/&quot;&gt;announcement post&lt;/a&gt; for the full story, or head to the
&lt;a href=&quot;https://esphome.io/starter-kit/&quot;&gt;Starter Kit page&lt;/a&gt; to see what’s in the box and to get yours.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.8.0 brings Bluetooth to more chips than ever: a new platform-neutral BLE layer moves all 39 BLE
sensor platforms off their ESP32-only foundation and powers new BLE trackers, and Bluetooth Proxy, on the
Raspberry Pi Pico W, BK72xx and LN882H. Builds get dramatically faster with ccache support on ESP8266, LibreTiny,
RP2040 and host, ESP-IDF toolchain installs shrink by roughly half, and ESP32 crash reports now capture the
faulting address. The release also delivers multi-interface networking with Ethernet and WiFi in one config, a
major Modbus overhaul with the new &lt;code dir=&quot;auto&quot;&gt;modbus_client&lt;/code&gt; component, multi-key OTA signature verification, and runtime
wake word management, alongside new components including the LD6002B 60 GHz presence radar and Hörmann garage
door support. The bundled Device Builder brings faster startup, parallel uploads, and one-click config
migration. The beta cycle also fixed ESP32 BLE trackers and proxies missing advertisements alongside WiFi on
ESP-IDF 5.5.5, and encrypted API connections and OTA uploads on ESP8266 that stalled for seconds now complete in
well under one second.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;If you set &lt;code dir=&quot;auto&quot;&gt;esp32_ble_id&lt;/code&gt; explicitly on any BLE sensor platform, rename it to &lt;code dir=&quot;auto&quot;&gt;ble_hub_id&lt;/code&gt; (the old key warns
until 2027.2.0)&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;voc&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;nox&lt;/code&gt; sensor keys on &lt;code dir=&quot;auto&quot;&gt;sgp4x&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sen5x&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;sen6x&lt;/code&gt;, rename them to &lt;code dir=&quot;auto&quot;&gt;voc_index&lt;/code&gt; and
&lt;code dir=&quot;auto&quot;&gt;nox_index&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;command_throttle&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt;, move the setting to &lt;code dir=&quot;auto&quot;&gt;turnaround_time&lt;/code&gt; on the &lt;code dir=&quot;auto&quot;&gt;modbus&lt;/code&gt;
component; &lt;code dir=&quot;auto&quot;&gt;allow_duplicate_commands&lt;/code&gt; no longer has any effect&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;modbus_server&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;address: 0&lt;/code&gt;, assign a unique address from 1-247 instead&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; sensors with &lt;code dir=&quot;auto&quot;&gt;custom_command: [0x17, ...]&lt;/code&gt;, subtract one from their &lt;code dir=&quot;auto&quot;&gt;offset:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you write &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; lambdas, note &lt;code dir=&quot;auto&quot;&gt;data&lt;/code&gt; is now &lt;code dir=&quot;auto&quot;&gt;std::span&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;payload_to_number()&lt;/code&gt; returns an
optional, so add &lt;code dir=&quot;auto&quot;&gt;.value_or(0)&lt;/code&gt; or a check&lt;/li&gt;
&lt;li&gt;If you use the &lt;code dir=&quot;auto&quot;&gt;aqi&lt;/code&gt; sensor, expect readings above the previous caps (&lt;code dir=&quot;auto&quot;&gt;301&lt;/code&gt; US AQI, &lt;code dir=&quot;auto&quot;&gt;101&lt;/code&gt; CAQI) to report real
interpolated values during heavy pollution&lt;/li&gt;
&lt;li&gt;If you use an &lt;code dir=&quot;auto&quot;&gt;rc522_i2c&lt;/code&gt; reader that relied on the old default address, set &lt;code dir=&quot;auto&quot;&gt;address: 0x2C&lt;/code&gt; explicitly&lt;/li&gt;
&lt;li&gt;If you use LVGL animations with &lt;code dir=&quot;auto&quot;&gt;ease_in&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;ease_out&lt;/code&gt; weights greater than 1.0, remove them; they are now
rejected at validation&lt;/li&gt;
&lt;li&gt;If you have a custom web server frontend or integration, update it for the new &lt;code dir=&quot;auto&quot;&gt;id&lt;/code&gt; format and the
&lt;code dir=&quot;auto&quot;&gt;alarm_control_panel&lt;/code&gt; domain spelling&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;pin: TEMPERATURE&lt;/code&gt; on the &lt;code dir=&quot;auto&quot;&gt;adc&lt;/code&gt; sensor for the RP2 on-die sensor, migrate to the
&lt;code dir=&quot;auto&quot;&gt;internal_temperature&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;If your automations relied on non-iBeacon Apple manufacturer payloads being parsed as iBeacons, note these no
longer match&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;rgb_order&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;is_rgbw&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;is_wrgb&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;esp32_rmt_led_strip&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;beken_spi_led_strip&lt;/code&gt; or
&lt;code dir=&quot;auto&quot;&gt;rp2040_pio_led_strip&lt;/code&gt;, switch to the single &lt;code dir=&quot;auto&quot;&gt;channel_colors&lt;/code&gt; key (the old keys warn until 2027.3.0)&lt;/li&gt;
&lt;li&gt;If you set &lt;code dir=&quot;auto&quot;&gt;inverted: true&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;allow_other_uses: true&lt;/code&gt; on an &lt;code dir=&quot;auto&quot;&gt;interrupt_pin&lt;/code&gt; for &lt;code dir=&quot;auto&quot;&gt;pcf8574&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pca9554&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;tca9555&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pca6416a&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pi4ioe5v6408&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;mcp23016&lt;/code&gt;, remove them; both are now rejected at validation&lt;/li&gt;
&lt;/ul&gt;


&lt;div&gt;&lt;h2 id=&quot;bluetooth-on-more-chips-platform-neutral-ble&quot;&gt;Bluetooth on More Chips: Platform-Neutral BLE&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt; across dozens of PRs, this release completes a major architectural
effort: the shared BLE advertisement layer moved out of &lt;code dir=&quot;auto&quot;&gt;esp32_ble_tracker&lt;/code&gt; into a new platform-neutral
&lt;code dir=&quot;auto&quot;&gt;ble_device_base&lt;/code&gt; component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17150&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17150&lt;/a&gt;), and every one of the 39
advertisement-based BLE sensor platforms was migrated onto it in a 13-batch series
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17716&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17716&lt;/a&gt; through
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18183&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18183&lt;/a&gt;). BLE sensors like &lt;code dir=&quot;auto&quot;&gt;ble_rssi&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;atc_mithermometer&lt;/code&gt;,
BTHome, Mopeka, RuuviTag and the entire Xiaomi family are no longer tied to ESP32; they work on any chip with a
BLE tracker.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New BLE trackers this release:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi Pico W / Pico 2 W&lt;/strong&gt; - the new &lt;a href=&quot;https://esphome.io/components/rp2_ble_tracker/&quot;&gt;rp2_ble_tracker&lt;/a&gt; scans passively
and actively while WiFi holds an API connection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BK72xx (Beken)&lt;/strong&gt; - &lt;a href=&quot;https://esphome.io/components/bk72xx_ble_tracker/&quot;&gt;bk72xx_ble_tracker&lt;/a&gt; by
&lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt; brings BLE 5.x scanning to the chips inside many Tuya-based
wall switches, thermostats and smart plugs, validated in production on a 20-device fleet&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LN882H&lt;/strong&gt; - &lt;a href=&quot;https://esphome.io/components/ln882h_ble_tracker/&quot;&gt;ln882h_ble_tracker&lt;/a&gt; by
&lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt; adds BLE 5.1 scanning with scan-response merging on LibreTiny
LN882H devices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Bluetooth Proxy beyond ESP32:&lt;/strong&gt; &lt;a href=&quot;https://esphome.io/components/bluetooth_proxy/&quot;&gt;bluetooth_proxy&lt;/a&gt; now consumes the neutral layer
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17880&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17880&lt;/a&gt;), so more chips can feed advertisements to Home
Assistant. The Pico W goes further: it supports full active connections
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18132&lt;/a&gt;) and now offers 3 connection slots with ESP32 parity
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18247&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18247&lt;/a&gt;), so Home Assistant can read, write and subscribe to
BLE devices through a Pico W proxy. BK72xx gained active scanning by packing the vendor SDK’s start command
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18169&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18169&lt;/a&gt;), which admitted it to Bluetooth Proxy as well.&lt;/p&gt;
&lt;p&gt;One config note: on migrated sensor platforms the auto-generated tracker reference key &lt;code dir=&quot;auto&quot;&gt;esp32_ble_id:&lt;/code&gt; is now
&lt;code dir=&quot;auto&quot;&gt;ble_hub_id:&lt;/code&gt;. Most configs never set it explicitly; those that do keep validating with a warning until
2027.2.0. See the Breaking Changes section for details.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESP32 scan window with WiFi:&lt;/strong&gt; ESP-IDF 5.5.5 fixed a coexistence bug that made BLE scans run far longer than
the configured window, and the default 30 ms window in a 320 ms interval had been relying on it; with the fix the
scanner listened only 9.4% of the time and trackers and proxies missed most advertisements alongside WiFi from
2026.7.1 on. With WiFi coexistence on ESP-IDF 5.5.5 or newer the
&lt;a href=&quot;https://esphome.io/components/esp32_ble_tracker/&quot;&gt;esp32_ble_tracker&lt;/a&gt; &lt;code dir=&quot;auto&quot;&gt;window&lt;/code&gt; now defaults to the &lt;code dir=&quot;auto&quot;&gt;interval&lt;/code&gt;, as Espressif
recommends; an explicit &lt;code dir=&quot;auto&quot;&gt;window&lt;/code&gt; is never changed (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18356&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18356&lt;/a&gt;).
&lt;code dir=&quot;auto&quot;&gt;bk72xx_ble&lt;/code&gt; also stops code generation with a clear message on Beken chips without a BLE 5.x stack (BK7231T,
BK7251, BK7231Q) instead of failing minutes into the build (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18406&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18406&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esphome-device-builder&quot;&gt;ESPHome Device Builder&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This section covers everything that changed in the bundled
&lt;a href=&quot;https://github.com/esphome/device-builder&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Device Builder&lt;/a&gt; since the 2026.7.0 release notes. Device Builder
updates also ship in ESPHome patch releases for as long as the changes remain safe to include, so some of what
follows already reached you during the 2026.7.x cycle; the rest is new with this release.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Faster Startup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;On a small host with a lot of devices, the dashboard used to finish scanning every configuration before it would serve
its first page. It now serves immediately from a shallow device scan and fills in the details in the background
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2514&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2514&lt;/a&gt;), and work not needed to serve that first page, from
preferences loading to MQTT broker discovery, moved off the startup critical path or got cheaper
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2500&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2500&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2501&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2501&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2503&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2503&lt;/a&gt;). The validated-config cache is also read in the new JSON
format ESPHome 2026.8 writes, so upgrading does not throw the cache away
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2517&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2517&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;More Updates at Once&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Updates used to upload to one device at a time. Uploads now run in parallel: four at a time, and up to nine when the
Device Builder is running ESPHome 2026.8 or newer, whose leaner CLI fast paths keep that many upload subprocesses
cheap (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2206&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2206&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2515&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2515&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2518&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2518&lt;/a&gt;). Queued offline updates benefit the most: a batch of
&lt;a href=&quot;https://esphome.io/components/deep_sleep/&quot;&gt;deep sleep&lt;/a&gt; devices waking around the same time collect their queued updates concurrently
instead of queueing behind one another (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2192&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2192&lt;/a&gt;), a freshly
flashed deep-sleep device gets its new version read in a quick burst before it goes back to sleep
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2146&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2146&lt;/a&gt;), and the install dialog follows the flash that happens
when the device wakes, so you can watch a queued update land
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1616&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1616&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One-Click Config Migration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ESPHome renames configuration keys from time to time, and keeping up has been a manual chore. The Device Builder can
now migrate a configuration for you: when a config contains something with a known migration, the editor offers to
apply it, and the offer is backed by a backend dry run so it only appears when the migration will actually succeed
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2432&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2432&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1538&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1538&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1550&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1550&lt;/a&gt;). The rules are discovered from the live
ESPHome schema rather than hand-maintained, covering renamed keys and component aliases
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2444&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2444&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2462&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2462&lt;/a&gt;), the &lt;code dir=&quot;auto&quot;&gt;rp2040&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;rp2&lt;/code&gt; platform rename
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2460&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2460&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2463&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2463&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1567&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1567&lt;/a&gt;), and the legacy &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; services
spelling, which is read on load and respelled to the canonical form on write
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2420&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2420&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1534&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1534&lt;/a&gt;). Newest of all, a device whose config
has a pending migration shows a dot on its card and table row, and clicking it opens the editor to apply the migration
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2563&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2563&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1652&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1652&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1653&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1653&lt;/a&gt;). The offer now names each change it
will make and shows a preview (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1662&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1662&lt;/a&gt;),
only proposes migrations the installed ESPHome supports
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2602&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2602&lt;/a&gt;), and covers the LED strip &lt;code dir=&quot;auto&quot;&gt;channel_colors&lt;/code&gt; rename
introduced in this release (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2585&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2585&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2596&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2596&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2600&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2600&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Structured Editor Rounds Out&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The structured editor spent this cycle learning to leave your file alone. Editing through the forms now preserves the
comments and flow style of the YAML it touches
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1377&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1377&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1380&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1380&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1383&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1383&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1386&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1386&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1387&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1387&lt;/a&gt;), and &lt;code dir=&quot;auto&quot;&gt;${substitution}&lt;/code&gt; references
render and stay editable in pin and numeric fields instead of being clobbered by the widget
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1342&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1342&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1344&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1344&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1347&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1347&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1511&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1511&lt;/a&gt;). Lambdas on templatable fields are no
longer flagged as invalid (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1529&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1529&lt;/a&gt;), and an
automation using an action the catalog does not know stays editable, rendering that one action read-only in place
instead of locking you out of the whole automation
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2351&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2351&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1513&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1513&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The pin field gained guided wiring presets that show where to connect the part
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1412&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1412&lt;/a&gt;), and boards whose hardware fixes a pin
lock the GPIO select to it (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1419&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1419&lt;/a&gt;). The
add-component dialog handles dependency chains as a stack of detours, so adding a component that needs a bus walks you
through creating the bus and returns you to where you were
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1586&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1586&lt;/a&gt;), detours to a new &lt;code dir=&quot;auto&quot;&gt;uart&lt;/code&gt; when no
existing bus can host the component (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1554&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1554&lt;/a&gt;),
and prefills entity names and unique IDs
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1552&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1552&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1553&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1553&lt;/a&gt;). The YAML hints from 2026.7.0 grew new
one-click fixes: an empty or commented-out block behind &lt;code dir=&quot;auto&quot;&gt;expected a dictionary&lt;/code&gt; is named and fixed for you
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1314&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1314&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1316&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1316&lt;/a&gt;), and a stray top-level key that belongs
to the section above it is offered an indent fix
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1319&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1319&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting and Crash Reporting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The status badges on a device now open a connectivity troubleshooting dialog, which runs an on-demand probe from the
Device Builder to the device and reports what worked and what did not
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2485&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2485&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1597&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1597&lt;/a&gt;). Reporting problems got easier too: the
bug report flow gained an optional device picker that attaches the selected device’s configuration with credentials
masked (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1595&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1595&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1591&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1591&lt;/a&gt;), crash reports are titled by where the
crash happened (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1584&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1584&lt;/a&gt;), and the log viewer
gained a crash report button (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1250&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1250&lt;/a&gt;). Crashes
captured over Web Serial have their backtraces decoded
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2105&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2105&lt;/a&gt;), including firmware compiled by a build server, through
a hosted decoder (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2140&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2140&lt;/a&gt;), and Web Serial installs surface
esptool-js connect diagnostics in the install log
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1651&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1651&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Status You Can Trust&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A run of work went into making Online, Offline, and the deployed version mean what they say. mDNS ownership now
requires live evidence and honors goodbye packets, so a stale record can no longer keep a dead device Online or attach
one device’s identity to another (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2376&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2376&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2386&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2386&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2393&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2393&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2395&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2395&lt;/a&gt;), stale addresses are dropped when a device is retargeted
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2488&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2488&lt;/a&gt;), and the device table’s Version column only shows a
version the Device Builder can actually trust
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1283&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1283&lt;/a&gt;). Renaming or cloning a device
retargets its generated fallback-AP SSID (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2247&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2247&lt;/a&gt;), and MQTT
device discovery now supports TLS brokers (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2256&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2256&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Windows Device Builder had a round of hardening: the ESP-IDF toolchain is shared at a short path so deep build
trees fit inside &lt;code dir=&quot;auto&quot;&gt;MAX_PATH&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2281&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2281&lt;/a&gt;), the compile subprocess
tree runs in UTF-8 mode (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2283&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2283&lt;/a&gt;), cancelling a build actually
stops the running compile (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2554&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2554&lt;/a&gt;), and toolchain subprocesses
can no longer pop blocking “Bad Image” error dialogs
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2569&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2569&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Remote Builds and Home Assistant&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Build servers now advertise a friendly name, which shows up across the UI and in the pairing handshake
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1252&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1252&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2526&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2526&lt;/a&gt;), and while remote building is off the dashboard shows a
neutral &lt;strong&gt;Disabled&lt;/strong&gt; badge with a turn-on action instead of hiding the feature
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1392&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1392&lt;/a&gt;). Imported bundles upload over HTTP
instead of the WebSocket, with a much higher size cap and an actionable error when a bundle still does not fit
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2340&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2340&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2320&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2320&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2324&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2324&lt;/a&gt;), and a dialog following a job reattaches after a
connection loss instead of failing (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1570&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1570&lt;/a&gt;).
Home Assistant adoption gained an encryption-key handoff with adoption key reuse
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2496&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2496&lt;/a&gt;), and a device broadcasting its factory name is adopted
under that name with the rename flow started for you
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1533&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1533&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Beyond the headlines: configuration files are written atomically, so a crash mid-write can no longer leave a partial
file (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2188&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2188&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2190&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2190&lt;/a&gt;), and a &lt;code dir=&quot;auto&quot;&gt;secrets.yaml&lt;/code&gt; with operator-set permissions
keeps them across rewrites (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2202&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2202&lt;/a&gt;). First-time installs are
guided to USB instead of a queued OTA that could never arrive
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1282&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1282&lt;/a&gt;), and the device card’s action buttons
and indicator icons gained tooltips (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1280&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1280&lt;/a&gt;).
&lt;a href=&quot;https://github.com/stvncode&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@stvncode&lt;/a&gt; moved toasts to the bottom-right corner
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1366&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1366&lt;/a&gt;) and refined the quickstart tour and
desktop setup flow (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1334&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1334&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1337&lt;/a&gt;),
&lt;a href=&quot;https://github.com/rwalker777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwalker777&lt;/a&gt; labels compile-only jobs for offline devices as &lt;strong&gt;Offline Compile&lt;/strong&gt;
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1266&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1266&lt;/a&gt;),
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; made ESPHome Web a standalone build target of the frontend
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1139&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1139&lt;/a&gt;),
&lt;a href=&quot;https://github.com/elcaptain&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@elcaptain&lt;/a&gt; put the official monochrome ESPHome logomarks in the header and navigation
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1141&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1141&lt;/a&gt;), and
&lt;a href=&quot;https://github.com/breti&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@breti&lt;/a&gt; kept the UI copy honest across the release
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1409&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1409&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1428&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1428&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1521&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1521&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;faster-builds-and-smaller-toolchain-installs&quot;&gt;Faster Builds and Smaller Toolchain Installs&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Compilation now runs through &lt;code dir=&quot;auto&quot;&gt;ccache&lt;/code&gt; when it is installed on ESP8266, LibreTiny, RP2040 and host builds
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17722&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17722&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17726&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17726&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17727&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17727&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17728&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17728&lt;/a&gt;), matching what ESP-IDF builds already did. The cache is
shared across devices and projects, so a fleet of similar devices compiles almost entirely from cache: in testing,
six Sonoff S31 devices built in 15 seconds for the first and 4 to 5 seconds for each of the rest. Set
&lt;code dir=&quot;auto&quot;&gt;ESPHOME_CCACHE_ENABLE=0&lt;/code&gt; to opt out; &lt;code dir=&quot;auto&quot;&gt;esphome clean-all&lt;/code&gt; removes the cache. A &lt;code dir=&quot;auto&quot;&gt;ccache&lt;/code&gt; on
&lt;code dir=&quot;auto&quot;&gt;PATH&lt;/code&gt; that does not run (a stale shim or a &lt;code dir=&quot;auto&quot;&gt;.bat&lt;/code&gt; wrapper on Windows) is now detected and skipped instead of
failing every compile step (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18407&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18407&lt;/a&gt;), the wrapper path is made
safe for &lt;code dir=&quot;auto&quot;&gt;cmd.exe&lt;/code&gt; so the ccache bundled with ESPHome Desktop works
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18495&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18495&lt;/a&gt;), and framework downloads retry transient network
errors with a short backoff (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18330&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18330&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;ESP-IDF installs also slimmed down considerably:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Only the toolchains for the variants you build&lt;/strong&gt; are installed
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17688&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17688&lt;/a&gt;), roughly halving a fresh install; the RISC-V
toolchain alone is a 292 MB download and 2.0 GB on disk&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The gdb and ULP toolchains&lt;/strong&gt; ESPHome never runs are skipped
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17687&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17687&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool download caches are pruned&lt;/strong&gt; after install (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17661&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17661&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;leaner-and-more-responsive-cli&quot;&gt;Leaner and More Responsive CLI&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A long series of changes trimmed the &lt;code dir=&quot;auto&quot;&gt;esphome upload&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt; fast paths, which matters because the
device builder runs several of these subprocesses concurrently. Imports the fast path never uses are now
deferred (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18093&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18093&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18105&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18105&lt;/a&gt;), and the validated-config cache is stored as JSON so a
cache hit never loads the YAML stack (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18106&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18106&lt;/a&gt;); cache parsing
dropped from 1-2 ms to 0.05 ms and the upload subprocess uses measurably less RAM.&lt;/p&gt;
&lt;p&gt;Log and build output streaming also improved: output flushes live instead of buffering
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18261&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18261&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18264&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18264&lt;/a&gt;), complete lines are no longer held back behind an
unfinished one (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18279&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18279&lt;/a&gt;), and an out-of-flash build now shows the
helpful tip instead of crashing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18280&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18280&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt; can now also tail a device over the &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt; event stream
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17110&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17110&lt;/a&gt;), so a device with &lt;code dir=&quot;auto&quot;&gt;web_server:&lt;/code&gt; but no &lt;code dir=&quot;auto&quot;&gt;api:&lt;/code&gt; can
finally be followed from the CLI. The native API is still preferred, then MQTT, then the web server.&lt;/p&gt;
&lt;p&gt;The beta cycle also removed some stalls. &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt; no longer blocks for up to 25 seconds on MQTT IP
discovery when it already has a usable address; the lookup runs concurrently and feeds any address it finds
into the running client (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18313&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18313&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;esphome upload&lt;/code&gt; retries
network-level OTA failures such as a connect timeout or the device closing the connection mid-handshake, while
device-reported errors still fail immediately (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18332&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18332&lt;/a&gt;). The
component alias map is read from a generated registry instead of scanning all 744 component directories on every
CLI start, the source of a startup regression on slow hosts like the HA Green
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18335&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18335&lt;/a&gt;), and &lt;code dir=&quot;auto&quot;&gt;PYTHONPATH&lt;/code&gt; no longer leaks into build
subprocesses (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18360&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18360&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;better-esp32-crash-reports&quot;&gt;Better ESP32 Crash Reports&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;esp32&lt;/code&gt; crash handler now captures the faulting memory address (EXCVADDR on Xtensa, MTVAL on RISC-V) and the
raw exception cause, so heap corruption and pointer bugs leave a usable trail in the post-reboot report
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17769&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17769&lt;/a&gt;). Crash records are also stamped with the build they
were captured by (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17770&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17770&lt;/a&gt;): a record left over from a previous
firmware is flagged instead of being decoded against the wrong ELF, which used to produce convincing but
meaningless backtraces. The addr2line hint is now one line per core, so decoders no longer merge two unrelated
stacks into one impossible call chain (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18418&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18418&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;ethernet-and-wifi-together-multi-interface-networking&quot;&gt;Ethernet and WiFi Together: Multi-Interface Networking&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Built by &lt;a href=&quot;https://github.com/rwalker777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwalker777&lt;/a&gt; and &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;, ESP32 devices can
now configure both &lt;code dir=&quot;auto&quot;&gt;ethernet:&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;wifi:&lt;/code&gt; in the same YAML. A new &lt;code dir=&quot;auto&quot;&gt;network: priority:&lt;/code&gt; list declares which
interface the device prefers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14255&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14255&lt;/a&gt;), and the default route is
arbitrated at runtime from that list (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17797&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17797&lt;/a&gt;): the first
connected interface in your priority order carries the traffic, DNS follows the active interface, and failover
plus failback happen automatically within milliseconds of a link change. Verified on hardware with cable pulls,
VLAN changes and runtime enable/disable cycles. See &lt;a href=&quot;https://esphome.io/components/network/&quot;&gt;network&lt;/a&gt; for configuration.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp8266-networking-and-stability&quot;&gt;ESP8266 Networking and Stability&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Encrypted API connections took 2.5 to 3.3 seconds to establish on ESP8266, against about 63 ms on ESP32. WiFi
and lwIP run in a cooperative context that only executes when the sketch yields, so a busy main loop let the WiFi
RX queue overflow and TCP stalled on retransmission. Rate-limited yields in the raw TCP read and write paths
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18455&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18455&lt;/a&gt;) and inside the handshake crypto
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18473&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18473&lt;/a&gt;) took a device that stalled on every attempt to 0 stalls
in 24 attempts, with a 357 ms median. OTA uses the same paths and benefits equally. The noise-c library behind
the encrypted API was also bumped from 0.1.11 to 0.1.21 along the way, freeing about 670 bytes of heap per
encrypted connection and making message encryption and decryption 13 to 31% faster in benchmarks
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18451&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18451&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/18482&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18482&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18484&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18484&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Three crash classes are gone as well: a &lt;code dir=&quot;auto&quot;&gt;LoadProhibited&lt;/code&gt; in &lt;code dir=&quot;auto&quot;&gt;cnx_node_search&lt;/code&gt; after a WiFi disconnect, seen on
ratgdo and Athom devices, fixed by taking the STA interface down before lwIP can transmit into the freed driver
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18333&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18333&lt;/a&gt;); watchdog resets from the software serial RX interrupt
posting a main loop wake for every byte, now only when no wake is pending
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18416&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18416&lt;/a&gt;); and a reboot when the captive portal shut down after
WiFi connected, because deleting the web server also deleted the captive portal mid-teardown, which broke Improv
serial provisioning on the esphome-web ESP8266 image and applies to every ESPAsyncWebServer platform (ESP8266,
RP2040, LibreTiny, LN882x) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18324&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18324&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;performance-optimizations&quot;&gt;Performance Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Several components stopped doing busy-work on every loop iteration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;espnow&lt;/strong&gt; no longer polls the WiFi driver every loop and disables its loop entirely while idle
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18027&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18027&lt;/a&gt;); it was one of the most expensive idle components at
0.056 ms per iteration, and its idle cost is now zero&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;script&lt;/strong&gt; components with queued mode stop polling while the queue is empty
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18121&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18121&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;improv_serial&lt;/strong&gt; reduced its per-loop overhead (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16019&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16019&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The blocking-warning log time no longer cascades into false warnings for subsequent components
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17710&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17710&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;modbus-overhaul-continues&quot;&gt;Modbus Overhaul Continues&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt;, the multi-release Modbus rework reached a milestone. The
&lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; message handling was rebuilt (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11781&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11781&lt;/a&gt;):
commands from all controllers now share the hub’s queue fairly (previously some controllers could starve),
responses are routed straight back to the command that sent them so a reply can no longer be applied to the
wrong sensor, offline devices are tracked per device instead of per command, and the common command path is
heap-free. Two controllers may now even share one device address to poll at different intervals.&lt;/p&gt;
&lt;p&gt;A new &lt;a href=&quot;https://esphome.io/components/modbus_client/&quot;&gt;modbus_client&lt;/a&gt; component
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17676&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17676&lt;/a&gt;) enables ad-hoc Modbus transactions straight from YAML
automations, with typed read/write actions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18078&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18078&lt;/a&gt;), a plain
device handle for lambdas (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18146&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18146&lt;/a&gt;), and read/write multiple
registers in one transaction (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18215&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18215&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Server mode grew too, with contributions from &lt;a href=&quot;https://github.com/zweckj&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@zweckj&lt;/a&gt; and
&lt;a href=&quot;https://github.com/marpi82&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@marpi82&lt;/a&gt;: coil and discrete-input support
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17464&lt;/a&gt;), read/write multiple registers (function code 0x17,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17357&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17357&lt;/a&gt;), spec-compliant broadcast writes
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17387&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17387&lt;/a&gt;) and byte-swapped word types
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17829&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17829&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Note that &lt;code dir=&quot;auto&quot;&gt;command_throttle&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;allow_duplicate_commands&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; are deprecated and no longer
have any effect; use &lt;code dir=&quot;auto&quot;&gt;turnaround_time&lt;/code&gt; on the &lt;code dir=&quot;auto&quot;&gt;modbus&lt;/code&gt; hub instead. See Breaking Changes for migration details.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;multi-key-ota-signature-verification&quot;&gt;Multi-Key OTA Signature Verification&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For externally signed firmware, &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; added ESPHome-side OTA signature verification
with a compiled-in trusted key list (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17981&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17981&lt;/a&gt;). An update is
accepted if any of up to three signature blocks matches a trusted key, which enables signing key rotation
(dual-sign a bridge release with old and new keys) and independent backup keys across signing providers.
Bootloader updates are now signature-checked as well, closing a path where they previously installed unverified.
See the &lt;a href=&quot;https://esphome.io/components/esp32/#signed-ota-verification&quot;&gt;Signed OTA Verification documentation&lt;/a&gt; for setup.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;voice-and-media&quot;&gt;Voice and Media&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; landed the groundwork for wake words that are not baked into firmware:
&lt;a href=&quot;https://esphome.io/components/micro_wake_word/&quot;&gt;micro_wake_word&lt;/a&gt; can now add and remove wake word models at runtime
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17927&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17927&lt;/a&gt;). Models load into PSRAM with validation, the &lt;code dir=&quot;auto&quot;&gt;models&lt;/code&gt;
option is now optional, and a follow-up voice assistant integration will download models advertised by Home
Assistant.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://esphome.io/components/sendspin/&quot;&gt;sendspin&lt;/a&gt; media player gained an image platform for album and artist artwork
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17937&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17937&lt;/a&gt;): artwork decodes into double-buffered frames a display
or LVGL can draw, with optional cross-fade transitions.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-components&quot;&gt;New Components&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/ld6002b/&quot;&gt;ld6002b&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/hepter&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@hepter&lt;/a&gt;, built across 5 PRs
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17819&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17819&lt;/a&gt; onward): the Hi-Link HLK-LD6002B 60 GHz 3D presence
radar, with per-target position tracking, configurable detection zones, interference areas, sensitivity and
power management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/cover/hoermann_hcp/&quot;&gt;hoermann_hcp&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/zweckj&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@zweckj&lt;/a&gt;: controls Hörmann garage
door motors over the HCP bus, with cover control
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17355&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17355&lt;/a&gt;), garage light
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18190&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18190&lt;/a&gt;) and a connectivity sensor
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18189&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18189&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/one_wire/ds248x/&quot;&gt;ds248x&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/tomwellnitz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomwellnitz&lt;/a&gt;: DS2482-100/-101/-800 and
DS2484 I²C-to-1-Wire bridges as a &lt;code dir=&quot;auto&quot;&gt;one_wire&lt;/code&gt; platform, so Dallas temperature sensors can hang off up to 8
bridged channels (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12717&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12717&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/output/zephyr_pwm/&quot;&gt;zephyr_pwm&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/wiomoc&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@wiomoc&lt;/a&gt;: PWM outputs on nRF52
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16483&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/modbus_client/&quot;&gt;modbus_client&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt;, covered in the
Modbus section above&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-hardware-support&quot;&gt;New Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CH390 SPI Ethernet&lt;/strong&gt; by &lt;a href=&quot;https://github.com/ptr727&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ptr727&lt;/a&gt;: the WCH CH390 single-chip 10/100 MAC and PHY
joins the &lt;a href=&quot;https://esphome.io/components/ethernet/&quot;&gt;ethernet&lt;/a&gt; component, verified at 100 Mbps full duplex
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18226&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18226&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Displays&lt;/strong&gt;: the JC8012P4A1-V2 panel revision for &lt;a href=&quot;https://esphome.io/components/display/mipi_dsi/&quot;&gt;mipi_dsi&lt;/a&gt; by
&lt;a href=&quot;https://github.com/rayz90&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rayz90&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17457&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17457&lt;/a&gt;), the Waveshare
ESP32-S3-Touch-LCD-3.5B (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17513&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17513&lt;/a&gt;) and the ST77916-based
ESP-VoCat round display by &lt;a href=&quot;https://github.com/rggammon&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rggammon&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17679&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17679&lt;/a&gt;) for &lt;a href=&quot;https://esphome.io/components/display/mipi_spi/&quot;&gt;mipi_spi&lt;/a&gt;, the
Guition JC8012P4A1 touchscreen for &lt;a href=&quot;https://esphome.io/components/touchscreen/gsl3670/&quot;&gt;gsl3670&lt;/a&gt; by
&lt;a href=&quot;https://github.com/mpoettgen&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mpoettgen&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17843&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17843&lt;/a&gt;), and the
7-color Soldered Inkplate 6COLOR e-paper by &lt;a href=&quot;https://github.com/franFodor&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@franFodor&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17717&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17717&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenThread diagnostics&lt;/strong&gt; by &lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt;: 13 new numeric sensors exposing MAC and
MLE counters plus parent link quality and RSSI (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17276&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17276&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Addressable LED channel order&lt;/strong&gt; by &lt;a href=&quot;https://github.com/peterkeen&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@peterkeen&lt;/a&gt; and
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;: &lt;a href=&quot;https://esphome.io/components/light/esp32_rmt_led_strip/&quot;&gt;esp32_rmt_led_strip&lt;/a&gt;,
&lt;a href=&quot;https://esphome.io/components/light/beken_spi_led_strip/&quot;&gt;beken_spi_led_strip&lt;/a&gt; and
&lt;a href=&quot;https://esphome.io/components/light/rp2040_pio_led_strip/&quot;&gt;rp2040_pio_led_strip&lt;/a&gt; now describe their channel layout with a single
&lt;code dir=&quot;auto&quot;&gt;channel_colors&lt;/code&gt; key, any permutation of &lt;code dir=&quot;auto&quot;&gt;R&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;G&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;B&lt;/code&gt; with an optional &lt;code dir=&quot;auto&quot;&gt;W&lt;/code&gt; anywhere (&lt;code dir=&quot;auto&quot;&gt;GRBW&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;WRGB&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;RWGB&lt;/code&gt;),
replacing &lt;code dir=&quot;auto&quot;&gt;rgb_order&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;is_rgbw&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;is_wrgb&lt;/code&gt;; the RP2040 strip gains white-channel positioning as a result,
and the old keys keep working with a warning naming the replacement until 2027.3.0
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18028&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18028&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/18474&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18474&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Haier short IR messages&lt;/strong&gt; for &lt;a href=&quot;https://esphome.io/components/remote_transmitter/&quot;&gt;remote_transmitter&lt;/a&gt; and
&lt;a href=&quot;https://esphome.io/components/remote_receiver/&quot;&gt;remote_receiver&lt;/a&gt; by &lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17826&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17826&lt;/a&gt;), and configurable I2S PDM microphone downsampling by
&lt;a href=&quot;https://github.com/egormanga&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@egormanga&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17751&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17751&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;other-notable-features&quot;&gt;Other Notable Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deep sleep wake automations&lt;/strong&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;: the new &lt;code dir=&quot;auto&quot;&gt;on_wake&lt;/code&gt; trigger on
&lt;a href=&quot;https://esphome.io/components/deep_sleep/&quot;&gt;deep_sleep&lt;/a&gt; fires when the device wakes with the wake cause, and each
&lt;code dir=&quot;auto&quot;&gt;esp32_ext1_wakeup&lt;/code&gt; pin can carry its own &lt;code dir=&quot;auto&quot;&gt;on_wake&lt;/code&gt; so different wake buttons perform different actions
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17569&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17569&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mitsubishi CN105 vane control&lt;/strong&gt; by &lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt;: the component gained a top-level
hub, a vertical vane direction select, a vane state trigger and a &lt;code dir=&quot;auto&quot;&gt;vane.control&lt;/code&gt; action
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16987&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16987&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16723&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16723&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16727&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16727&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16737&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16737&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LVGL&lt;/strong&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;: runtime theme updates via &lt;code dir=&quot;auto&quot;&gt;lvgl.theme.update&lt;/code&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17678&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17678&lt;/a&gt;), widget stacking control via
&lt;code dir=&quot;auto&quot;&gt;lvgl.widget.set_z_index&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17993&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17993&lt;/a&gt;), and a &lt;code dir=&quot;auto&quot;&gt;pause&lt;/code&gt; option for
&lt;code dir=&quot;auto&quot;&gt;round_trip&lt;/code&gt; animations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17574&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17574&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AQI over-range handling&lt;/strong&gt; by &lt;a href=&quot;https://github.com/jasstrong&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jasstrong&lt;/a&gt;: hazardous air quality now
interpolates correctly across 301-500 instead of pinning at 301, with a new &lt;code dir=&quot;auto&quot;&gt;extended_range&lt;/code&gt; option to
extrapolate beyond 500 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17570&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17570&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zigbee improvements&lt;/strong&gt; by &lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; and
&lt;a href=&quot;https://github.com/TesseractTimmee&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@TesseractTimmee&lt;/a&gt;: an &lt;code dir=&quot;auto&quot;&gt;on_start&lt;/code&gt; automation, automatic rejoin after
network failure, leave-on-factory-reset, sensor resolution attributes and more units
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18009&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18009&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18008&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18008&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17973&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17973&lt;/a&gt;); esp-zigbee-sdk is bumped to 2.0.4, which lets the
coordinator remove an end device that is not its direct child and has routers send an explicit rejoin request
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18415&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18415&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CC1101 tuning options&lt;/strong&gt; by &lt;a href=&quot;https://github.com/hn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@hn&lt;/a&gt;: frequency offset compensation and bit
synchronization registers are now configurable from YAML for narrowband protocols like wM-Bus
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17577&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17577&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus garage doors and more&lt;/strong&gt; covered in the Modbus section above&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;notable-bug-fixes&quot;&gt;Notable Bug Fixes&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32-P4&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;variant: esp32p4&lt;/code&gt; without a &lt;code dir=&quot;auto&quot;&gt;board:&lt;/code&gt; built the pre-v3 bootloader layout since 2026.7.0 and
bootlooped on production (v3.x) silicon; the production layout is now the default, with &lt;code dir=&quot;auto&quot;&gt;engineering_sample&lt;/code&gt;
still available for pre-release chips (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18500&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18500&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;image&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;defaults:&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;files:&lt;/code&gt; work again on &lt;code dir=&quot;auto&quot;&gt;image:&lt;/code&gt; platform entries (&lt;code dir=&quot;auto&quot;&gt;file&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;animation&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;online_image&lt;/code&gt;) to share options across several images, not only through the legacy format migration
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18032&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18032&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ld2420&lt;/strong&gt;: An unknown command error from the radar indexed past a three-entry message table and caused a boot
loop (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18322&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18322&lt;/a&gt;), and the component no longer shares the UART
bus setup priority, which could run its setup before the bus was ready and leave the bus dead on ESP-IDF
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18428&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18428&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus custom commands&lt;/strong&gt;: Responses with a function code outside the user-defined ranges (65-72 and 100-110),
such as the &lt;code dir=&quot;auto&quot;&gt;0x49&lt;/code&gt; used by Sofar inverters, were dropped as parse failures since 2026.7 because only user-defined
codes fell back to the CRC scan for the frame end. Every function code of unknown length is now CRC-scanned, and
a server hub answers such a request with &lt;code dir=&quot;auto&quot;&gt;ILLEGAL_FUNCTION&lt;/code&gt; instead of silence
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18483&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensor delta filter&lt;/strong&gt;: NaN passes through again, so a &lt;code dir=&quot;auto&quot;&gt;timeout:&lt;/code&gt; filter followed by &lt;code dir=&quot;auto&quot;&gt;delta:&lt;/code&gt; marks the sensor
unavailable instead of holding the last valid reading forever; this had been lost in 2026.2.0
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18400&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18400&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entity keys&lt;/strong&gt;: The beta hashed API entity keys from the raw name, which made Home Assistant recreate every
entity on first connect and drop helpers tied to them. Keys are back to the sanitized object ID hash for this
release; the config-time duplicate check is kept (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18361&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18361&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rotary_encoder&lt;/strong&gt;: The reset pin now sets &lt;code dir=&quot;auto&quot;&gt;min_value&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt; when the minimum is above zero
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18197&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18197&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;esp32_ble&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;LOCAL_IR&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;LOCAL_ER&lt;/code&gt; GAP events the stack raises on first boot after a flash no longer
log an “unexpected GAP event” warning (&lt;a href=&quot;https://github.com/esphome/esphome/pull/18359&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18359&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cv.parse_esphome_version&lt;/strong&gt;: Restored as a deprecated helper after its removal broke external components that
call it; it warns and points at &lt;code dir=&quot;auto&quot;&gt;cv.require_esphome_version&lt;/code&gt;, and goes away in 2027.2.0
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18366&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18366&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sendspin&lt;/strong&gt;: sendspin-cpp 0.7.2 fixes the artwork image’s &lt;code dir=&quot;auto&quot;&gt;on_clear&lt;/code&gt; never firing
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/18316&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18316&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;thank-you-contributors&quot;&gt;Thank You, Contributors&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;This release includes 348 pull requests from over 40 contributors. A huge thank you to everyone who made
2026.8.0 possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt; - 42 PRs including the platform-neutral &lt;code dir=&quot;auto&quot;&gt;ble_device_base&lt;/code&gt; layer,
the new BK72xx and LN882H BLE trackers, and the 13-batch migration of every BLE sensor platform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; - 29 PRs including &lt;code dir=&quot;auto&quot;&gt;deep_sleep&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;on_wake&lt;/code&gt; triggers, RP2 platform
cleanups and internal temperature fixes, and CI improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; - 27 PRs including clang-tidy coverage for RP2 and LibreTiny,
vendor SDK compatibility fixes, and security hardening&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; - 25 PRs including the &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; refactor and the new
&lt;code dir=&quot;auto&quot;&gt;modbus_client&lt;/code&gt; component with typed actions&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; - 10 PRs including multi-key OTA signature verification, network
default-route arbitration, and the &lt;code dir=&quot;auto&quot;&gt;veml3235&lt;/code&gt; auto-gain overhaul&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; - 7 PRs including runtime wake word model management and the
&lt;code dir=&quot;auto&quot;&gt;sendspin&lt;/code&gt; artwork image platform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/zweckj&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@zweckj&lt;/a&gt; - 6 PRs including the new &lt;code dir=&quot;auto&quot;&gt;hoermann_hcp&lt;/code&gt; garage door component and
Modbus server broadcast and 0x17 support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt; - 6 PRs including the Sensirion &lt;code dir=&quot;auto&quot;&gt;voc_index&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;nox_index&lt;/code&gt; renames and
&lt;code dir=&quot;auto&quot;&gt;cv.rename_key&lt;/code&gt; improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hepter&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@hepter&lt;/a&gt; - 6 PRs including the new &lt;code dir=&quot;auto&quot;&gt;ld6002b&lt;/code&gt; 60GHz presence radar component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt; - 5 PRs including the &lt;code dir=&quot;auto&quot;&gt;mitsubishi_cn105&lt;/code&gt; hub extraction and vertical vane
control&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - 5 PRs including new LVGL actions and display models&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; - 4 PRs including nRF52 OTA support for the Adafruit
bootloader and Zigbee radio stats&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/marpi82&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@marpi82&lt;/a&gt; - 3 PRs including byte-swapped Modbus word types with tests&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; - 3 PRs including Zigbee network handling improvements and the
&lt;code dir=&quot;auto&quot;&gt;on_start&lt;/code&gt; automation&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt; - 2 PRs including &lt;code dir=&quot;auto&quot;&gt;mcp4461&lt;/code&gt; persistence and wiper actions&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@hn&lt;/a&gt; - 2 PRs including CC1101 frequency offset compensation options&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jeroen85&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jeroen85&lt;/a&gt; - 2 PRs including OpenTherm and blocking-warning log fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/egormanga&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@egormanga&lt;/a&gt; - 2 PRs including I2S PDM microphone DSR selection&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ximex&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ximex&lt;/a&gt; - 2 PRs including unit capitalization fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt; - 2 PRs including Haier short IR message support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ptr727&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ptr727&lt;/a&gt; - 2 PRs including CH390 SPI Ethernet support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TesseractTimmee&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@TesseractTimmee&lt;/a&gt; - 2 PRs including Zigbee sensor resolution and units&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomwellnitz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomwellnitz&lt;/a&gt; - the new &lt;code dir=&quot;auto&quot;&gt;ds248x&lt;/code&gt; I²C-to-1-Wire bridge component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rwalker777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwalker777&lt;/a&gt; - network priority for multi-interface support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/wiomoc&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@wiomoc&lt;/a&gt; - the new &lt;code dir=&quot;auto&quot;&gt;zephyr_pwm&lt;/code&gt; platform for nRF52&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also thank you to &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, &lt;a href=&quot;https://github.com/ShaTie&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ShaTie&lt;/a&gt;,
&lt;a href=&quot;https://github.com/Eelviny&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Eelviny&lt;/a&gt;, &lt;a href=&quot;https://github.com/stas-sl&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@stas-sl&lt;/a&gt;,
&lt;a href=&quot;https://github.com/jhenkens&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jhenkens&lt;/a&gt;, &lt;a href=&quot;https://github.com/Rocco83&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Rocco83&lt;/a&gt;,
&lt;a href=&quot;https://github.com/matt123p&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@matt123p&lt;/a&gt;, &lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt;,
&lt;a href=&quot;https://github.com/jptrsn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jptrsn&lt;/a&gt;, &lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt;,
&lt;a href=&quot;https://github.com/rayz90&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rayz90&lt;/a&gt;, &lt;a href=&quot;https://github.com/lsellens&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@lsellens&lt;/a&gt;,
&lt;a href=&quot;https://github.com/ljungqvist&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ljungqvist&lt;/a&gt;, &lt;a href=&quot;https://github.com/jasstrong&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jasstrong&lt;/a&gt;,
&lt;a href=&quot;https://github.com/rggammon&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rggammon&lt;/a&gt;, &lt;a href=&quot;https://github.com/zerafachris&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@zerafachris&lt;/a&gt;,
&lt;a href=&quot;https://github.com/franFodor&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@franFodor&lt;/a&gt;, &lt;a href=&quot;https://github.com/mpoettgen&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mpoettgen&lt;/a&gt;,
&lt;a href=&quot;https://github.com/kobihikri&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kobihikri&lt;/a&gt;, &lt;a href=&quot;https://github.com/peterkeen&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@peterkeen&lt;/a&gt;,
&lt;a href=&quot;https://github.com/youkorr&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@youkorr&lt;/a&gt; for their contributions, and to everyone who reported issues, tested
pre-releases, and helped in the community.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;ble-sensor-platforms&quot;&gt;BLE Sensor Platforms&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;All BLE sensor platforms&lt;/strong&gt;: The auto-generated tracker reference key &lt;code dir=&quot;auto&quot;&gt;esp32_ble_id&lt;/code&gt; is renamed to
&lt;code dir=&quot;auto&quot;&gt;ble_hub_id&lt;/code&gt; on every advertisement-based BLE platform (&lt;code dir=&quot;auto&quot;&gt;ble_presence&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ble_rssi&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ble_scanner&lt;/code&gt;, the
mi-thermometer, BTHome, Mopeka, Ruuvi, Airthings, Inkbird, RadonEye, ThermoPro and Xiaomi families, and
&lt;code dir=&quot;auto&quot;&gt;b_parasite&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;exposure_notifications&lt;/code&gt;). Most configurations never set this key explicitly; those that do
keep validating with a warning until 2027.2.0, when the old key is removed
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17716&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17716&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17950&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17950&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17951&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17951&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18161&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18161&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18165&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18165&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18168&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18168&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18170&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18170&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18171&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18171&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18172&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18172&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18174&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18174&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18178&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18178&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18180&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18180&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18183&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18183&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;iBeacon parsing&lt;/strong&gt;: A 23-byte Apple manufacturer payload must now carry the 0x02/0x15 iBeacon sub-type prefix
to be treated as an iBeacon. Automations that matched spurious beacons with garbage UUIDs stop firing, which
is the fix &lt;a href=&quot;https://github.com/esphome/esphome/pull/18081&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18081&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SGP4x / SEN5x / SEN6x&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;voc&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;nox&lt;/code&gt; sensor keys are renamed to &lt;code dir=&quot;auto&quot;&gt;voc_index&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;nox_index&lt;/code&gt; to
reflect that they publish Sensirion’s unitless gas index, not a concentration. Old keys warn and auto-migrate
until removal in 2027.2.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17723&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17723&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17724&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17724&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17725&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17725&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AQI&lt;/strong&gt;: Over-range readings are no longer pinned to a flat value. US AQI readings above the top breakpoint now
interpolate correctly across 301-500 (and beyond with the new &lt;code dir=&quot;auto&quot;&gt;extended_range&lt;/code&gt; option), and CAQI is unbounded
past 100 per the CITEAIR spec, so values reported during heavy pollution will change
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17570&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17570&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LVGL&lt;/strong&gt;: Animation weights greater than 1.0 in &lt;code dir=&quot;auto&quot;&gt;ease_in&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;ease_out&lt;/code&gt; timing are now rejected at validation
(they previously produced out-of-range progress values), and the default ease timing changes slightly, which
may be visible as a cosmetic difference &lt;a href=&quot;https://github.com/esphome/esphome/pull/17574&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17574&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RC522 I²C&lt;/strong&gt;: The default I²C address changed from &lt;code dir=&quot;auto&quot;&gt;0x2C&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;0x28&lt;/code&gt; to match the documentation and typical
board wiring. If your reader relied on the old default, set &lt;code dir=&quot;auto&quot;&gt;address: 0x2C&lt;/code&gt; explicitly
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17566&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Addressable LED strips&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;rgb_order&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;is_rgbw&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;is_wrgb&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;esp32_rmt_led_strip&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;beken_spi_led_strip&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;rp2040_pio_led_strip&lt;/code&gt; are deprecated in favour of &lt;code dir=&quot;auto&quot;&gt;channel_colors&lt;/code&gt;; they migrate
automatically with a warning until removal in 2027.3.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18474&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18474&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPIO expanders&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;inverted: true&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;allow_other_uses: true&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;interrupt_pin&lt;/code&gt; are now validation errors
for &lt;code dir=&quot;auto&quot;&gt;pcf8574&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pca9554&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;tca9555&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pca6416a&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pi4ioe5v6408&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;mcp23016&lt;/code&gt;; an inverted pin caused an
endless I²C read loop and a shared pin never delivered interrupts
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18472&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18472&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;modbus&quot;&gt;Modbus&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;modbus_controller&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;command_throttle&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;allow_duplicate_commands&lt;/code&gt; no longer have any effect. They are
still accepted with a validation warning and will be removed in 2027.2.0; use &lt;code dir=&quot;auto&quot;&gt;turnaround_time&lt;/code&gt; on the
&lt;code dir=&quot;auto&quot;&gt;modbus&lt;/code&gt; component instead of &lt;code dir=&quot;auto&quot;&gt;command_throttle&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/11781&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11781&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;modbus_controller&lt;/strong&gt;: When several sensors share a range’s start address, the polled range is now widened to
cover the widest sensor. Devices that reject reads touching unmapped registers may return an exception where a
shorter, registration-order-dependent read happened to succeed before
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17677&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17677&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;modbus_controller&lt;/strong&gt;: Sensors polled with &lt;code dir=&quot;auto&quot;&gt;custom_command: [0x17, ...]&lt;/code&gt; (read/write multiple registers) no
longer receive the leading byte-count byte in the payload; subtract one from the &lt;code dir=&quot;auto&quot;&gt;offset:&lt;/code&gt; of any such sensor
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18215&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18215&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;modbus_server&lt;/strong&gt;: Devices can no longer use &lt;code dir=&quot;auto&quot;&gt;address: 0&lt;/code&gt;, which is the Modbus broadcast address. Broadcast
writes are now correctly delivered to all server devices with no response; assign each server a unique address
from 1-247 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17387&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17387&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;web-server&quot;&gt;Web Server&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Entity IDs&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;id&lt;/code&gt; field in the web server JSON now carries the &lt;code dir=&quot;auto&quot;&gt;{domain}/{device?}/{name}&lt;/code&gt; format and
the transitional &lt;code dir=&quot;auto&quot;&gt;name_id&lt;/code&gt; field is removed, completing the migration announced in 2026.1. Current frontends
handle this automatically; only pinned pre-2026.1.3 bundles or custom frontends keyed off the old id are
affected &lt;a href=&quot;https://github.com/esphome/esphome/pull/17586&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17586&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alarm control panel domain&lt;/strong&gt;: The JSON &lt;code dir=&quot;auto&quot;&gt;domain&lt;/code&gt; field now reports &lt;code dir=&quot;auto&quot;&gt;alarm_control_panel&lt;/code&gt; (underscores) instead
of the previously advertised &lt;code dir=&quot;auto&quot;&gt;alarm-control-panel&lt;/code&gt;, matching the only route the server ever accepted
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17594&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17594&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;undocumented-api-changes&quot;&gt;Undocumented API Changes&lt;/h3&gt;&lt;/div&gt;

&lt;p&gt;Advanced users with lambdas and external component maintainers should note the following internal C++ API
changes. These are not covered by the formal breaking change policy, but lambdas sometimes depend on them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: The hub call &lt;code dir=&quot;auto&quot;&gt;send_pdu()&lt;/code&gt; is renamed to &lt;code dir=&quot;auto&quot;&gt;queue_pdu()&lt;/code&gt; to reflect that it queues a request rather
than putting a frame on the wire; &lt;code dir=&quot;auto&quot;&gt;send_pdu()&lt;/code&gt; remains as a deprecated alias for the deprecation window, and a
&lt;code dir=&quot;auto&quot;&gt;succeeded()&lt;/code&gt; helper replaces ad-hoc exception checks
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18196&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18196&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus server&lt;/strong&gt;: Read lambdas can now decline a read by returning an empty optional, answering the request
with &lt;code dir=&quot;auto&quot;&gt;SERVICE_DEVICE_FAILURE&lt;/code&gt;. A register lambda that literally wrote &lt;code dir=&quot;auto&quot;&gt;return {};&lt;/code&gt; previously produced &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt; and
now declines the read; &lt;code dir=&quot;auto&quot;&gt;ServerRegister::set_read_lambda&amp;#x3C;T&gt;()&lt;/code&gt; widens its signature to &lt;code dir=&quot;auto&quot;&gt;optional&amp;#x3C;T&gt;&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17464&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VEML3235&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;gain: AUTO&lt;/code&gt; is removed from the schema (it never compiled; automatic mode remains the separate
&lt;code dir=&quot;auto&quot;&gt;auto_gain&lt;/code&gt; option, enabled by default), and the non-functional &lt;code dir=&quot;auto&quot;&gt;set_power_on()&lt;/code&gt;/shutdown code path is removed
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17551&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17551&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zigbee&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;is_connected&lt;/code&gt; is renamed to &lt;code dir=&quot;auto&quot;&gt;is_joined()&lt;/code&gt;, and the &lt;code dir=&quot;auto&quot;&gt;joined&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;started&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;factory_new&lt;/code&gt; members
are now protected; use &lt;code dir=&quot;auto&quot;&gt;is_joined()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;is_started()&lt;/code&gt; in lambdas instead
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18007&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18007&lt;/a&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18008&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18008&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web server base&lt;/strong&gt;: The credential setters on &lt;code dir=&quot;auto&quot;&gt;WebServerBase&lt;/code&gt; now take &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt; instead of
&lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;, and on non-ESP32 basic-auth builds &lt;code dir=&quot;auto&quot;&gt;set_auth_username&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;set_auth_password&lt;/code&gt; are replaced by
&lt;code dir=&quot;auto&quot;&gt;set_auth_basic_hash&lt;/code&gt; (part of the fix for basic auth failing with long credentials)
&lt;a href=&quot;https://github.com/esphome/esphome/pull/18237&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18237&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ModbusController API&lt;/strong&gt;: Handler signatures for &lt;code dir=&quot;auto&quot;&gt;on_data_func&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;create_read_command()&lt;/code&gt; and
&lt;code dir=&quot;auto&quot;&gt;create_custom_command()&lt;/code&gt; now take &lt;code dir=&quot;auto&quot;&gt;std::span&amp;#x3C;const uint8_t&gt;&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const std::vector&amp;#x3C;uint8_t&gt;&amp;#x26;&lt;/code&gt;;
&lt;code dir=&quot;auto&quot;&gt;on_register_data()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;send_raw()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_command_queue_length()&lt;/code&gt; and the 4-argument &lt;code dir=&quot;auto&quot;&gt;create_read_command()&lt;/code&gt;
overload are removed; &lt;code dir=&quot;auto&quot;&gt;ModbusCommandItem&lt;/code&gt; data members are now protected (use the accessors); and
&lt;code dir=&quot;auto&quot;&gt;ModbusController&lt;/code&gt; no longer derives from &lt;code dir=&quot;auto&quot;&gt;modbus::ModbusClientDevice&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/11781&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11781&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ModbusController sensor dispatch&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;SensorItem::parse_and_publish()&lt;/code&gt; takes &lt;code dir=&quot;auto&quot;&gt;std::span&amp;#x3C;const uint8_t&gt;&lt;/code&gt;;
external platforms must set addresses via &lt;code dir=&quot;auto&quot;&gt;set_address()&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;set_offset_from_start_address()&lt;/code&gt; instead of
assigning &lt;code dir=&quot;auto&quot;&gt;start_address&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;offset&lt;/code&gt; directly, and &lt;code dir=&quot;auto&quot;&gt;payload_to_float()&lt;/code&gt; gains an explicit &lt;code dir=&quot;auto&quot;&gt;offset&lt;/code&gt; parameter
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17677&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17677&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESPBTDevice::address_str() deprecated&lt;/strong&gt;: Use the buffer-based &lt;code dir=&quot;auto&quot;&gt;address_str_to()&lt;/code&gt;; the old method is removed
in 2027.2.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18092&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#18092&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the
&lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-8-1---august-24&quot;&gt;Release 2026.8.1 - August 24&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[wifi] Take the lwIP core lock around sntp_servermode_dhcp() &lt;a href=&quot;https://github.com/esphome/esphome/pull/18511&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18511&lt;/a&gt; by &lt;a href=&quot;https://github.com/SoundGoof&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@SoundGoof&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.12.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18541&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18541&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[nrf52] Rebuild the Python env when its interpreter symlink dangles &lt;a href=&quot;https://github.com/esphome/esphome/pull/18540&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18540&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Keep templated !include filenames as strings so Windows path normalization cannot corrupt them &lt;a href=&quot;https://github.com/esphome/esphome/pull/18549&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18549&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.12.2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18573&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18573&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espnow] Fix dump_config crash when enable_on_boot is false &lt;a href=&quot;https://github.com/esphome/esphome/pull/18572&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18572&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[emontx] Fix sensor state_class defaults not being applied correctly &lt;a href=&quot;https://github.com/esphome/esphome/pull/17610&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17610&lt;/a&gt; by &lt;a href=&quot;https://github.com/FredM67&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@FredM67&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_hosted] Fire on_update_available trigger when update is detected &lt;a href=&quot;https://github.com/esphome/esphome/pull/18591&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18591&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.12.3 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18601&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18601&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.12.4 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18651&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18651&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bk72xx_ble] Block BK7238 until the LibreTiny bonding partition fix lands &lt;a href=&quot;https://github.com/esphome/esphome/pull/18649&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18649&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble] Log connection parameter update results &lt;a href=&quot;https://github.com/esphome/esphome/pull/18607&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18607&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp8266] Don’t report stale crash state after hardware WDT resets &lt;a href=&quot;https://github.com/esphome/esphome/pull/18597&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18597&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Dump the main.cpp config comment with sorted keys &lt;a href=&quot;https://github.com/esphome/esphome/pull/18653&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18653&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Report abort and task watchdog panics correctly in crash handler &lt;a href=&quot;https://github.com/esphome/esphome/pull/18575&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18575&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Retry transient network errors when downloading external files &lt;a href=&quot;https://github.com/esphome/esphome/pull/18538&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18538&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fix loop stall that triggers the task watchdog when entity list sends block &lt;a href=&quot;https://github.com/esphome/esphome/pull/18577&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18577&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_tracker] Scan at the default window while a GATT connection is active &lt;a href=&quot;https://github.com/esphome/esphome/pull/18609&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18609&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-8-2---august-31&quot;&gt;Release 2026.8.2 - August 31&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[espidf] Always reconfigure after component discovery &lt;a href=&quot;https://github.com/esphome/esphome/pull/18730&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18730&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[gpio] Fix one_wire reset busy-waiting with interrupts off when delay wraps &lt;a href=&quot;https://github.com/esphome/esphome/pull/18733&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18733&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.13.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18743&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18743&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix on_value/on_update triggers for LVGL select entities &lt;a href=&quot;https://github.com/esphome/esphome/pull/18778&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18778&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Default watchdog_timeout from timeout on ESP32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18732&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18732&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] Fix dimensions for jc3636518v2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18786&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18786&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mdns] Skip MDNS.update() while the ESP8266 radio cannot transmit &lt;a href=&quot;https://github.com/esphome/esphome/pull/18785&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18785&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.13.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18807&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18807&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.8.0/&quot;&gt;full 2026.8.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>Community Day 2026: Save the date!</title><link>https://esphome.io/blog/2026/08/13/community-day-2026-save-the-date/</link><guid isPermaLink="true">https://esphome.io/blog/2026/08/13/community-day-2026-save-the-date/</guid><description>You’ve been asking all year, and the wait is over… Mark your calendars, because Community Day 2026 will be held on Saturday, November 7! 🎉</description><pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You’ve been asking all year, and the wait is over… Mark your calendars, because &lt;a href=&quot;https://luma.com/communityday2026&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Community Day 2026&lt;/a&gt; will be held on Saturday, November 7! 🎉&lt;/p&gt;</content:encoded><category>Announcements</category></item><item><title>Get ready to start building: The ESPHome Starter Kit is here!</title><link>https://esphome.io/blog/2026/08/12/the-esphome-starter-kit-is-here/</link><guid isPermaLink="true">https://esphome.io/blog/2026/08/12/the-esphome-starter-kit-is-here/</guid><description>Meet the ESPHome Starter Kit: the easiest way to start building your own smart home devices – no soldering, breadboarding, or coding required.</description><pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Back in April during State of the Open Home 2026, we gave you a sneak peek of ESPHome’s &lt;em&gt;very first&lt;/em&gt; official
product… And after months of hard work alongside the community, the &lt;a href=&quot;https://esphome.io/starter-kit/&quot;&gt;ESPHome Starter Kit&lt;/a&gt; is here! 🎉&lt;/p&gt;
&lt;p&gt;Designed and produced by &lt;a href=&quot;https://apolloautomation.com/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Apollo Automation&lt;/a&gt;, the
&lt;a href=&quot;https://www.openhomefoundation.org/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Open Home Foundation’s&lt;/a&gt; second commercial partner, the kit is the easiest way
to start building your own smart home devices. Affordable and packed with all the components you need, the Starter
Kit invites &lt;em&gt;everyone&lt;/em&gt;, not just seasoned tinkerers, to begin building.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://esphome.io/_astro/starter-kit-glowing-modules.DOUeChav_Z1yCJSQ.webp&quot; srcset=&quot;/_astro/starter-kit-glowing-modules.DOUeChav_Z21pxu6.webp 480w, /_astro/starter-kit-glowing-modules.DOUeChav_1PlRg5.webp 768w, /_astro/starter-kit-glowing-modules.DOUeChav_Z1yCJSQ.webp 1000w&quot; alt=&quot;ESPHome Starter Kit modules on a table, with the ESPHome logo shaped notification module illuminated by rainbow LED lights.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1000px) 1000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-fit=&quot;cover&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1000&quot; height=&quot;667&quot;&gt;&lt;figcaption&gt;&lt;span&gt;A tiny house for big ideas.&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div&gt;&lt;h2 id=&quot;time-to-start-creating&quot;&gt;Time to start creating&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Ever wanted to build your own smart home device, but didn’t know where to begin? Between chips, pins, soldering
irons, and breadboards – sourcing the right hardware can stop a project getting off the ground. Not to mention time
spent ensuring the parts are compatible, and working out how to wire them together.&lt;/p&gt;
&lt;p&gt;That’s where the Starter Kit comes in. With no soldering, breadboarding, or coding experience needed, the kit
equips you with all you need to stop just using smart home tech, and start &lt;em&gt;creating&lt;/em&gt; it.&lt;/p&gt;
&lt;a href=&quot;https://esphome.io/starter-kit/#buy&quot;&gt;Buy now&lt;/a&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-in-the-box&quot;&gt;What’s in the box?&lt;/h2&gt;&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://esphome.io/_astro/starter-kit-unboxed.hgwjyefn_Z1PM86j.webp&quot; srcset=&quot;/_astro/starter-kit-unboxed.hgwjyefn_Z6eFf0.webp 480w, /_astro/starter-kit-unboxed.hgwjyefn_Z1PM86j.webp 670w&quot; alt=&quot;The ESPHome Starter Kit box next to its unboxed contents: notification module, main board, motion sensor, button module, ribbon cables, and stand, arranged on a wooden surface.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 670px) 670px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-fit=&quot;cover&quot; data-astro-image-pos=&quot;center&quot; width=&quot;670&quot; height=&quot;672&quot;&gt;&lt;figcaption&gt;&lt;span&gt;A box packed with possibilities.&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The ESPHome Starter Kit arrives with four modules to build with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Motion sensor – to detect movement, making a perfect first automation&lt;/li&gt;
&lt;li&gt;Temperature and humidity sensor – to reliably track a room’s comfort level&lt;/li&gt;
&lt;li&gt;Notification module – to provide alerts via a buzzer and ten individually controllable RGB LEDs that glow
through the ESPHome logo&lt;/li&gt;
&lt;li&gt;Button module – to trigger any automation you like&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Powering it all is an ESP32-C6 microcontroller, which, for anyone new to electronics, is the programmable chip that
acts as the “brain” of your project. ESPHome builds the software that runs on this chip, letting it control the four
modules and talk to Home Assistant or any other smart home platform that supports it.&lt;/p&gt;
&lt;p&gt;You’ll also find everything you need to put it all together: the flat ribbon cables that connect each module to the
board (with a spare in the box, so you’re covered if one goes astray), and a stand to show off the notification
module and its glowing ESPHome logo. It runs on a standard USB-C cable, and uses the same open standards as the rest
of your smart home, so there’s nothing special to buy before you get started: it works with your existing Home
Assistant setup straight out of the box.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;snap-into-action&quot;&gt;Snap into action&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The kit arrives with a snap-apart panel, with each module attached by small breakaway tabs. Instead of soldering
joints and wiring breadboards, you simply snap a module off the panel and connect it to the main board via the flat
ribbon cable.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://esphome.io/_astro/starter-kit-assembly.qFnx7-va_Z1dF834.webp&quot; srcset=&quot;/_astro/starter-kit-assembly.qFnx7-va_Z1ws3cQ.webp 480w, /_astro/starter-kit-assembly.qFnx7-va_10xh7r.webp 768w, /_astro/starter-kit-assembly.qFnx7-va_Z1dF834.webp 1000w&quot; alt=&quot;A two-part image: on the left, ESPHome Starter Kit components laid out on a wooden surface, including the main board, modules, ribbon cables, and stand; on the right, hands connecting a ribbon cable between the main board and the button module.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1000px) 1000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-fit=&quot;cover&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1000&quot; height=&quot;563&quot;&gt;&lt;figcaption&gt;&lt;span&gt;The kit’s pieces (left) and how they come together.&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;And because every module connects the same way, they’re completely interchangeable: pop one off, snap the next one
on, install new software on your ESP microcontroller, and you’ve got a different device.&lt;/p&gt;
&lt;p&gt;This kit is designed to be experimented with. You can reconfigure it as your ideas grow, and adapt it as you learn,
so the same hardware carries you from your very first project to your tenth. Each build works as a standalone device
right away, and if you find yourself ready to explore more complex automations, it drops straight into Home
Assistant.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-kit-for-keeps&quot;&gt;A kit for keeps&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Most learning kits end up the same way: forgotten in a drawer. But Apollo Automation co-founders Trevor Schirmer and
Justin Bunton had other ideas: they wanted to create something sustainable that helped more people experience the
joy of building, &lt;em&gt;and&lt;/em&gt; left them with devices that remained useful long after the basics had clicked.&lt;/p&gt;
&lt;p&gt;That’s why every module in the ESPHome Starter Kit becomes a custom, working smart home device: the kind you can’t
buy off the shelf. Shaped by you to fit your home and habits, each device becomes yours in every sense – run locally
with no cloud dependency, so your data stays in your home instead of on someone else’s server. And it’s easier than
you might think…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One of the core requirements for the kit was that you had something useful at the end. One of the foundation’s
principles is sustainability. So, this isn’t something that you just buy, learn, and then put in a drawer or the
trash never to be seen again. You can make real usable products out of this at the end. … For example, you could
use the motion module to turn on the lights when somebody walks into your room, or you could use the ESPHome-shaped
LEDs to turn red when you’re in a meeting, letting others in your home know…&lt;/p&gt;
&lt;p&gt;— Trevor Schirmer, Co-Founder of Apollo Automation&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;h2 id=&quot;your-trusty-guide&quot;&gt;Your trusty guide…&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The Starter Kit comes with two tools that guide you every step of the way, from your very first setup to your most
ambitious projects.&lt;/p&gt;
&lt;p&gt;The first is the
&lt;a href=&quot;https://wiki.apolloautomation.com/products/ESPHome-Starter-Kit/start-here/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Learning Wiki&lt;/a&gt;: more than assembly
instructions, it explains the &lt;em&gt;why&lt;/em&gt; behind each step, showing how your components connect to the code that runs
them. This means you’re not just following a recipe – you’re picking up the fundamentals of electronics and device
building, one project at a time. By the end, you’ll have the skills and the confidence to take on bigger builds of
your own.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;and-a-revamped-visual-builder&quot;&gt;…and a revamped visual builder&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The second is our &lt;a href=&quot;https://esphome.io/install/&quot;&gt;ESPHome Device Builder&lt;/a&gt;, recently &lt;a href=&quot;https://esphome.io/blog/2026/07/02/unbox-your-creativity-with-the-esphome-device-builder/&quot;&gt;updated&lt;/a&gt; to help make ESPHome more approachable for all – no matter if you’ve been with us for years or if this is the first time you hear about ESPHome. Its intuitive interface lets you configure everything without writing a line of code, though the YAML’s always there underneath, should you want it.&lt;/p&gt;
&lt;p&gt;Best of all, it runs right on your desktop through our app, so you can start building with whatever you already
have. And once you’ve nailed the basics, you can still use the Device Builder to help you go further – whatever you
decide to build next.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;three-things-to-try-with-the-esphome-starter-kit&quot;&gt;Three things to try with the ESPHome Starter Kit&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As its name suggests, the Starter Kit is just the beginning. Once you’ve made your modules, you can connect them to
just about any automation you like – for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Set your button to close the blinds:&lt;/strong&gt; Press the button and your blinds glide shut, no hunting for a remote.
Perfect for movie nights or shutting out the afternoon glare.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set your motion sensor to detect visitors:&lt;/strong&gt; Place it by the front door or driveway and be notified the moment
it senses movement, so you’re never caught off guard.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set your temperature monitor to manage the heating:&lt;/strong&gt; Choose your ideal range and let the sensor keep watch,
adjusting automatically if a room gets too warm or cool.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The possibilities are almost endless, with plenty more to discover as your ideas grow, and a community of
experienced ESPHome users to talk to for inspiration.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;join-the-community&quot;&gt;Join the community&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;On the subject of community, half the fun of building something is sharing it with others. When you start using the
kit, you join thousands of other makers using ESPHome. Come say hello on the
&lt;a href=&quot;https://discord.gg/KhAMKrd&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Discord server&lt;/a&gt; to swap ideas and show off what you’ve built, or drop into our
&lt;a href=&quot;https://community.home-assistant.io/c/esphome/36&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome forum&lt;/a&gt; to ask questions and find your feet. And if you
have thoughts about what Apollo Automation should build next, you can share them on the
&lt;a href=&quot;https://discord.com/invite/fvwxCab4hR&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Apollo Automation Discord server&lt;/a&gt;!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;ready-set-start&quot;&gt;Ready, set, &lt;em&gt;start&lt;/em&gt;&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Keen to get your kit? Head to the &lt;a href=&quot;https://esphome.io/starter-kit/&quot;&gt;ESPHome Starter Kit&lt;/a&gt; site to grab your gear today. The majority of
profit from every kit goes straight to the Open Home Foundation, meaning every purchase helps fund the future of
&lt;a href=&quot;https://esphome.io/&quot;&gt;ESPHome&lt;/a&gt;, &lt;a href=&quot;https://www.home-assistant.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Home Assistant&lt;/a&gt;, and &lt;a href=&quot;https://www.music-assistant.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Music Assistant&lt;/a&gt;,
and the other projects working to make smart home tech accessible to all. We can’t wait to see what you create!&lt;/p&gt;</content:encoded><category>Announcements</category></item><item><title>Simplify your ESPHome setup with the new desktop app</title><link>https://esphome.io/blog/2026/08/04/simplify-your-esphome-setup-with-the-new-desktop-app/</link><guid isPermaLink="true">https://esphome.io/blog/2026/08/04/simplify-your-esphome-setup-with-the-new-desktop-app/</guid><description>Download the new ESPHome Device Builder desktop app for macOS, Windows, or Linux, and start building your own custom smart home devices in minutes.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last month, we introduced the
&lt;a href=&quot;https://esphome.io/blog/2026/07/02/unbox-your-creativity-with-the-esphome-device-builder/&quot;&gt;ESPHome Device Builder&lt;/a&gt;: a more visual and
intuitive tool for configuring your smart home devices without having to write any code, unless you want to! Now we’ve
taken a further step in our efforts to make ESPHome more approachable, by bringing the Device Builder to your desktop
in a quick and easy way.&lt;/p&gt;
&lt;p&gt;Say hello to the &lt;a href=&quot;https://esphome.io/install/&quot;&gt;ESPHome Device Builder desktop app&lt;/a&gt;, available now for macOS, Windows, and Linux.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-final-hurdle-for-beginners&quot;&gt;The final hurdle for beginners&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;If you’ve already tried the Device Builder, you’ll know how much friction it removes from configuring a device. But for
a lot of newcomers, there was still a hurdle to clear before getting started: the technical tasks of installing Python
and typing commands in a terminal. Not that hard if you’ve done it before… but if you haven’t, it’s a process that could
turn a Saturday afternoon project into a weekend of troubleshooting.&lt;/p&gt;
&lt;p&gt;The desktop app removes that hurdle, and is designed to be simple to set up.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;all-you-need-to-do&quot;&gt;All you need to do&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Download the app for your platform, run the installer… and that’s it. On first launch:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The app quietly sets everything up in the background: no technical steps required.&lt;/li&gt;
&lt;li&gt;It opens the Device Builder automatically in your browser.&lt;/li&gt;
&lt;li&gt;A small icon appears in your system tray, giving you access to reopen the Device Builder, check for updates, or quit:
no digging through tabs or task managers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That tray icon stays there for as long as you use ESPHome: it’s your quick way back in, every time, not just on day one.
And because the app is designed to run locally, on your own computer, there’s no login or password to set up, so it’s
ready to use the moment it opens.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;why-this-matters-for-beginners&quot;&gt;Why this matters for beginners…&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Think back to the workshop metaphor from our last post: the Device Builder itself is the well-organized bench where the
creative work happens. The desktop app is what makes it easy – and low stakes – to walk in and start that work. So if
you’re faced with your first microcontroller (the imminent ESPHome Starter Kit perhaps 👀), there’s no technical setup
standing between unboxing and beginning your build: just download the app, and away you go.&lt;/p&gt;
&lt;p&gt;It’s not just the start-up that’s easy. Every time you want to tweak a device or add a new one, it’s the same simple
open-and-go experience, with no need to remember any previous commands.&lt;/p&gt;
&lt;p&gt;When you start slightly more advanced projects, the desktop app can help with other elements of your setup. For example
if you run ESPHome on a lower-powered device, like a Raspberry Pi, you can have it send the heavy lifting of compiling
firmware over to the app instead, then send the finished result back. It’s a handy way to speed up builds without
changing how or where you actually flash your devices.&lt;/p&gt;
&lt;p&gt;The app is also useful for anyone helping a less technical friend or family member get started. “Download this app and
open it” is an instruction anyone can follow. “Install Python, then pip install this, then run this command” is not.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;and-for-experienced-users&quot;&gt;…and for experienced users&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Don’t mistake the beginner focus for a lack of depth. If you’re setting up ESPHome on a new machine, spinning up a build
environment for a demo, or just tired of manually checking the latest Device Builder version, the desktop app handles
all that for you. Update checks live right in your system tray: no more remembering to consult the changelog yourself.&lt;/p&gt;
&lt;p&gt;What’s more, nothing about your existing workflow changes. If you’re already running ESPHome through pip, Docker, or the
Home Assistant add-on, you’re unaffected: the desktop app is simply another door into the same Device Builder, for
people who’d rather not open a terminal at all.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;try-it-this-weekend&quot;&gt;Try it this weekend&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Ready to give it a go? Here’s how to get started in three simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download the app:&lt;/strong&gt; For macOS, Windows, or Linux from esphome.io/install.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open it and let it work&lt;/strong&gt;: ESPHome sets itself up in the background, no configuration needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Start your first project:&lt;/strong&gt; Dive straight into the Device Builder that opens automatically, and explore the
Component Catalog we introduced last month.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;reminder-for-returning-users&quot;&gt;Reminder for returning users&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;If you’re already comfortable with pip, Docker, or the Home Assistant App, there’s nothing you need to change. The
desktop app is an additional on-ramp, not a replacement for how you already work… it’s there for the next person who’s
about to start exploring the wonderful world of ESPHome!&lt;/p&gt;</content:encoded><category>Announcements</category></item><item><title>Making our web analytics open source with Plausible</title><link>https://esphome.io/blog/2026/07/30/making-our-web-analytics-open-source-with-plausible/</link><guid isPermaLink="true">https://esphome.io/blog/2026/07/30/making-our-web-analytics-open-source-with-plausible/</guid><description>The Open Home Foundation fights for privacy, choice, and sustainability. These principles are at the heart of everything we do, including how we handle website analytics. Our position is clear: we reject tools that track individuals across the web to monetize their data. Instead, we want aggregated, anonymized analytics that show how our websites are performing overall — without identifying who our visitors are, or compromising their privacy.</description><pubDate>Thu, 30 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The Open Home Foundation fights for privacy, choice, and sustainability. These principles are at the heart of everything we do, including how we handle website analytics. Our position is clear: we reject tools that track individuals across the web to monetize their data. Instead, we want aggregated, anonymized analytics that show how our websites are performing overall — without identifying who our visitors are, or compromising their privacy.&lt;/p&gt;</content:encoded><category>Announcements</category></item><item><title>ESPHome 2026.7.0: Native toolchains by default</title><link>https://esphome.io/blog/2026/07/15/esphome-2026-7/</link><guid isPermaLink="true">https://esphome.io/blog/2026/07/15/esphome-2026-7/</guid><description>ESPHome 2026.7.0 makes native toolchains the default on ESP32 and nRF52, adds EN18031 security groundwork, and overhauls Modbus.</description><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/ufm01/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ufm01.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;UFM-​0​1​ ​Flow ​Meter&lt;/div&gt;&lt;div&gt;Flow ​&amp;#x26;​ ​Temperature&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/waveshare_io_ch32v003/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/waveshare_io_ch32v003.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Waveshare ​CH3​2​V0​0​3​ ​IO ​Expander&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/display/it8951/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/it8951.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;IT8​9​5​1​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/motion/qmi8658/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/imu.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;QMI8​6​5​8​&lt;/div&gt;&lt;div&gt;Accelerometer ​&amp;#x26;​ ​Gyroscope&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/touchscreen/cst9220/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/touch.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;CST9​2​2​0​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/display/pixoo/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/pixoo.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Pixoo&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/touchscreen/st7123/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/touch.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;ST7​1​2​3​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/touchscreen/cst328/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/touch.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;CST3​2​8​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/provisioning/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/timer.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Provisioning&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/touchscreen/gsl3670/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/touchscreen.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;GSL3​6​7​0​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.7.0 flips the default ESP32 and nRF52 toolchains to native builds (ESP-IDF and the nRF Connect
SDK) 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;

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


&lt;div&gt;&lt;h2 id=&quot;native-toolchains-are-now-the-default-on-esp32-and-nrf52&quot;&gt;Native Toolchains Are Now the Default on ESP32 and nRF52&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The default toolchain for the &lt;code dir=&quot;auto&quot;&gt;esp32&lt;/code&gt; platform switches from PlatformIO to native ESP-IDF
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16910&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16910&lt;/a&gt;). Configurations that do not set an explicit &lt;code dir=&quot;auto&quot;&gt;toolchain:&lt;/code&gt;
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
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17023&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17023&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The toolchain selects the build backend, not the framework: both the Arduino and ESP-IDF frameworks build on
either toolchain, with the native toolchain pulling in Arduino as an ESP-IDF component. Configurations that
explicitly set &lt;code dir=&quot;auto&quot;&gt;toolchain: platformio&lt;/code&gt; continue to build exactly as they did before, while new configurations
generated by the wizard or from packages will pick up the native ESP-IDF toolchain automatically. ESP-IDF is
now the recommended choice for both the toolchain and the framework.&lt;/p&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;nrf52&lt;/code&gt; platform makes the same move: native nRF Connect SDK builds, added earlier this cycle by
&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16898&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16898&lt;/a&gt;), are
now the default toolchain (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17319&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17319&lt;/a&gt;). Configurations without an
explicit &lt;code dir=&quot;auto&quot;&gt;toolchain:&lt;/code&gt; option build against nRF Connect SDK 2.9.2, installed into the new shared toolchain cache
described below, and &lt;code dir=&quot;auto&quot;&gt;toolchain: platformio&lt;/code&gt; remains available as an opt-out here as well.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esphome-device-builder&quot;&gt;ESPHome Device Builder&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The bundled &lt;a href=&quot;https://github.com/esphome/device-builder&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Device Builder&lt;/a&gt; has been updated, and most of the work
this cycle went into the remote build server.&lt;/p&gt;
&lt;p&gt;Compiling firmware is the slowest thing the Device Builder does, and on a small host such as a Home Assistant Green or a
Raspberry Pi a single build can take several minutes. A remote build server lets that dashboard hand the compile to a
faster machine on your network, such as a desktop or laptop running &lt;a href=&quot;https://desktop.esphome.io&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Desktop&lt;/a&gt;, which
builds the firmware and sends it back to be installed as usual. Your devices, configurations, and dashboard all stay
where they are; only the build moves.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pairing With a Build Server Is Much Easier&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A machine that builds for other dashboards now says so on its own dashboard
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1240&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1240&lt;/a&gt;). A &lt;strong&gt;Build server&lt;/strong&gt; section appears
above the device list once another dashboard is paired with it, or once remote building is turned on, and it walks you
through pairing in three steps instead of leaving you to find the pieces in Settings.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://esphome.io/images/device-builder-build-server.png&quot; alt=&quot;Pairing a build server in the ESPHome Device Builder&quot;&gt;&lt;/p&gt;
&lt;p&gt;From there you can open the pairing window and watch its countdown, copy the address to enter on the sending dashboard
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2075&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2075&lt;/a&gt;), and compare the identity fingerprint against the one the
sender shows. Once peers are paired the section lists them with their connection state and the build queue, and any
pairing request waiting on you appears at the top. Settings gained a matching explainer, and the old &lt;strong&gt;Only use this for
remote compute&lt;/strong&gt; switch is now &lt;strong&gt;Remote compute dashboard&lt;/strong&gt;, which decides which section opens first rather than hiding
anything.&lt;/p&gt;
&lt;p&gt;Remote builds are steadier once they are running, too. If a receiver restarts, the sender now reconnects as soon as it
reappears on mDNS instead of waiting out its backoff (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2084&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2084&lt;/a&gt;).
Receivers can now also provision beta versions of ESPHome, so a build server running a different version to a sender on
the beta channel no longer quietly falls back to building locally
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2082&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2082&lt;/a&gt;). The first build for a version installs ESPHome from PyPI
and can take a few minutes, which the job log now says out loud instead of sitting silent
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2083&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2083&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you have never tried this, the terminal now shows a build timer, and a local compile that runs longer than five
minutes on a dashboard with no build server paired suggests sending your builds to a faster machine
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1183&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1183&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Offline and Deep Sleep Updates&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Updating a device that is not awake has always been a matter of timing. An OTA aimed at a device that is asleep or
otherwise unreachable simply fails, which is a familiar problem if you run anything on &lt;a href=&quot;https://esphome.io/components/deep_sleep/&quot;&gt;deep
sleep&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Queued offline updates, contributed by &lt;a href=&quot;https://github.com/rwalker777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwalker777&lt;/a&gt;, fix that
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/1430&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#1430&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/911&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#911&lt;/a&gt;). If a device is offline when you install to
it, the Device Builder compiles the firmware, queues the update, and flashes it when the device next appears on the
network, with no need for you to be watching at the time.&lt;/p&gt;
&lt;p&gt;The groundwork for this landed in 2026.6.0, and it is ready for production use now. It works across a whole fleet:
select any number of devices and hit update, and the ones that are unreachable are compiled once and queued for their
next appearance rather than failing (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/1929&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#1929&lt;/a&gt;). A device that drops
offline between hitting install and the build finishing is queued as well, instead of failing at the last step
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/1964&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#1964&lt;/a&gt;), and a queued update reopens as an install, carrying its
queued message, when you come back to it
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1181&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1181&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quickstart Tour&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Getting from a fresh install to a working device has always been the hardest part of ESPHome, and this release takes a
real run at it. Setup now ends by offering you a guided tour, and the tour teaches the Device Builder by using it rather
than by describing it.&lt;/p&gt;
&lt;p&gt;It spotlights one real control at a time, explains what it is for, and on the steps that matter it waits for you to
click it rather than moving on without you. Over eleven steps it walks you through creating your first device, picking a
board, naming it, entering your WiFi details, finding your way around the device navigator and the editor, watching the
YAML pane stay in sync as you go, and how installing to your board works, finishing on your new device sitting on the
dashboard. It takes about five minutes, it leaves you with a real device rather than a throwaway, you can close it and
pick it up where you left off, and it is always available afterwards from the menu in the top right.&lt;/p&gt;
&lt;p&gt;The tour was a team effort from &lt;a href=&quot;https://github.com/Erioldoesdesign&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Erioldoesdesign&lt;/a&gt;,
&lt;a href=&quot;https://github.com/stvncode&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@stvncode&lt;/a&gt;, and &lt;a href=&quot;https://github.com/marcelveldt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@marcelveldt&lt;/a&gt;, across design, wireframes,
and build (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1045&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1045&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1232&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1232&lt;/a&gt;). The setup flow around it was rebuilt at
the same time: a new welcome screen, an experience question that lets beginners take the recommended path with a single
click, and a closing screen that hands you to the tour. If you set up the desktop app while another Device Builder is
already running on your network, setup now points that out and explains how to pair the two, so you can put the new
machine to work building for the dashboard you already have
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1235&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1235&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;YAML Errors Explained and Auto-Fixed&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A number of issues reported against ESPHome turn out not to be bugs at all, but a small mistake made while editing YAML.
This release goes after that whole class of problem.&lt;/p&gt;
&lt;p&gt;Getting a space wrong used to earn you the raw parser output, &lt;code dir=&quot;auto&quot;&gt;mapping values are not allowed here&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;could not find expected &apos;:&apos;&lt;/code&gt;, and only if you thought to hover over the squiggle. The line it pointed at was usually where the parser
gave up rather than where you made the mistake, which is little help if you are not already fluent in YAML.&lt;/p&gt;
&lt;p&gt;The editor now reads the error and tells you what is actually wrong, in a banner that stays put, naming the line you
need to change and what to do to it: &lt;em&gt;“Indentation mismatch: line 12 &lt;code dir=&quot;auto&quot;&gt;- platform&lt;/code&gt; is indented less than its properties.
Indent line 12 by 2 spaces so &lt;code dir=&quot;auto&quot;&gt;- platform&lt;/code&gt; lines up with them.”&lt;/em&gt; Next to it is a &lt;strong&gt;Try auto-fix&lt;/strong&gt; button that makes
exactly that change for you. It is a best-effort guess rather than magic, so it is validated against your config before
it is applied, it tells you if other errors remain, and it lands as a normal edit you can undo
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1121&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1121&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1147&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1147&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1148&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1148&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Indentation is not the only thing it explains. Tabs used where YAML wants spaces, a value starting with &lt;code dir=&quot;auto&quot;&gt;@&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;%&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;*&lt;/code&gt;
that needs quotes, an unterminated quote, a duplicate key, and an unclosed bracket or brace all get the same
plain-language treatment. A list marker missing its space, &lt;code dir=&quot;auto&quot;&gt;-platform: gpio&lt;/code&gt;, is offered a one-click repair to &lt;code dir=&quot;auto&quot;&gt;- platform: gpio&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1149&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1149&lt;/a&gt;). So is a key that has
drifted out of the block it belongs to, such as an &lt;code dir=&quot;auto&quot;&gt;encryption&lt;/code&gt; key left sitting directly under &lt;code dir=&quot;auto&quot;&gt;api:&lt;/code&gt;, in either
direction; the Device Builder checks its component catalog first to confirm where the key really belongs, and offers
nothing rather than a wrong guess if it cannot tell
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1164&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1164&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Device log lines now link to the documentation that explains them
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1116&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1116&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1118&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1118&lt;/a&gt;). Ten common warnings and errors get a
curated explanation, including &lt;code dir=&quot;auto&quot;&gt;took a long time for an operation&lt;/code&gt;, WiFi reconnect loops, repeated resets, OTA
rollbacks, and running out of Bluetooth proxy connection slots, and any other line tagged with a component links
straight to that component’s page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Headless Build Servers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; added &lt;code dir=&quot;auto&quot;&gt;--remote-build-only&lt;/code&gt;, which runs Device Builder as a dedicated build
box with no web interface at all (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/1861&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#1861&lt;/a&gt;):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome-device-builder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--remote-build-only&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/var/lib/esphome-builder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It serves only the peer link, so there is no interface for anyone to click Accept in. Instead it opens a pairing window
on first start and prints its identity fingerprint and a one-time key to the console. You pair from the sending
dashboard, check that the fingerprint matches the console, and type in the key, which the pair dialog knows to ask for
up front (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/1881&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#1881&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1120&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1120&lt;/a&gt;). That window pairs exactly one dashboard
and then closes.&lt;/p&gt;
&lt;p&gt;If you would rather keep the web interface but still dedicate the machine to building, turn on &lt;strong&gt;Remote compute
dashboard&lt;/strong&gt; in Settings and a &lt;strong&gt;Hide the Device builder&lt;/strong&gt; option appears beneath it, leaving only the &lt;strong&gt;Build server&lt;/strong&gt;
view (&lt;a href=&quot;https://github.com/esphome/device-builder/pull/2077&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#2077&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1244&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1244&lt;/a&gt;). Device Builder can also listen on a UNIX
socket with &lt;code dir=&quot;auto&quot;&gt;--socket&lt;/code&gt; for reverse-proxy setups, contributed by &lt;a href=&quot;https://github.com/vexofp&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@vexofp&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/1862&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#1862&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Builds&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Starting a build no longer greys out the buttons that would take you back to it. Update and Install now open the running
job, and Edit stays clickable so you can read your YAML while it compiles
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1191&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1191&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1193&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1193&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1197&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1197&lt;/a&gt;). Download and Retry now wait for a
running build to finish instead of cancelling and restarting it, which also means Download can no longer hand you a
half-written binary (&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1199&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1199&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1201&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1201&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1204&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1204&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;A bulk &lt;strong&gt;Compile only&lt;/strong&gt; action lets you check a change across many devices before deploying any of it
(&lt;a href=&quot;https://github.com/esphome/device-builder-frontend/pull/1176&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;frontend#1176&lt;/a&gt;). ESP-IDF builds now show compile
progress, which is read from the ninja build counters rather than the percentage that ESP-IDF never prints
(&lt;a href=&quot;https://github.com/esphome/device-builder/pull/1880&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#1880&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Special thanks to &lt;a href=&quot;https://github.com/breti&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@breti&lt;/a&gt;, whose QA testing and detailed issue reports ran through this whole
release and do not show up in any pull request count.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;security-and-provisioning-groundwork-for-en18031&quot;&gt;Security and Provisioning Groundwork for EN18031&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release lands three coordinated pieces of security infrastructure, led by
&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;, that together move ESPHome toward EN18031 compliance for network-connected
consumer devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NVS Encryption on ESP32 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17004&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17004&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;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 &lt;a href=&quot;https://esphome.io/components/esp32/&quot;&gt;esp32&lt;/a&gt; documentation carefully before
enabling this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OTA Downgrade Protection (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17315&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17315&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Software anti-rollback for signed ESP-IDF OTAs. The version baked into the staged image (from
&lt;code dir=&quot;auto&quot;&gt;project: version:&lt;/code&gt;) is compared against the running version before the boot partition is switched. Covers all OTA
sources: native, &lt;code dir=&quot;auto&quot;&gt;http_request.ota&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt;. Requires a signed OTA to be effective.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Provisioning Component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17152&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17152&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A new transport-agnostic &lt;a href=&quot;https://esphome.io/components/provisioning/&quot;&gt;provisioning&lt;/a&gt; component that manages a provisioning window for
devices shipping unprovisioned. Sources such as &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;esp32_improv&lt;/code&gt; register with the component, and the
window is closed on timeout, at which point any provisioning-related API clients are disconnected with
&lt;code dir=&quot;auto&quot;&gt;DISCONNECT_REASON_PROVISIONING_CLOSED&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;performance-single-precision-float-math&quot;&gt;Performance: Single-Precision Float Math&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;, a tree-wide sweep replaces silent
&lt;code dir=&quot;auto&quot;&gt;double&lt;/code&gt;-promotion patterns with single-precision equivalents across roughly 50 components
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17252&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17252&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17253&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17253&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17254&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17254&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17255&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17255&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17256&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17256&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17260&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17260&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The issue was invisible on ESP32 because ESP-IDF does not enable &lt;code dir=&quot;auto&quot;&gt;-Wdouble-promotion&lt;/code&gt;: literals like &lt;code dir=&quot;auto&quot;&gt;2.0&lt;/code&gt; and
functions like &lt;code dir=&quot;auto&quot;&gt;fmod&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;round&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;fabs&lt;/code&gt; 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 &lt;code dir=&quot;auto&quot;&gt;float&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Measured Impact:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;hsv_to_rgb&lt;/code&gt; code size&lt;/strong&gt;: 108 bytes → 69 bytes (&lt;code dir=&quot;auto&quot;&gt;-36%&lt;/code&gt;) on ESP32&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Soft-double helper calls eliminated&lt;/strong&gt;: roughly 8 per call site&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Components touched&lt;/strong&gt;: displays, lights, climate, most sensor drivers, &lt;code dir=&quot;auto&quot;&gt;openthread&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;mqtt&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;speaker&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;graph&lt;/code&gt;, and many more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The final straggler pass (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17260&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17260&lt;/a&gt;) also rewrites hot expressions
such as &lt;code dir=&quot;auto&quot;&gt;std::pow(2, sf)&lt;/code&gt; in &lt;a href=&quot;https://esphome.io/components/sx126x/&quot;&gt;sx126x&lt;/a&gt; to a constexpr bit shift, and switches a few call sites
to &lt;code dir=&quot;auto&quot;&gt;std::numbers::pi_v&amp;#x3C;float&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;memory-esp8266-dram-savings&quot;&gt;Memory: ESP8266 DRAM Savings&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Every byte of RAM matters on ESP8266, and three focused changes by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; reclaim a
useful chunk of DRAM without changing runtime behavior.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;libstdc++ throw message strings&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17341&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17341&lt;/a&gt;) — Overrides
&lt;code dir=&quot;auto&quot;&gt;std::__throw_*&lt;/code&gt; helpers so the never-read message arguments are dropped. Saves roughly 96 bytes of RAM on a
ratgdo build. Crash behavior is unchanged.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;lwIP glue DHCP stub strings&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17395&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17395&lt;/a&gt;) — Silent equivalents
for &lt;code dir=&quot;auto&quot;&gt;dhcp_cleanup()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;dhcp_release()&lt;/code&gt; stubs. Frees &lt;code dir=&quot;auto&quot;&gt;48&lt;/code&gt; bytes of RAM and &lt;code dir=&quot;auto&quot;&gt;88&lt;/code&gt; bytes of flash, and removes the
noisy &lt;code dir=&quot;auto&quot;&gt;STUB: dhcp_cleanup&lt;/code&gt; log on every WiFi disconnect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;dashboard_import package URL&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17127&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17127&lt;/a&gt;) — Moves the mDNS TXT
&lt;code dir=&quot;auto&quot;&gt;package_import_url&lt;/code&gt; string from &lt;code dir=&quot;auto&quot;&gt;.rodata&lt;/code&gt; (DRAM) to flash. It was the last mDNS TXT value pinned in RAM.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;build-system-ccache-and-shared-toolchain-caches&quot;&gt;Build System: ccache and Shared Toolchain Caches&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;, the ESP-IDF and nRF SDK toolchains gain both compiler-level
caching and installation-level sharing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ccache is now on by default for ESP-IDF builds&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17163&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17163&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17136&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17136&lt;/a&gt;) when the &lt;code dir=&quot;auto&quot;&gt;ccache&lt;/code&gt; binary is present, using depend mode
(depfile hashing instead of preprocessing) and a cache directory under the IDF tools path. Opt out with
&lt;code dir=&quot;auto&quot;&gt;IDF_CCACHE_ENABLE=0&lt;/code&gt;. On the 23-batch CI matrix, summed runner time dropped from &lt;code dir=&quot;auto&quot;&gt;543&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;504&lt;/code&gt; minutes (~7%) and
wall time from &lt;code dir=&quot;auto&quot;&gt;154&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;139&lt;/code&gt; minutes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Toolchains now install into a machine-global cache directory&lt;/strong&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17306&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17306&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17353&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17353&lt;/a&gt;). ESP-IDF installs to
&lt;code dir=&quot;auto&quot;&gt;~/.cache/esphome/idf&lt;/code&gt; and the nRF Connect SDK installs to &lt;code dir=&quot;auto&quot;&gt;~/.cache/esphome/sdk-nrf&lt;/code&gt;, 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Config validation got faster too&lt;/strong&gt;, thanks to import deferral by &lt;a href=&quot;https://github.com/frenck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@frenck&lt;/a&gt;:
&lt;code dir=&quot;auto&quot;&gt;aioesphomeapi.posix_tz&lt;/code&gt; deferral cuts &lt;code dir=&quot;auto&quot;&gt;esphome config&lt;/code&gt; median wall time by roughly 33% on a host config from
&lt;code dir=&quot;auto&quot;&gt;445&lt;/code&gt; ms to &lt;code dir=&quot;auto&quot;&gt;297&lt;/code&gt; ms (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17214&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17214&lt;/a&gt;), and deferring &lt;code dir=&quot;auto&quot;&gt;requests&lt;/code&gt; imports
shaves another ~70 ms (~16%) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17215&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17215&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;component-alias-infrastructure&quot;&gt;Component Alias Infrastructure&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A new core mechanism (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16826&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16826&lt;/a&gt;) lets components be renamed without
breaking existing YAML configurations. Components declare &lt;code dir=&quot;auto&quot;&gt;ALIASES = [...]&lt;/code&gt; (and an optional
&lt;code dir=&quot;auto&quot;&gt;ALIAS_REMOVAL_VERSION&lt;/code&gt;), and a pre-pass in config validation rewrites legacy keys while a &lt;code dir=&quot;auto&quot;&gt;sys.meta_path&lt;/code&gt; finder
resolves Python imports for &lt;code dir=&quot;auto&quot;&gt;esphome.components.&amp;#x3C;oldname&gt;&lt;/code&gt;. Aliases are discovered by an AST scan so components do
not need to be imported to enumerate them.&lt;/p&gt;
&lt;p&gt;The first user of the new infrastructure is the &lt;a href=&quot;https://esphome.io/components/rp2/&quot;&gt;rp2&lt;/a&gt; rename
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17145&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17145&lt;/a&gt;) by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;, which
renames the &lt;code dir=&quot;auto&quot;&gt;rp2040&lt;/code&gt; platform to &lt;code dir=&quot;auto&quot;&gt;rp2&lt;/code&gt; to reflect its coverage of both RP2040 and RP2350. The legacy &lt;code dir=&quot;auto&quot;&gt;rp2040:&lt;/code&gt;
YAML key and &lt;code dir=&quot;auto&quot;&gt;esphome.components.rp2040&lt;/code&gt; imports continue to work as deprecated aliases and will be removed in
2027.7.0. New &lt;code dir=&quot;auto&quot;&gt;rp2_2040&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;rp2_2350&lt;/code&gt; variant kwargs are added to &lt;code dir=&quot;auto&quot;&gt;SplitDefault&lt;/code&gt; and
&lt;code dir=&quot;auto&quot;&gt;require_framework_version&lt;/code&gt;, mirroring the ESP32 pattern.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;modbus-overhaul&quot;&gt;Modbus Overhaul&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; landed a major rework of the &lt;a href=&quot;https://esphome.io/components/modbus/&quot;&gt;modbus&lt;/a&gt; component across
multiple PRs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Client and server split&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11969&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11969&lt;/a&gt;) — &lt;code dir=&quot;auto&quot;&gt;Modbus&lt;/code&gt; is split into
&lt;code dir=&quot;auto&quot;&gt;ModbusClientHub&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ModbusServerHub&lt;/code&gt;, retiring the role enum entirely. Client components move to
&lt;code dir=&quot;auto&quot;&gt;ModbusClientDevice&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11987&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11987&lt;/a&gt;), and the core API surface was
renamed and settled before the release (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17434&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17434&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17378&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17378&lt;/a&gt;). External components need to update against the new
API now, and further client-mode API cleanup is planned for the next release.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rewritten parser&lt;/strong&gt; — 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 &lt;code dir=&quot;auto&quot;&gt;std::optional&amp;#x3C;ModbusDeviceCommand&gt;&lt;/code&gt;, enabling address+function-code matching, multiple devices per address,
and two new callbacks: &lt;code dir=&quot;auto&quot;&gt;on_modbus_no_response()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;on_modbus_not_sent()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Heap-free send path&lt;/strong&gt; — A new &lt;code dir=&quot;auto&quot;&gt;SmallInlineBuffer&amp;#x3C;8&gt;&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;StaticVector&amp;#x3C;uint8_t, MAX_PDU_SIZE&gt;&lt;/code&gt; 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 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17282&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17282&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Server improvements&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17205&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17205&lt;/a&gt;) — Multi-register values now
match by full span, a new &lt;code dir=&quot;auto&quot;&gt;allow_partial_read&lt;/code&gt; option is available, overlapping registers are rejected, and the
obsolete &lt;code dir=&quot;auto&quot;&gt;RAW&lt;/code&gt; value type has been removed from server mode.&lt;/p&gt;
&lt;p&gt;Default &lt;code dir=&quot;auto&quot;&gt;send_wait_time&lt;/code&gt; moves from &lt;code dir=&quot;auto&quot;&gt;250ms&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;2000ms&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;turnaround_time&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;100ms&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;600ms&lt;/code&gt;. If you were
overriding these to compensate for the old parser, review whether the overrides are still needed.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;lvgl-animations-rotation-and-runtime-updates&quot;&gt;LVGL: Animations, Rotation, and Runtime Updates&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; drove a substantial expansion of the &lt;a href=&quot;https://esphome.io/components/lvgl/&quot;&gt;lvgl&lt;/a&gt;
component this release.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Animations&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16796&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16796&lt;/a&gt;) — Full LVGL animation support with
from/to interpolation, timing functions (gravity and friends), duration, looping, and &lt;code dir=&quot;auto&quot;&gt;auto_start&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic rotation&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16773&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16773&lt;/a&gt;) — Templated
&lt;code dir=&quot;auto&quot;&gt;lvgl.display.set_rotation&lt;/code&gt; in degrees, new &lt;code dir=&quot;auto&quot;&gt;on_landscape&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;on_portrait&lt;/code&gt; triggers, and layout option updates
in &lt;code dir=&quot;auto&quot;&gt;lvgl.update&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Direct &lt;code dir=&quot;auto&quot;&gt;mapping&lt;/code&gt; syntax&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15863&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15863&lt;/a&gt;) — Cleaner LVGL text and
image &lt;code dir=&quot;auto&quot;&gt;src&lt;/code&gt; updates using a mapping directly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boot pausing&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16973&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16973&lt;/a&gt;) — A new &lt;code dir=&quot;auto&quot;&gt;paused&lt;/code&gt; config option
suppresses LVGL updates on boot. Especially useful for e-paper displays that should not render invalid state
before the API connects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continued activity while display busy&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17374&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17374&lt;/a&gt;) — When
&lt;code dir=&quot;auto&quot;&gt;update_when_display_idle&lt;/code&gt; 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.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;networking-and-connectivity&quot;&gt;Networking and Connectivity&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Gigabit Ethernet on ESP32-S31&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17277&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17277&lt;/a&gt;) — Adds
&lt;code dir=&quot;auto&quot;&gt;type: GENERIC&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;type: YT8531&lt;/code&gt; 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 &lt;code dir=&quot;auto&quot;&gt;power_pin&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;phy_registers&lt;/code&gt;
options are available on the &lt;a href=&quot;https://esphome.io/components/ethernet/&quot;&gt;ethernet&lt;/a&gt; component.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESP-NOW v2 payloads&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17360&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17360&lt;/a&gt;) — The
&lt;a href=&quot;https://esphome.io/components/espnow/&quot;&gt;espnow&lt;/a&gt; component gains a &lt;code dir=&quot;auto&quot;&gt;max_payload_size&lt;/code&gt; 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LN882X MQTT support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17297&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17297&lt;/a&gt;) — LN882H boards can finally use
the &lt;a href=&quot;https://esphome.io/components/mqtt/&quot;&gt;mqtt&lt;/a&gt; component. LN882X was previously blocked despite sharing the LibreTiny backend.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data whitening for SX126x&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17102&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17102&lt;/a&gt;) — Configurable FSK data
whitening (CCITT algorithm) via new &lt;code dir=&quot;auto&quot;&gt;whitening_enable&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;whitening_initial&lt;/code&gt; options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bluetooth proxy subscriber semantics&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17423&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17423&lt;/a&gt;) — 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.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;openthread-on-zephyrnrf52-and-mtd-polling-control&quot;&gt;OpenThread on Zephyr/nRF52 and MTD Polling Control&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Basic Zephyr/nRF52 support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16854&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16854&lt;/a&gt;) — First-cut
&lt;a href=&quot;https://esphome.io/components/openthread/&quot;&gt;openthread&lt;/a&gt; support on the nRF52 Zephyr platform, by
&lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt;. Handles the “join network” flow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Runtime poll period control&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11766&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11766&lt;/a&gt;) — A new
&lt;code dir=&quot;auto&quot;&gt;set_poll_period&lt;/code&gt; action lets a Minimal Thread Device (Sleepy End Device) temporarily switch to radio-always-on
for OTA. &lt;code dir=&quot;auto&quot;&gt;http_request.ota&lt;/code&gt; becomes roughly &lt;code dir=&quot;auto&quot;&gt;10x&lt;/code&gt; faster on MTDs, and &lt;code dir=&quot;auto&quot;&gt;esphome.ota&lt;/code&gt; starts working at all.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;rtc-backed-preferences-on-esp32&quot;&gt;RTC-Backed Preferences on ESP32&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/bootc&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bootc&lt;/a&gt; taught the ESP32 preferences backend to honor the &lt;code dir=&quot;auto&quot;&gt;in_flash=false&lt;/code&gt; flag of
&lt;code dir=&quot;auto&quot;&gt;make_preference()&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17073&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17073&lt;/a&gt;), adding RTC-memory-backed preferences
in the same way ESP8266 already had them. The shared word-buffer plus checksum format is extracted into
&lt;code dir=&quot;auto&quot;&gt;preferences_rtc.h&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;New configuration surface:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;safe_mode: storage: rtc&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;flash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;wifi: fast_connect:&lt;/code&gt; dict form with &lt;code dir=&quot;auto&quot;&gt;enabled&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;storage&lt;/code&gt; sub-options&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;preferences: rtc_storage: true&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-displays-touch-controllers-and-peripherals&quot;&gt;New Displays, Touch Controllers, and Peripherals&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The release adds broad support for new display and touch hardware, largely on M5Stack, Waveshare, and Seeed
reTerminal families.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Touch controllers&lt;/strong&gt; — &lt;a href=&quot;https://esphome.io/components/touchscreen/cst328/&quot;&gt;cst328&lt;/a&gt; by
&lt;a href=&quot;https://github.com/latonita&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@latonita&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/8011&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#8011&lt;/a&gt;),
&lt;a href=&quot;https://esphome.io/components/touchscreen/st7123/&quot;&gt;st7123&lt;/a&gt; integrated display-touch driver for the M5Stack Tab5 by
&lt;a href=&quot;https://github.com/miniskipper&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@miniskipper&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12075&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12075&lt;/a&gt;),
&lt;a href=&quot;https://esphome.io/components/touchscreen/gsl3670/&quot;&gt;gsl3670&lt;/a&gt; for Seeed reTerminal D1001 by
&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16285&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16285&lt;/a&gt;), and
&lt;a href=&quot;https://esphome.io/components/touchscreen/cst9220/&quot;&gt;cst9220&lt;/a&gt; covering CST9220 and CST9217 by
&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16888&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16888&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;E-paper displays&lt;/strong&gt; — The &lt;a href=&quot;https://esphome.io/components/display/epaper_spi/&quot;&gt;epaper_spi&lt;/a&gt; component picks up several new panels:
Waveshare 7.5” V2 BWR 800×480 by &lt;a href=&quot;https://github.com/twisterss&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@twisterss&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/15719&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15719&lt;/a&gt;),
Seeed reTerminal E1004 13.3” 6-color (T133A01, dual-CS SPI) by &lt;a href=&quot;https://github.com/limengdu&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@limengdu&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16706&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16706&lt;/a&gt;),
Waveshare 2.13” V4 BWR (SSD1683) by &lt;a href=&quot;https://github.com/profplump&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@profplump&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16828&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16828&lt;/a&gt;),
Soldered Inkplate 2 by &lt;a href=&quot;https://github.com/arunderwood&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@arunderwood&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16856&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16856&lt;/a&gt;),
and Seeed reTerminal-sticky by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16950&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16950&lt;/a&gt;). The &lt;a href=&quot;https://esphome.io/components/display/it8951/&quot;&gt;it8951&lt;/a&gt; e-paper
controller for M5Paper and Seeed reTerminal E1003/EE03 (up to 1872×1404, 16-level grayscale) arrives as a new
component by &lt;a href=&quot;https://github.com/Passific&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Passific&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/15346&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15346&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MIPI-SPI displays&lt;/strong&gt; — M5STACK ATOM3SR by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17344&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17344&lt;/a&gt;) and the Waveshare ESP32-S3-Touch-AMOLED-1.64 (SH8601)
by &lt;a href=&quot;https://github.com/crimike&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crimike&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17386&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17386&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Divoom Pixoo 64&lt;/strong&gt; — A new &lt;a href=&quot;https://esphome.io/components/display/pixoo/&quot;&gt;pixoo&lt;/a&gt; component by
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16974&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16974&lt;/a&gt;) drives the
64×64 RGB LED matrix over SPI and exposes a light platform for panel brightness alongside the image API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sensors and peripherals&lt;/strong&gt; — A &lt;a href=&quot;https://esphome.io/components/ufm01/&quot;&gt;ufm01&lt;/a&gt; ScioSense UFM-01 ultrasonic flow meter by
&lt;a href=&quot;https://github.com/ljungqvist&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ljungqvist&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16582&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16582&lt;/a&gt;) reports
accumulated flow, flow rate, water temperature, and four diagnostic binary sensors over UART. A
&lt;a href=&quot;https://esphome.io/components/sensor/qmi8658/&quot;&gt;qmi8658&lt;/a&gt; 6-axis IMU by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16889&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16889&lt;/a&gt;) adds accelerometer, gyroscope, and on-chip temperature
sensing with a motion platform. The &lt;a href=&quot;https://esphome.io/components/waveshare_io_ch32v003/&quot;&gt;waveshare_io_ch32v003&lt;/a&gt; I/O expander by
&lt;a href=&quot;https://github.com/latonita&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@latonita&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10071&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#10071&lt;/a&gt;) 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Audio&lt;/strong&gt; — The &lt;a href=&quot;https://esphome.io/components/audio_dac/pcm5122/&quot;&gt;pcm5122&lt;/a&gt; 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
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17313&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17313&lt;/a&gt;) by &lt;a href=&quot;https://github.com/remcom&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@remcom&lt;/a&gt;. The
&lt;a href=&quot;https://esphome.io/components/i2s_audio/&quot;&gt;i2s_audio&lt;/a&gt; speaker now accepts wider streams (e.g. 24-bit into a 16-bit device) and
narrows them in place using esp-audio-libs’ &lt;code dir=&quot;auto&quot;&gt;pcm_convert::copy_frames&lt;/code&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16821&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16821&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;image-component-becomes-a-platform&quot;&gt;Image Component Becomes a Platform&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; restructured &lt;code dir=&quot;auto&quot;&gt;image:&lt;/code&gt; into a platform component
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17416&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17416&lt;/a&gt;). The new form uses &lt;code dir=&quot;auto&quot;&gt;platform: file&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;platform: animation&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;platform: online_image&lt;/code&gt;, with &lt;code dir=&quot;auto&quot;&gt;animation&lt;/code&gt; becoming a proper sub-component of the
new file platform. The legacy top-level &lt;code dir=&quot;auto&quot;&gt;image:&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;animation:&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;online_image:&lt;/code&gt; keys continue to work through
2027.1.0 with copy-paste migration warnings shown at validation time.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;zigbee-sdk-2-0-2-and-endpoint-merging&quot;&gt;Zigbee: SDK 2.0.2 and Endpoint Merging&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; bumped the &lt;a href=&quot;https://esphome.io/components/zigbee/&quot;&gt;zigbee&lt;/a&gt; component on ESP32 to the new esp-zigbee-sdk
2.0.2 for better ESP-IDF compatibility and picked up ESP32-H4, H21, and S31 variants
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16869&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16869&lt;/a&gt;). 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.&lt;/p&gt;
&lt;p&gt;A follow-up (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17402&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17402&lt;/a&gt;) 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.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;yaml-merge-warnings&quot;&gt;YAML Merge Warnings&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; added a warning when a YAML merge (&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;&amp;#x3C;:&lt;/code&gt;) silently drops a key
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17246&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17246&lt;/a&gt;). Two top-level &lt;code dir=&quot;auto&quot;&gt;api:&lt;/code&gt; blocks combined via &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;&amp;#x3C;:&lt;/code&gt; would
previously drop one without any indication; ESPHome now prints the source location, explains that a merge is
happening, and suggests &lt;code dir=&quot;auto&quot;&gt;packages:&lt;/code&gt; for a deep merge instead. Toggle with &lt;code dir=&quot;auto&quot;&gt;esphome: merge_warnings: false&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;other-notable-features&quot;&gt;Other Notable Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Legacy web dashboard removed&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17124&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17124&lt;/a&gt;) — The built-in
Tornado-based dashboard is gone in favor of the external ESPHome Device Builder. The &lt;code dir=&quot;auto&quot;&gt;dashboard&lt;/code&gt; 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.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python 3.11 support dropped&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17280&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17280&lt;/a&gt;) — Minimum Python
version is now 3.12. Home Assistant add-on and Docker images are already on 3.12.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BK7238 and Tuya T1 board support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17288&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17288&lt;/a&gt;) — The
&lt;a href=&quot;https://esphome.io/components/libretiny/&quot;&gt;LibreTiny&lt;/a&gt; 1.13.0 update adds BK7238 boards to the &lt;code dir=&quot;auto&quot;&gt;bk72xx&lt;/code&gt; platform:
&lt;code dir=&quot;auto&quot;&gt;generic-bk7238&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;generic-bk7238-tuya&lt;/code&gt;, and the Tuya T1 module family (&lt;code dir=&quot;auto&quot;&gt;t1-2s&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;t1-3s&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;t1-m&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;t1-u&lt;/code&gt;),
which is becoming common in devices on the market.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PSRAM for ESP32-S31 and H4&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17192&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17192&lt;/a&gt;) — 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 &lt;code dir=&quot;auto&quot;&gt;esp_psram&lt;/code&gt;
Kconfig on ESP-IDF release/v6.1, and octal-mode validation is now data-driven rather than hardcoded to S3.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Host platform preferences directory&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11160&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11160&lt;/a&gt;) — A new
&lt;code dir=&quot;auto&quot;&gt;ESPHOME_PREFDIR&lt;/code&gt; environment variable overrides where the &lt;a href=&quot;https://esphome.io/components/host/&quot;&gt;host&lt;/a&gt; platform stores
preferences, useful when running ESPHome as a system service where &lt;code dir=&quot;auto&quot;&gt;HOME&lt;/code&gt; may not be set.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web server SSE optimization&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17400&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17400&lt;/a&gt;) — Logger’s known
message length is now threaded through the SSE send path, avoiding &lt;code dir=&quot;auto&quot;&gt;strlen&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;strchr&lt;/code&gt; rescans on every log
event. No wire changes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web server HTTP digest authentication&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17541&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17541&lt;/a&gt;) —
&lt;a href=&quot;https://esphome.io/components/web_server/&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt;&lt;/a&gt; &lt;code dir=&quot;auto&quot;&gt;auth:&lt;/code&gt; gains a new &lt;code dir=&quot;auto&quot;&gt;type:&lt;/code&gt; option to select &lt;code dir=&quot;auto&quot;&gt;basic&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;digest&lt;/code&gt;.
Digest keeps the password off the network (only hashes are sent) instead of the trivially reversible Base64
that Basic uses; both look identical in the browser. The scheme is fixed at build time so the unused code
path is compiled out. The default stays &lt;code dir=&quot;auto&quot;&gt;basic&lt;/code&gt; for now to avoid breaking non-browser REST clients and will
change to &lt;code dir=&quot;auto&quot;&gt;digest&lt;/code&gt; in 2027.1.0; set &lt;code dir=&quot;auto&quot;&gt;type: basic&lt;/code&gt; explicitly to keep the current behavior after that release.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WiFi roaming scan suppression&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17012&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17012&lt;/a&gt;) — A new internal API
lets components request that post-connect roaming scans be paused. First user is
&lt;a href=&quot;https://esphome.io/components/sendspin/&quot;&gt;sendspin&lt;/a&gt;, which now suppresses roaming scans while playing to prevent audible hiccups
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17133&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17133&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runtime UART reconfiguration&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16990&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16990&lt;/a&gt;) — Baud rate, parity,
and other UART settings can now be changed at runtime on open channels without reconnecting. Landed for both
the standard &lt;a href=&quot;https://esphome.io/components/uart/&quot;&gt;uart&lt;/a&gt; and &lt;a href=&quot;https://esphome.io/components/usb_uart/&quot;&gt;usb_uart&lt;/a&gt; components.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Light brightness on turn-off preservation&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17103&lt;/a&gt;) —
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.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;coex/sdkconfig reconciler&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17008&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17008&lt;/a&gt;) — A single reconciler
now handles WiFi/Ethernet/BLE coexistence sdkconfig flags on ESP32, killing conflicting values (for example
&lt;code dir=&quot;auto&quot;&gt;ethernet&lt;/code&gt; versus &lt;code dir=&quot;auto&quot;&gt;esp32_ble_tracker&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;CONFIG_SW_COEXIST_ENABLE&lt;/code&gt;). Behavior is preserved and internal
helpers gain semantic names such as &lt;code dir=&quot;auto&quot;&gt;request_wifi&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;request_ethernet&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;request_software_coexistence&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visual editor visibility hints&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/17449&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17449&lt;/a&gt;) — Build-system and
framework internals are now marked with &lt;code dir=&quot;auto&quot;&gt;cv.Visibility&lt;/code&gt; so the Device Builder visual editor can hide them from
users who edit YAML from the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;thank-you-contributors&quot;&gt;Thank You, Contributors&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;This release includes 217 pull requests from over 30 contributors. A huge thank you to everyone who made
2026.7.0 possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; - 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&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; - 45 PRs including the generic component alias infrastructure,
the &lt;code dir=&quot;auto&quot;&gt;final&lt;/code&gt; 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&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - 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&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; - 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&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; - 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&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; - 6 PRs including WiFi roaming-scan suppression, the [sendspin]
playback integration, [i2s_audio] stream narrowing, and microMP3 bumps&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt; - 5 PRs extending nRF52/Zephyr networking: BSD socket support,
basic OpenThread, mDNS, [api] support, and enlarged Zephyr net buffers&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; - 4 PRs including ESP32 NVS encryption, OTA downgrade protection, the
new [provisioning] component, and the ESP32 network/coexistence sdkconfig reconciler&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt; - 4 PRs including [usb_uart] per-device baud caps, FTDI RX
stability fixes, and a vector &lt;code dir=&quot;auto&quot;&gt;pop_back&lt;/code&gt; helper&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; - 3 PRs including the [zigbee] SDK 2.0.2 bump and endpoint merging
on esp32&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/frenck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@frenck&lt;/a&gt; - 3 PRs deferring &lt;code dir=&quot;auto&quot;&gt;aioesphomeapi&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;requests&lt;/code&gt; imports to speed up
config validation, and refining ESP32-S3 PSRAM pin warnings&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/latonita&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@latonita&lt;/a&gt; - 2 PRs including the new [cst328] touchscreen and the
[waveshare_io_ch32v003] I/O expander&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt; - 2 PRs including the [openthread] &lt;code dir=&quot;auto&quot;&gt;set_poll_period&lt;/code&gt; action for
MTDs and a [socket] wake-request gate fix&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/anunayk&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@anunayk&lt;/a&gt; - 2 PRs including Zephyr GPIO interrupts and [ble_nus] atomic log
framing&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/remcom&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@remcom&lt;/a&gt; - 2 PRs including the [pcm5122] analog gain, channel mixing, and
standby/powerdown work, plus [audio_file] MP3 detection fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/miniskipper&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@miniskipper&lt;/a&gt; - the new [st7123] touch controller component for the M5Stack
Tab5&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Passific&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Passific&lt;/a&gt; - the new [it8951] e-paper controller component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ljungqvist&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ljungqvist&lt;/a&gt; - the new [ufm01] ultrasonic flow meter component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bootc&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bootc&lt;/a&gt; - RTC-backed preferences on ESP32, honoring the &lt;code dir=&quot;auto&quot;&gt;in_flash&lt;/code&gt; flag&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also thank you to &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, &lt;a href=&quot;https://github.com/haku&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@haku&lt;/a&gt;,
&lt;a href=&quot;https://github.com/Eelviny&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Eelviny&lt;/a&gt;, &lt;a href=&quot;https://github.com/twisterss&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@twisterss&lt;/a&gt;,
&lt;a href=&quot;https://github.com/ddrown&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ddrown&lt;/a&gt;, &lt;a href=&quot;https://github.com/limengdu&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@limengdu&lt;/a&gt;,
&lt;a href=&quot;https://github.com/profplump&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@profplump&lt;/a&gt;, &lt;a href=&quot;https://github.com/arunderwood&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@arunderwood&lt;/a&gt;,
&lt;a href=&quot;https://github.com/kyvaith&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kyvaith&lt;/a&gt;, &lt;a href=&quot;https://github.com/jspiros&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jspiros&lt;/a&gt;,
&lt;a href=&quot;https://github.com/guillempages&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@guillempages&lt;/a&gt;, &lt;a href=&quot;https://github.com/zeroflow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@zeroflow&lt;/a&gt;,
&lt;a href=&quot;https://github.com/mikelawrence&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mikelawrence&lt;/a&gt;, &lt;a href=&quot;https://github.com/jclehner&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jclehner&lt;/a&gt;,
&lt;a href=&quot;https://github.com/berikv&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@berikv&lt;/a&gt;, &lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt;,
and &lt;a href=&quot;https://github.com/crimike&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crimike&lt;/a&gt; for their contributions, and to everyone who reported issues,
tested pre-releases, and helped in the community.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;platform-changes&quot;&gt;Platform Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32&lt;/strong&gt;: ESP-IDF is now the default toolchain when no explicit &lt;code dir=&quot;auto&quot;&gt;toolchain:&lt;/code&gt; is set. Add
&lt;code dir=&quot;auto&quot;&gt;toolchain: platformio&lt;/code&gt; to your &lt;code dir=&quot;auto&quot;&gt;esp32:&lt;/code&gt; block to keep building with PlatformIO
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16910&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16910&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt;: Minimum supported Python bumped to 3.12. Home Assistant add-on and Docker are unaffected; only
direct &lt;code dir=&quot;auto&quot;&gt;pip&lt;/code&gt; installs on 3.11 need to upgrade &lt;a href=&quot;https://github.com/esphome/esphome/pull/17280&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17280&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nRF52&lt;/strong&gt;: The native nRF Connect SDK toolchain is now the default when no explicit &lt;code dir=&quot;auto&quot;&gt;toolchain:&lt;/code&gt; is set. Add
&lt;code dir=&quot;auto&quot;&gt;toolchain: platformio&lt;/code&gt; to your &lt;code dir=&quot;auto&quot;&gt;nrf52:&lt;/code&gt; block to keep building with PlatformIO
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17319&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17319&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nRF52&lt;/strong&gt;: 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
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17373&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17373&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;dashboard&quot;&gt;Dashboard&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Legacy Dashboard&lt;/strong&gt;: The built-in Tornado web dashboard has been removed. Users installing via &lt;code dir=&quot;auto&quot;&gt;pip&lt;/code&gt; should
install and run &lt;a href=&quot;https://github.com/esphome/device-builder&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome-device-builder&lt;/a&gt; instead. Docker and Home
Assistant add-on users are unaffected &lt;a href=&quot;https://github.com/esphome/esphome/pull/17124&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17124&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bluetooth Proxy&lt;/strong&gt;: 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 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17423&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17423&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hub75&lt;/strong&gt;: The deprecated &lt;code dir=&quot;auto&quot;&gt;scan_wiring&lt;/code&gt; names &lt;code dir=&quot;auto&quot;&gt;FOUR_SCAN_16PX_HIGH&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;FOUR_SCAN_32PX_HIGH&lt;/code&gt;, and
&lt;code dir=&quot;auto&quot;&gt;FOUR_SCAN_64PX_HIGH&lt;/code&gt; have been removed. Use &lt;code dir=&quot;auto&quot;&gt;SCAN_1_4_16PX_HIGH&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SCAN_1_8_32PX_HIGH&lt;/code&gt;, and
&lt;code dir=&quot;auto&quot;&gt;SCAN_1_8_64PX_HIGH&lt;/code&gt; instead &lt;a href=&quot;https://github.com/esphome/esphome/pull/17118&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17118&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Light&lt;/strong&gt;: Setting brightness to &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt; no longer silently clamps to &lt;code dir=&quot;auto&quot;&gt;1.0&lt;/code&gt;. If a subsequent turn-on has no
explicit brightness and the current brightness is &lt;code dir=&quot;auto&quot;&gt;0&lt;/code&gt;, brightness is restored to &lt;code dir=&quot;auto&quot;&gt;1.0&lt;/code&gt; at turn-on time instead
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17103&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LibreTiny (LN882H)&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;generic-ln882hki&lt;/code&gt; board removed; use &lt;code dir=&quot;auto&quot;&gt;generic-ln882h&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;generic-ln882h-tuya&lt;/code&gt;
depending on factory firmware. Default LN882H log UART is now &lt;code dir=&quot;auto&quot;&gt;UART1&lt;/code&gt;. LN882H partition layouts changed
(on-device OTA migration handled by LibreTiny). On the &lt;code dir=&quot;auto&quot;&gt;wb02a&lt;/code&gt; board, pin aliases shifted (&lt;code dir=&quot;auto&quot;&gt;D1&lt;/code&gt; → GPIO6,
&lt;code dir=&quot;auto&quot;&gt;D7&lt;/code&gt; → GPIO5, &lt;code dir=&quot;auto&quot;&gt;D8&lt;/code&gt; → GPIO9, &lt;code dir=&quot;auto&quot;&gt;D9&lt;/code&gt; → GPIO24, new &lt;code dir=&quot;auto&quot;&gt;D10&lt;/code&gt; → GPIO25) and default I2C pin order changed
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17288&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17288&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;disable_crc&lt;/code&gt; option has been removed, along with &lt;code dir=&quot;auto&quot;&gt;send_wait_time&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;turnaround_time&lt;/code&gt; from
server mode. Client-mode defaults were raised: &lt;code dir=&quot;auto&quot;&gt;send_wait_time&lt;/code&gt; 250ms → 2000ms, &lt;code dir=&quot;auto&quot;&gt;turnaround_time&lt;/code&gt; 100ms →
600ms &lt;a href=&quot;https://github.com/esphome/esphome/pull/11969&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11969&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Packages&lt;/strong&gt;: The single-package &lt;code dir=&quot;auto&quot;&gt;!include&lt;/code&gt; form is removed. Wrap the include in a list:
&lt;code dir=&quot;auto&quot;&gt;packages: [!include mypackage.yaml]&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/17119&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17119&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Server&lt;/strong&gt;: The deprecated object ID URL matching fallback has been removed. URLs are matched by entity
name only &lt;a href=&quot;https://github.com/esphome/esphome/pull/17113&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17113&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Server&lt;/strong&gt;: Version 1 is deprecated. A configuration warning is emitted when &lt;code dir=&quot;auto&quot;&gt;version: 1&lt;/code&gt; is set;
removal is targeted for 2027.1.0. Migrate to v2 (the default) or v3
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17109&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17109&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Server&lt;/strong&gt;: Cross-origin browser requests carrying an &lt;code dir=&quot;auto&quot;&gt;Origin&lt;/code&gt; header are now rejected unless the origin
matches the request &lt;code dir=&quot;auto&quot;&gt;Host&lt;/code&gt; (same-origin) or is listed in the new &lt;code dir=&quot;auto&quot;&gt;allowed_origins:&lt;/code&gt; option. Requests with
no &lt;code dir=&quot;auto&quot;&gt;Origin&lt;/code&gt; header (curl, native API, other non-browser clients) are always allowed, so this
is defense-in-depth against the browser confused-deputy/CSRF case, not an authentication boundary. Private
Network Access is now off by default (previously on) and, when enabled, reuses &lt;code dir=&quot;auto&quot;&gt;allowed_origins:&lt;/code&gt; to
authorize preflights; enabling PNA without any allowed origins is rejected at config validation
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17530&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17530&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zigbee&lt;/strong&gt;: The Zigbee SDK bump to 2.0.2 changes the storage layout, so ESP32 devices must be re-joined and
reconfigured after upgrading. The &lt;code dir=&quot;auto&quot;&gt;reporting:&lt;/code&gt; config values &lt;code dir=&quot;auto&quot;&gt;enabled&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;coordinator&lt;/code&gt; are no longer valid
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16869&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16869&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zigbee&lt;/strong&gt;: on ESP32 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
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17402&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17402&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display Components&lt;/strong&gt;: The MIPI family of display drivers (&lt;code dir=&quot;auto&quot;&gt;mipi_spi&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;mipi_dsi&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;mipi_rgb&lt;/code&gt;) now enforce
configuration of mandatory components such as PSRAM and I/O expanders where required. This applies only to those
display models that identify integrated boards with known hardware assignments.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17405&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17405&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;undocumented-api-changes&quot;&gt;Undocumented API Changes&lt;/h3&gt;&lt;/div&gt;

&lt;p&gt;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 &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; allocation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Core&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;value_accuracy_to_string()&lt;/code&gt; has been removed. Use &lt;code dir=&quot;auto&quot;&gt;value_accuracy_to_buf()&lt;/code&gt;, which writes into a
caller-provided buffer of &lt;code dir=&quot;auto&quot;&gt;VALUE_ACCURACY_MAX_LEN&lt;/code&gt; bytes.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17116&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17116&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std::string s &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value_accuracy_to_string&lt;/span&gt;&lt;span&gt;(value, accuracy);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;buf&lt;/span&gt;&lt;span&gt;[VALUE_ACCURACY_MAX_LEN];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;value_accuracy_to_buf&lt;/span&gt;&lt;span&gt;(buf, value, accuracy);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remote Base (Midea)&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;MideaData::to_string()&lt;/code&gt; has been removed. Use &lt;code dir=&quot;auto&quot;&gt;to_str(buffer)&lt;/code&gt; instead, which
formats into a caller-provided buffer. &lt;a href=&quot;https://github.com/esphome/esphome/pull/17117&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17117&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;std::string s &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_string&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;buf&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_str&lt;/span&gt;&lt;span&gt;(buf);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dashboard Import (ESP8266)&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;package_import_url&lt;/code&gt; is now stored as a PROGMEM flash literal
(&lt;code dir=&quot;auto&quot;&gt;ProgmemStr&lt;/code&gt;) rather than a plain &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt; in DRAM. Existing consumers already read it as a flash
pointer (mDNS via &lt;code dir=&quot;auto&quot;&gt;MDNS_STR_ARG&lt;/code&gt;, MQTT via ArduinoJson’s &lt;code dir=&quot;auto&quot;&gt;__FlashStringHelper&lt;/code&gt; overload), so this is a
transparent change on ESP8266 and a no-op on other platforms. Lambdas that read &lt;code dir=&quot;auto&quot;&gt;package_import_url&lt;/code&gt; on
ESP8266 should not dereference it as a plain &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt;.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17127&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17127&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modbus API split&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;Modbus&lt;/code&gt; is split into &lt;code dir=&quot;auto&quot;&gt;ModbusClientHub&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ModbusServerHub&lt;/code&gt;;
&lt;code dir=&quot;auto&quot;&gt;ModbusDevice::set_parent()&lt;/code&gt; now takes &lt;code dir=&quot;auto&quot;&gt;ModbusClientHub *&lt;/code&gt;; &lt;code dir=&quot;auto&quot;&gt;Modbus::register_device()&lt;/code&gt; removed
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/11969&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11969&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/11987&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11987&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/12376&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12376&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus API naming&lt;/strong&gt;: Core public API surface renamed and settled before release; further client-mode API
cleanup is planned for the next release
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17378&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17378&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17434&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17434&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus function code comparisons&lt;/strong&gt;: Ordering operators (&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;=&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;&gt;&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;&gt;=&lt;/code&gt;) between &lt;code dir=&quot;auto&quot;&gt;ModbusFunctionCode&lt;/code&gt;
and &lt;code dir=&quot;auto&quot;&gt;uint8_t&lt;/code&gt; removed. Cast explicitly or use &lt;code dir=&quot;auto&quot;&gt;helpers::is_function_code_*()&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/11969&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11969&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Select &lt;code dir=&quot;auto&quot;&gt;state&lt;/code&gt; member removed&lt;/strong&gt;: Use &lt;code dir=&quot;auto&quot;&gt;current_option()&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;active_index()&lt;/code&gt; instead
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17027&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17027&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scheduler &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; overloads removed&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;App.scheduler.set_timeout(std::string, ...)&lt;/code&gt; and related
&lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;-name overloads are gone; pass &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt; names
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17111&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17111&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;get_object_id()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;get_compilation_time()&lt;/code&gt; removed&lt;/strong&gt;: Previously deprecated core helpers deleted
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17112&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17112&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;GPIOPin::dump_summary()&lt;/code&gt; returning &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; removed&lt;/strong&gt;: Overrides must return via the buffer form
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17115&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17115&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART &lt;code dir=&quot;auto&quot;&gt;load_settings(bool)&lt;/code&gt; is now pure virtual&lt;/strong&gt;: All &lt;code dir=&quot;auto&quot;&gt;UARTComponent&lt;/code&gt; subclasses must implement runtime
settings updates &lt;a href=&quot;https://github.com/esphome/esphome/pull/16990&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16990&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API pre-1.14 object_id backward-compat removed&lt;/strong&gt;: Old client fallback path deleted
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17108&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17108&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preferences RTC helpers moved&lt;/strong&gt;: Word-buffer + checksum format extracted to &lt;code dir=&quot;auto&quot;&gt;preferences_rtc.h&lt;/code&gt; and shared
between ESP32/ESP8266 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17073&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17073&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network &lt;code dir=&quot;auto&quot;&gt;use_address&lt;/code&gt; logging changes&lt;/strong&gt;: Runtime MAC-suffix expansion moved into the network component
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17432&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17432&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configurable classes marked &lt;code dir=&quot;auto&quot;&gt;final&lt;/code&gt;&lt;/strong&gt;: Roughly 20 batches of components add &lt;code dir=&quot;auto&quot;&gt;final&lt;/code&gt; to their
runtime-instantiated concrete classes to allow devirtualization
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16952&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16952&lt;/a&gt;-&lt;a href=&quot;https://github.com/esphome/esphome/pull/16972&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16972&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17129&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17129&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17130&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17130&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17147&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17147&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;rp2040&lt;/code&gt; component renamed to &lt;code dir=&quot;auto&quot;&gt;rp2&lt;/code&gt;&lt;/strong&gt;: Python imports &lt;code dir=&quot;auto&quot;&gt;esphome.components.rp2040&lt;/code&gt; and the &lt;code dir=&quot;auto&quot;&gt;rp2040:&lt;/code&gt; YAML key
continue to work as deprecated aliases through 2027.7.0 via the new alias infrastructure
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/17145&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17145&lt;/a&gt;,
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16826&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16826&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;mipi_&lt;/code&gt; display driver model config changes&lt;/strong&gt;: Use of &lt;code dir=&quot;auto&quot;&gt;swap_xy=cv.UNDEFINED&lt;/code&gt; in a model definition is deprecated.
&lt;a href=&quot;https://github.com/esphome/esphome/pull/17405&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#17405&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the
&lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-7-1---july-21&quot;&gt;Release 2026.7.1 - July 21&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[emc2101] Fix negative external temperatures reported as large positives &lt;a href=&quot;https://github.com/esphome/esphome/pull/17494&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17494&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[haier] Fix outdoor defrost temperature reporting the coil temperature &lt;a href=&quot;https://github.com/esphome/esphome/pull/17492&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17492&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[zephyr] implement ISRInternalGPIOPin::digital_write &lt;a href=&quot;https://github.com/esphome/esphome/pull/17601&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17601&lt;/a&gt; by &lt;a href=&quot;https://github.com/quantum5&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@quantum5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[as3935_i2c] Use repeated start when reading registers &lt;a href=&quot;https://github.com/esphome/esphome/pull/17584&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17584&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[micro_wake_word] Include the local model file in bundles &lt;a href=&quot;https://github.com/esphome/esphome/pull/17604&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17604&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Improve framework mirror selection, download errors, and version parsing &lt;a href=&quot;https://github.com/esphome/esphome/pull/17615&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17615&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Fix use-after-return of header collection state in IDF backend &lt;a href=&quot;https://github.com/esphome/esphome/pull/17627&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17627&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[web_server_idf] Use core format_hex_to helper for digest auth (fixes Arduino build) &lt;a href=&quot;https://github.com/esphome/esphome/pull/17608&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17608&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[nrf52] Set ZEPHYR_SDK_INSTALL_DIR for Zephyr SDK discovery &lt;a href=&quot;https://github.com/esphome/esphome/pull/17633&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17633&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17640&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17640&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump aioesphomeapi from 45.6.0 to 45.6.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17653&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17653&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump aioesphomeapi from 45.6.1 to 45.6.2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17654&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17654&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.3 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17651&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17651&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Suggest installing missing system libraries when the tools install fails &lt;a href=&quot;https://github.com/esphome/esphome/pull/17619&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17619&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix srcFilter exclusions being silently ignored on Windows &lt;a href=&quot;https://github.com/esphome/esphome/pull/17648&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17648&lt;/a&gt; by &lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pin cryptography to 48.0.1 on Intel macOS &lt;a href=&quot;https://github.com/esphome/esphome/pull/17658&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17658&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ship component requirements.txt files in the sdist and wheel &lt;a href=&quot;https://github.com/esphome/esphome/pull/17660&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17660&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[logs] Cap the logs reconnect backoff for deep-sleep devices &lt;a href=&quot;https://github.com/esphome/esphome/pull/17656&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17656&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[nrf52] Install PlatformIO toolchain Python packages into a dedicated venv &lt;a href=&quot;https://github.com/esphome/esphome/pull/17635&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17635&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.4 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17662&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17662&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Bump recommended ESP-IDF to 5.5.5 and Arduino to 3.3.10 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17669&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17669&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.5 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17675&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17675&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.6 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17681&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17681&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.7 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17696&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17696&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Split multi-token build.flags entries when generating ESP-IDF component CMakeLists &lt;a href=&quot;https://github.com/esphome/esphome/pull/17649&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17649&lt;/a&gt; by &lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ssd1306] Fix offset_x being ignored on SH1106/SH1107 displays &lt;a href=&quot;https://github.com/esphome/esphome/pull/17700&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17700&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[micro_wake_word] Download models in parallel &lt;a href=&quot;https://github.com/esphome/esphome/pull/17701&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17701&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[platformio] Accept git URLs passed as the library name &lt;a href=&quot;https://github.com/esphome/esphome/pull/17697&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17697&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[git] Detect interrupted clones and re-clone automatically &lt;a href=&quot;https://github.com/esphome/esphome/pull/17690&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17690&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Make openocd-esp32 optional so its libusb check cannot break installs &lt;a href=&quot;https://github.com/esphome/esphome/pull/17686&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17686&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[light] Fix pulse and other effects &lt;a href=&quot;https://github.com/esphome/esphome/pull/17645&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17645&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.8 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17708&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17708&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Auto-clean the PlatformIO build environment when the Python version changes &lt;a href=&quot;https://github.com/esphome/esphome/pull/17671&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17671&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[platformio] Re-download library when cached copy is missing its manifest &lt;a href=&quot;https://github.com/esphome/esphome/pull/17691&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17691&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Fix usage of http response body &lt;a href=&quot;https://github.com/esphome/esphome/pull/17713&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17713&lt;/a&gt; by &lt;a href=&quot;https://github.com/kamaradclimber&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kamaradclimber&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[platformio] Include cache path in invalid library error &lt;a href=&quot;https://github.com/esphome/esphome/pull/17692&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17692&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Resume interrupted toolchain downloads instead of restarting &lt;a href=&quot;https://github.com/esphome/esphome/pull/17706&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17706&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wireguard] Mark private keys sensitive, stop redacting public keys &lt;a href=&quot;https://github.com/esphome/esphome/pull/17736&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17736&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp8266] Fail fast when Rosetta 2 is missing on Apple Silicon Macs &lt;a href=&quot;https://github.com/esphome/esphome/pull/17737&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17737&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-7-2---july-23&quot;&gt;Release 2026.7.2 - July 23&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Bump aioesphomeapi from 45.6.2 to 45.7.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17768&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17768&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sen5x] Add model option to override autodetection &lt;a href=&quot;https://github.com/esphome/esphome/pull/17764&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17764&lt;/a&gt; by &lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sendspin] Bump sendspin-cpp to v0.7.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17781&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17781&lt;/a&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] fix partial update bug &lt;a href=&quot;https://github.com/esphome/esphome/pull/17747&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17747&lt;/a&gt; by &lt;a href=&quot;https://github.com/Flautz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Flautz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bundle] Remap absolute file paths when compiling an extracted bundle &lt;a href=&quot;https://github.com/esphome/esphome/pull/17765&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17765&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.9 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17793&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17793&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-7-3---july-28&quot;&gt;Release 2026.7.3 - July 28&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.6.10 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17801&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17801&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble] Forward ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT to GAP handlers &lt;a href=&quot;https://github.com/esphome/esphome/pull/17833&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17833&lt;/a&gt; by &lt;a href=&quot;https://github.com/mvoss96&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mvoss96&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Honor compile_process_limit in native ESP-IDF builds &lt;a href=&quot;https://github.com/esphome/esphome/pull/17857&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17857&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Include .cc, .cxx and .c++ sources in the app source glob &lt;a href=&quot;https://github.com/esphome/esphome/pull/17754&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17754&lt;/a&gt; by &lt;a href=&quot;https://github.com/ruimarinho&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ruimarinho&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.7.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17871&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17871&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Lock scan results shared with the captive portal web task &lt;a href=&quot;https://github.com/esphome/esphome/pull/17850&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17850&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[git] Fix submodule update failure when cloning libraries on the esp-idf toolchain &lt;a href=&quot;https://github.com/esphome/esphome/pull/17862&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17862&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[captive_portal] Escape SSID when building config JSON &lt;a href=&quot;https://github.com/esphome/esphome/pull/17872&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17872&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ethernet] Set SPI CS hold time for ENC28J60 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17885&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17885&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; (breaking-change)&lt;/li&gt;
&lt;li&gt;[light] Ensure binary light is off with brightness 0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17893&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17893&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Update webserver local assets to 20260728-053845 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17899&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17899&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-7-4---august-5&quot;&gt;Release 2026.7.4 - August 5&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Bump filelock from 3.29.0 to 3.32.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17759&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17759&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump platformdirs from 4.10.0 to 4.11.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17756&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17756&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.8.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17953&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17953&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.8.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17964&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17964&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[epaper_spi] Default init sequence to empty not None &lt;a href=&quot;https://github.com/esphome/esphome/pull/17966&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17966&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[git] Fix device adoption failing on first attempt: lock the clone cache against concurrent resolutions &lt;a href=&quot;https://github.com/esphome/esphome/pull/17923&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17923&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Use forward slashes in generated component CMakeLists &lt;a href=&quot;https://github.com/esphome/esphome/pull/17965&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17965&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Restrict toolchain validation to supported values &lt;a href=&quot;https://github.com/esphome/esphome/pull/17972&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17972&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fix double free when overflow buffer drain is re-entered &lt;a href=&quot;https://github.com/esphome/esphome/pull/17969&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17969&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.8.2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17995&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17995&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.9.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18017&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18017&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.9.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18025&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18025&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.9.2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18051&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18051&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] explicitly disable BLE 5.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/18047&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#18047&lt;/a&gt; by &lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.7.0/&quot;&gt;full 2026.7.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>Unbox your creativity with the ESPHome Device Builder</title><link>https://esphome.io/blog/2026/07/02/unbox-your-creativity-with-the-esphome-device-builder/</link><guid isPermaLink="true">https://esphome.io/blog/2026/07/02/unbox-your-creativity-with-the-esphome-device-builder/</guid><description>Discover a more approachable way to bring your smart home ideas to life: the new visual Device Builder in the latest ESPHome release.</description><pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The ESPHome blog is a new space for us – and you! We usually share our updates through raw, engineering-focused
changelogs. While that
&lt;a href=&quot;https://esphome.io/blog/2026/06/17/esphome-2026-6/#esphome-device-builder-replaces-the-legacy-dashboard&quot;&gt;technical documentation&lt;/a&gt;
isn’t going anywhere, we want to make our milestone releases more digestible for everyone in the community – regardless
of your experience with creating custom smart home devices.&lt;/p&gt;
&lt;p&gt;This new way of sharing information goes hand-in-hand with all the work we’ve been doing to make ESPHome (and all
&lt;a href=&quot;https://www.openhomefoundation.org/projects/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Open Home Foundation projects&lt;/a&gt;) more accessible. It’s also why the
latest release of ESPHome is focused on lowering the barrier to entry: a shift especially relevant with the highly
anticipated release of the ESPHome Starter Kit around the corner.&lt;/p&gt;
&lt;p&gt;By moving towards intuitive visual interfaces and optimizing how our microcontrollers manage processing power, we’re
making the ecosystem more approachable for complete beginners without sacrificing the depth, control, and granular
flexibility our more experienced users love.&lt;/p&gt;
&lt;p&gt;Think of this update as a thorough organizing of a communal workshop, ensuring your local devices run faster, utilize
less memory, and stand ready as durable components of a private, sustainable smart home.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;making-esphome-more-accessible&quot;&gt;Making ESPHome more accessible&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With this in mind, let’s look at the updates designed to make your life easier. Part of the satisfaction of creating
your own smart home gear is the process itself: embracing the sometimes chaotic, but joyful, mess of wires and
components scattered across your desk. We want to enhance that creative, hands-on experience, while stripping away the
unnecessary technical frustrations that can block a good project from getting off the ground.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;explore-with-the-new-esphome-device-builder&quot;&gt;Explore with the new ESPHome Device Builder&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To do this, we’ve officially retired the old text-heavy dashboard and replaced it with a visual workspace designed to
remove the guesswork and get your project up and running without headaches. Think of it like baking a cake from
scratch. The pleasure comes from mixing the ingredients yourself, but you still want a recipe that’s easy to follow and
promises a tasty result: in this sense the new Device Builder 1.0.0 is what you need!&lt;/p&gt;
&lt;p&gt;Rather than serving as a blank text editor, the new builder is a tool for creative discovery. It features an
interactive component catalog that suggests ideas and layout configurations as you build, transforming a technical task
into an exploration of what’s possible.&lt;/p&gt;
&lt;p&gt;And don’t worry, if you enjoy editing the YAML directly, you still can!&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://esphome.io/_astro/esphome-device-builder-ui._BV2DVMg_ZuoYYr.webp&quot; srcset=&quot;/_astro/esphome-device-builder-ui._BV2DVMg_Z2gC3Dh.webp 480w, /_astro/esphome-device-builder-ui._BV2DVMg_17YpvX.webp 768w, /_astro/esphome-device-builder-ui._BV2DVMg_Z2iulDD.webp 1024w, /_astro/esphome-device-builder-ui._BV2DVMg_1Hxg96.webp 1200w, /_astro/esphome-device-builder-ui._BV2DVMg_ZuoYYr.webp 1919w&quot; alt=&quot;A screenshot of the ESPHome Device Builder interface, showing a successful device configuration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1919px) 1919px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-fit=&quot;cover&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1919&quot; height=&quot;1031&quot;&gt;&lt;figcaption&gt;&lt;span&gt;View your configurations as simple steps, or as code, as you prefer.&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;That same flexibility applies to setting up your hardware. For example, the Device Builder can tell you which pins are
available on each board so you don’t need to go on a treasure hunt for datasheets of each development to find out for
yourself. Combined with inline help and guidance right inside the workspace, you no longer need twenty different browser
tabs open just to debug a stray wire.&lt;/p&gt;
&lt;p&gt;What’s more, you don’t have to wait for one device to finish installing before moving to the next. The builder
introduces background multitasking, letting you queue compilation, installation, or clean-up tasks across multiple
hardware nodes without freezing up your browser tab.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-this-means-for-advanced-users&quot;&gt;What this means for advanced users&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Don’t let this beginner-friendly focus fool you: this workspace is a massive productivity upgrade for advanced users
too. By replacing manual datasheet cross-referencing with an integrated pin list, you lose the mental fatigue of
tracking complex wiring layouts.&lt;/p&gt;
&lt;p&gt;Combined with the background multitasking, you can now manage, compile, and push updates to an entire fleet of hardware
nodes back-to-back, transforming what used to be a tedious afternoon of sequential flashing into a fast, parallel
workflow.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;under-the-hood-faster-leaner-and-more-capable&quot;&gt;Under the hood: Faster, leaner, and more capable&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;While the new visual interface changes how you interact with ESPHome, we’ve also overhauled how it runs on your
devices. By optimizing data flows so they respond faster, you have plenty of room for growth as you add more features.
Key highlights from this release include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reclaimed memory:&lt;/strong&gt; If you build a battery-powered sensor that turns off its WiFi to save energy, the system now
“reclaims” that dormant network memory. This frees up crucial space on the chip, helping to keep your device running
smoothly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smoother screens and sound:&lt;/strong&gt; Fans of custom touchscreens or media players will find that layout validation is now
up to 4.5 times faster, and audio flows through a direct pipeline to cut sound stuttering and voice lag.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Next-gen hardware support:&lt;/strong&gt; We’ve baked native support for popular hardware right into the core. This includes
everything from high-fidelity audio chips and industrial pressure sensors to next-gen mmWave micro-radars that can
pinpoint the positioning of multiple people in a room at once.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🛠️ Looking for the full changelog? This is just a high-level look at the biggest upgrades. If you want to dive into the
complete, line-by-line list of every single bug fix, supported chip version, and technical milestone in this release,
&lt;a href=&quot;https://esphome.io/blog/2026/06/17/esphome-2026-6/#esphome-device-builder-replaces-the-legacy-dashboard&quot;&gt;check out the full 2026.6.0 release notes&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;three-things-to-try-this-weekend&quot;&gt;Three things to try this weekend&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With the new tools live, now’s a great time to clear your desk, grab a microcontroller, and dive in! Here’s some
inspiration for your next project:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Match your hardware:&lt;/strong&gt; Start a project quickly and easily by picking your board from our new Board Catalog. From
there you can load the correct settings automatically and get building straightaway. We’ve even integrated
community-submitted hardware configurations directly from &lt;a href=&quot;https://devices.esphome.io&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;devices.esphome.io&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browse the components:&lt;/strong&gt; Once your board is set, take a tour of the Component Catalog to discover what else is
possible. This massive list of supported sensors, lights, and switches shows how easy it is to drop them into your
project without typing a single line of code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get ready for the Starter Kit:&lt;/strong&gt; If you don’t have any components yet and don’t know where to begin, help is
coming! Stay tuned to our ESPHome social channels and &lt;a href=&quot;https://esphome.io/&quot;&gt;our website&lt;/a&gt;: the official ESPHome Starter
Kit, made by Apollo Automation, will be shipping soon… and we have more updates on the way!&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;quick-note-for-returning-users&quot;&gt;Quick note for returning users&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Are you an advanced user updating an existing fleet of smart devices? While this blog highlights our new
beginner-friendly features, this release does include a few syntax modernizations for legacy configurations. Be sure to
check out the &lt;a href=&quot;https://esphome.io/blog/2026/06/17/esphome-2026-6/#upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/a&gt; over on our official
technical release notes before deploying your updates.&lt;/p&gt;</content:encoded><category>Announcements</category></item><item><title>ESPHome 2026.6.0: Meet the new Device Builder</title><link>https://esphome.io/blog/2026/06/17/esphome-2026-6/</link><guid isPermaLink="true">https://esphome.io/blog/2026/06/17/esphome-2026-6/</guid><description>ESPHome 2026.6.0 retires the legacy dashboard for ESPHome Device Builder 1.0.0, raises ESP8266 WiFi security to WPA2, and modernizes the audio stack.</description><pubDate>Wed, 17 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/motion/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/imu.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Motion ​(​IMU)​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/motion/bmi270/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/imu.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;BMI2​7​0​&lt;/div&gt;&lt;div&gt;Accelerometer ​&amp;#x26;​ ​Gyroscope&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/motion/lsm6ds/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/imu.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LSM6​DS&lt;/div&gt;&lt;div&gt;Accelerometer ​&amp;#x26;​ ​Gyroscope&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/speaker/router/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/speaker.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Router ​Speaker&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/audio_dac/pcm5122/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/pcm5122.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;PCM5​1​2​2​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/xdb401/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/xdb401.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;XDB4​0​1​&lt;/div&gt;&lt;div&gt;Pressure&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.6.0 retires the legacy in-tree dashboard, replacing it with the new &lt;strong&gt;ESPHome Device Builder&lt;/strong&gt;,
which reached 1.0.0 this release. The release also raises the default WiFi
security mode on ESP8266 to WPA2 and finally makes WiFi and ethernet &lt;code dir=&quot;auto&quot;&gt;enable_on_boot: false&lt;/code&gt; 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. A wide audio-stack modernization brings zero-copy ring buffers, any-bit-depth mixing, and a new
&lt;code dir=&quot;auto&quot;&gt;router&lt;/code&gt; speaker, while a multi-PR effort prepares the codebase for ESP-IDF 6 and native RISC-V clang-tidy. It
also adds a new &lt;code dir=&quot;auto&quot;&gt;motion&lt;/code&gt; IMU framework with BMI270 and LSM6DS drivers, two USB-serial drivers, a PCM5122 audio
DAC, YAML frontmatter, and a top-level &lt;code dir=&quot;auto&quot;&gt;build_flags&lt;/code&gt; option that finally works on native IDF.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;

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


&lt;div&gt;&lt;h2 id=&quot;esphome-device-builder-replaces-the-legacy-dashboard&quot;&gt;ESPHome Device Builder Replaces the Legacy Dashboard&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;strong&gt;ESPHome Device Builder&lt;/strong&gt;, shipped as an opt-in public beta in 2026.5.0, reached
&lt;a href=&quot;https://github.com/esphome/device-builder/releases/tag/1.0.0&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;1.0.0&lt;/a&gt; this release and replaces the legacy
in-tree dashboard, which is being retired. The Device Builder lives in two repos,
&lt;a href=&quot;https://github.com/esphome/device-builder&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;device-builder&lt;/a&gt; (Python backend) and
&lt;a href=&quot;https://github.com/esphome/device-builder-frontend&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;device-builder-frontend&lt;/a&gt; (web UI), and as of 2026.6.0 it
is the dashboard bundled by default in the official Home Assistant ESPHome add-on.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://esphome.io/images/device-builder-dashboard.png&quot; alt=&quot;The ESPHome Device Builder device list&quot;&gt;&lt;/p&gt;
&lt;p&gt;What it brings over the legacy dashboard:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Visual component and automation builder&lt;/strong&gt; alongside a CodeMirror YAML editor, with a left-sidebar device
navigator. The legacy dashboard was a plain text editor over a &lt;code dir=&quot;auto&quot;&gt;.yaml&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component catalog with dependency resolution&lt;/strong&gt; and a &lt;strong&gt;per-board pin info viewer&lt;/strong&gt; that maps GPIO
capabilities and shows which component is using each pin.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firmware job queue&lt;/strong&gt; with progress, history, and cancel for compile / install / clean, replacing the
legacy one-operation-at-a-time model.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote builder:&lt;/strong&gt; one Device Builder instance can offload OTA builds to another over a peer-paired link
(mDNS discovery, out-of-band fingerprint confirmation, identity rotation, per-peer auto-route).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Labels&lt;/strong&gt;, &lt;strong&gt;areas&lt;/strong&gt;, an editable &lt;strong&gt;friendly name&lt;/strong&gt;, &lt;strong&gt;device cloning&lt;/strong&gt;, and &lt;strong&gt;multi-select bulk actions&lt;/strong&gt;
(update, delete, archive, and label across an arbitrary set of devices).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Out-of-sync detection:&lt;/strong&gt; an encryption-state mismatch badge on every device, plus version and config-hash
in-sync diagnostics in the device drawer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;YAML diff view&lt;/strong&gt;, &lt;strong&gt;cross-config YAML search&lt;/strong&gt; with surrounding context, and a &lt;strong&gt;command palette&lt;/strong&gt;
(⌘K / Ctrl-K).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Card and table views&lt;/strong&gt; with configurable columns and faceted filters (platform / status / area / labels).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real settings UI&lt;/strong&gt; with light / dark / system theme and localization underway across multiple languages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;First-run WiFi onboarding&lt;/strong&gt; and an expanded install-method dialog: Web Serial flashing, server-side USB
(relabeled for the Home Assistant host when running as the add-on), &lt;code dir=&quot;auto&quot;&gt;web.esphome.io&lt;/code&gt; download, and manual
&lt;code dir=&quot;auto&quot;&gt;.bin&lt;/code&gt; download.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The 2026.5.0 &lt;strong&gt;Use new Device Builder Preview&lt;/strong&gt; opt-in toggle is gone; the Device Builder is simply the
dashboard now.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp8266-default-wifi-security-raised-to-wpa2&quot;&gt;ESP8266 Default WiFi Security Raised to WPA2&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESP8266 now defaults to &lt;code dir=&quot;auto&quot;&gt;min_auth_mode: WPA2&lt;/code&gt;, matching the ESP32 default that has shipped for years. ESPHome
has been printing a deprecation warning on every ESP8266 config without an explicit &lt;code dir=&quot;auto&quot;&gt;min_auth_mode&lt;/code&gt; 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 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16682&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16682&lt;/a&gt; by
&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Configurations connecting to modern WPA2/WPA3 access points need no change. Devices on legacy WPA-only (TKIP)
routers must pin the old behavior explicitly:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;wifi&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;min_auth_mode&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;WPA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;wifi-and-ethernet-now-truly-free-their-memory-when-disabled-at-boot&quot;&gt;WiFi and Ethernet Now Truly Free Their Memory When Disabled at Boot&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;enable_on_boot: false&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;wifi:&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ethernet:&lt;/code&gt; previously skipped only the &lt;code dir=&quot;auto&quot;&gt;start()&lt;/code&gt; call, leaving the entire
driver resident in DMA-capable internal SRAM. Two PRs by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reclaimed memory on ESP32:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WiFi&lt;/strong&gt;: roughly &lt;strong&gt;15–30 KB&lt;/strong&gt; of DMA-capable internal SRAM freed when &lt;code dir=&quot;auto&quot;&gt;enable_on_boot: false&lt;/code&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16606&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16606&lt;/a&gt;). Field-tested on ESP32-S3 with W5500 SPI ethernet
&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;: roughly &lt;strong&gt;3–8 KB&lt;/strong&gt; freed when &lt;code dir=&quot;auto&quot;&gt;enable_on_boot: false&lt;/code&gt;, matching parity with the WiFi lifecycle
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16607&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16607&lt;/a&gt;). Brings &lt;code dir=&quot;auto&quot;&gt;ethernet.enable&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;ethernet.disable&lt;/code&gt;
actions and &lt;code dir=&quot;auto&quot;&gt;ethernet.connected&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;ethernet.enabled&lt;/code&gt; conditions, mirroring the WiFi automation surface.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;The W5500 SPI driver also got a CPU win in &lt;a href=&quot;https://github.com/esphome/esphome/pull/16596&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16596&lt;/a&gt; by
&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;: 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.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;lvgl-configuration-validation-up-to-4-5-faster&quot;&gt;LVGL Configuration Validation Up to 4.5× Faster&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new device builder UI revalidates configurations on every save, which made &lt;code dir=&quot;auto&quot;&gt;esphome config&lt;/code&gt; latency a
direct UX cost. LVGL configs were the worst offender. A five-PR series by
&lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; attacks the hot path in LVGL schema construction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memoize and lazily build &lt;code dir=&quot;auto&quot;&gt;container_schema&lt;/code&gt;&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16567&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16567&lt;/a&gt;) -
repeated validation median dropped from 210 ms to 17 ms on a representative LVGL config.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build widget update action schemas lazily&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16569&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16569&lt;/a&gt;) -
saves roughly 200 ms at lvgl import time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Merge dict-extend chains&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16614&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16614&lt;/a&gt;) - &lt;strong&gt;2.81× speed-up&lt;/strong&gt;
on &lt;code dir=&quot;auto&quot;&gt;read_config&lt;/code&gt; (0.246 s → 0.087 s on the &lt;code dir=&quot;auto&quot;&gt;lvtest&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;host.yaml&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memoize &lt;code dir=&quot;auto&quot;&gt;obj_schema&lt;/code&gt; by widget type&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16615&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16615&lt;/a&gt;) - &lt;strong&gt;2.14×
speed-up&lt;/strong&gt; stacked on top.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build &lt;code dir=&quot;auto&quot;&gt;automation_schema&lt;/code&gt; event validators lazily&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16633&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16633&lt;/a&gt;)
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;4.5× reduction&lt;/strong&gt; in per-call cost (281 ms → 63 ms across 29 widget types in a microbench).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The user-visible effect: every save in the device builder is noticeably snappier, especially on configurations
with large LVGL screens.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;audio-stack-modernization&quot;&gt;Audio Stack Modernization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; led a wide-ranging audio rework this cycle, replacing the
allocate-and-copy &lt;code dir=&quot;auto&quot;&gt;AudioSourceTransferBuffer&lt;/code&gt; pattern with a zero-copy &lt;code dir=&quot;auto&quot;&gt;RingBufferAudioSource&lt;/code&gt; across the
critical audio paths.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zero-copy ring-buffer rollout&lt;/strong&gt; eliminates one allocation and one extra copy per chunk of audio processing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;resampler&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16560&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16560&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;AudioDecoder&lt;/code&gt; for the speaker media player (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16564&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16564&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;micro_wake_word&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16595&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16595&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;voice_assistant&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16597&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16597&lt;/a&gt;) - also drops two 1024-byte send
buffers in favor of reading directly from the ring buffer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Mixer supports any bit depth&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16524&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16524&lt;/a&gt;). 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 &lt;code dir=&quot;auto&quot;&gt;esp-audio-libs&lt;/code&gt; 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resampler bit-depth pass-through&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16892&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16892&lt;/a&gt;). 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New &lt;code dir=&quot;auto&quot;&gt;router&lt;/code&gt; speaker component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16592&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16592&lt;/a&gt;) for switching
between output speakers at runtime via the &lt;code dir=&quot;auto&quot;&gt;router.speaker.switch_output&lt;/code&gt; action. A typical use case is
switching between SPDIF and analog I2S outputs live from a &lt;code dir=&quot;auto&quot;&gt;select&lt;/code&gt; entity, with audio staying in sync after
the switch. See &lt;a href=&quot;https://esphome.io/components/speaker/router/&quot;&gt;router&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;micro_wake_word&lt;/code&gt; task stack can live in PSRAM&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16632&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16632&lt;/a&gt;),
saving roughly &lt;strong&gt;3 KB of internal SRAM&lt;/strong&gt; on the ESP32-S3 with no measurable performance impact. Set
&lt;code dir=&quot;auto&quot;&gt;task_stack_in_psram: true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PSRAM task-stack handling consolidated&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16628&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16628&lt;/a&gt;) so
&lt;code dir=&quot;auto&quot;&gt;audio_file&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;audio_http&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;mixer&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;resampler&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sendspin&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;speaker.media_player&lt;/code&gt; all share the same
validation pattern, with a bug fix for &lt;code dir=&quot;auto&quot;&gt;task_stack_in_psram: false&lt;/code&gt; on the speaker media player.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp-idf-6-and-native-risc-v-clang-tidy&quot;&gt;ESP-IDF 6 and Native RISC-V clang-tidy&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A multi-PR effort by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; makes static analysis substantially better
at catching real-firmware bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;script/clang-tidy&lt;/code&gt; now supports RISC-V targets natively&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16809&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16809&lt;/a&gt;)
&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native ESP-IDF clang-tidy is now the comprehensive pass&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16823&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16823&lt;/a&gt;).
The arduino toolchain has a blind spot where its headers pull &lt;code dir=&quot;auto&quot;&gt;std::&lt;/code&gt; float math overloads into the global
namespace, hiding &lt;code dir=&quot;auto&quot;&gt;performance-type-promotion-in-math-fn&lt;/code&gt; findings. The IDF toolchain catches them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Float-to-double promotion fixed across the codebase&lt;/strong&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16812&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16812&lt;/a&gt;) - &lt;code dir=&quot;auto&quot;&gt;display&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;daikin_arc&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;nau7802&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sgp4x&lt;/code&gt;,
&lt;code dir=&quot;auto&quot;&gt;thermopro_ble&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;tuya&lt;/code&gt; all switched from C &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;math.h&gt;&lt;/code&gt; to the float-typed &lt;code dir=&quot;auto&quot;&gt;std::&lt;/code&gt; overloads, keeping math
in float on 32-bit MCUs instead of needlessly promoting to double.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;clang-tidy passes on ESP-IDF 6&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16850&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16850&lt;/a&gt;) - 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.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;arduino-esp32&lt;/code&gt; stub for managed IDF components&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16695&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16695&lt;/a&gt;)
&lt;ul&gt;
&lt;li&gt;on PlatformIO, components like FastLED that declare &lt;code dir=&quot;auto&quot;&gt;REQUIRES arduino-esp32&lt;/code&gt; now resolve to a stub that
re-exports the framework via CMake &lt;code dir=&quot;auto&quot;&gt;INTERFACE&lt;/code&gt;, instead of the IDF Component Manager trying to download a
duplicate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;100% patch coverage gating&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16827&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16827&lt;/a&gt; by
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;) - new PRs must cover every changed line. The project-level
coverage stays informational so contributors are not penalized for pre-existing untested code.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-components-and-hardware-support&quot;&gt;New Components and Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; landed a coordinated IMU stack: a generic &lt;a href=&quot;https://esphome.io/components/motion/&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;motion&lt;/code&gt;&lt;/a&gt;
hub component that provides acceleration, angular rate, and derived pitch/roll values, plus actions for
automatic pitch/roll calibration (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16226&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16226&lt;/a&gt;). Two concrete
drivers ride on top:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bosch BMI270&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16202&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16202&lt;/a&gt;) - used in M5Stack Tab5 and
Espressif’s EchoEar&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;STMicro LSM6DS3TR-C&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16232&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16232&lt;/a&gt;) - used in the Seeed
ReTerminal D1001&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New sensors and DACs:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PCM5122 audio DAC&lt;/strong&gt; by &lt;a href=&quot;https://github.com/remcom&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@remcom&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/15709&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15709&lt;/a&gt;) - 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.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;XDB401 pressure sensor&lt;/strong&gt; by &lt;a href=&quot;https://github.com/RT530&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@RT530&lt;/a&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/15108&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15108&lt;/a&gt;) - I2C pressure and temperature from the XIDIBEI
XDB401.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;USB-serial drivers&lt;/strong&gt; by &lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FTDI FT23XX family&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14587&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14587&lt;/a&gt;) - 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.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prolific PL2303 family&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16885&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16885&lt;/a&gt;) - covers the legacy
PL2303H/HX through the modern G-series; baud rate encoding selected per chip type.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New display:&lt;/strong&gt; WAVESHARE-ESP32-S3-TOUCH-AMOLED-2.16 added to the &lt;code dir=&quot;auto&quot;&gt;mipi_spi&lt;/code&gt; driver
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16887&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16887&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;dlms-smart-meter-component-overhaul&quot;&gt;DLMS Smart Meter Component Overhaul&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Tomer27cz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Tomer27cz&lt;/a&gt; refactored the &lt;code dir=&quot;auto&quot;&gt;dlms_meter&lt;/code&gt; component to use the external
&lt;a href=&quot;https://github.com/esphome-libs/dlms_parser&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;dlms_parser&lt;/code&gt;&lt;/a&gt; library
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/15458&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15458&lt;/a&gt;), substantially broadening smart-meter support:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic OBIS code schema&lt;/strong&gt; - define custom sensors, text sensors, or binary sensors by their OBIS code
(e.g. &lt;code dir=&quot;auto&quot;&gt;&quot;1-0:99.99.9&quot;&lt;/code&gt;) instead of being limited to the hardcoded property list.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Binary sensor support&lt;/strong&gt; is new.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decryption key now optional&lt;/strong&gt; - meters that broadcast plaintext are supported directly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible UART baud rate&lt;/strong&gt; - the 2400-baud requirement is gone; configure the UART to whatever your meter
speaks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New configuration variables&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;auth_key&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;custom_patterns&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;skip_crc&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;receive_timeout&lt;/code&gt; for
meters with non-standard behavior.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The legacy schema continues to work and the &lt;code dir=&quot;auto&quot;&gt;provider&lt;/code&gt; key is now ignored with a deprecation warning, slated
for removal in 2026.11.0. Existing configurations should still validate without change.&lt;/p&gt;
&lt;p&gt;The companion &lt;a href=&quot;https://esphome.io/components/sensor/dsmr/&quot;&gt;DSMR&lt;/a&gt; component also got a fix and feature pass
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16561&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16561&lt;/a&gt; by &lt;a href=&quot;https://github.com/PolarGoose&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@PolarGoose&lt;/a&gt;),
including support for EON Hungary meters, custom auth keys, and automatic hex-string detection in equipment
ID fields. Note that &lt;code dir=&quot;auto&quot;&gt;electricity_switch_position&lt;/code&gt; moved from &lt;code dir=&quot;auto&quot;&gt;sensor&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;text_sensor&lt;/code&gt;, which may need a YAML
update.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;networking-zephyr-and-platform-plumbing&quot;&gt;Networking, Zephyr, and Platform Plumbing&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Zephyr IPv6 networking on nRF52&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16336&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16336&lt;/a&gt; by
&lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt;) is the first step toward OpenThread support on the nRF52840 via
Zephyr. Adds a Zephyr-specific &lt;code dir=&quot;auto&quot;&gt;IPAddress&lt;/code&gt; class backed by &lt;code dir=&quot;auto&quot;&gt;struct in6_addr&lt;/code&gt;, networking Kconfig, and three
new nRF52 network test fixtures. IPv6 defaults to enabled on nRF52.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RP2350 / RP2040 variant config&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16602&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16602&lt;/a&gt; by
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;) brings the ESP32-style &lt;code dir=&quot;auto&quot;&gt;variant&lt;/code&gt; option to the &lt;code dir=&quot;auto&quot;&gt;rp2040&lt;/code&gt;
platform block, so the same platform can target the RP2040 or RP2350 and emits matching
&lt;code dir=&quot;auto&quot;&gt;USE_RP2040_VARIANT_&amp;#x3C;VARIANT&gt;&lt;/code&gt; build flags. The variant is auto-derived from the board’s MCU; specifying both
must match.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;esp32_hosted&lt;/code&gt; PSRAM transport buffers&lt;/strong&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16627&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16627&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;) -
new &lt;code dir=&quot;auto&quot;&gt;use_psram: true&lt;/code&gt; option moves the esp_hosted transport mempool out of DMA-capable internal RAM and into
PSRAM, fixing boot-time &lt;code dir=&quot;auto&quot;&gt;sdio_mempool_create&lt;/code&gt; asserts on memory-tight ESP32-P4 + LVGL UI configurations.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;configuration-and-tooling-improvements&quot;&gt;Configuration and Tooling Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;YAML frontmatter&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16552&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16552&lt;/a&gt; by
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;) - a leading &lt;code dir=&quot;auto&quot;&gt;---&lt;/code&gt;-separated YAML document is now treated as
opaque metadata, stripped before validation, and captured per-file on &lt;code dir=&quot;auto&quot;&gt;CORE.frontmatter&lt;/code&gt;. Future tooling
(including the device builder) can consume arbitrary user metadata like author, version, labels:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Jesse Hills&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1.0.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;labels&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;office&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;climate&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;my-node&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;esphome.build_flags&lt;/code&gt; for IDF + PlatformIO&lt;/strong&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16629&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16629&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;) -
a top-level &lt;code dir=&quot;auto&quot;&gt;esphome.build_flags&lt;/code&gt; list now applies compiler flags on both backends. The existing
&lt;code dir=&quot;auto&quot;&gt;platformio_options.build_flags&lt;/code&gt; was PlatformIO-only; users on native IDF (ESP32-P4, ESP32-H2) needed this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;esphome config --no-defaults&lt;/code&gt;&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16718&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16718&lt;/a&gt; by
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;) 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Codeberg short-form Git URLs&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16501&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16501&lt;/a&gt; by
&lt;a href=&quot;https://github.com/Eelviny&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Eelviny&lt;/a&gt;) - &lt;code dir=&quot;auto&quot;&gt;codeberg://owner/repo/path/file.yaml&lt;/code&gt; is now a supported source
for &lt;code dir=&quot;auto&quot;&gt;dashboard_import&lt;/code&gt; and short-form &lt;code dir=&quot;auto&quot;&gt;packages&lt;/code&gt;, alongside &lt;code dir=&quot;auto&quot;&gt;github://&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;gitlab://&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;github://&lt;/code&gt; framework source&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16639&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16639&lt;/a&gt; by
&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;) - &lt;code dir=&quot;auto&quot;&gt;esp32.framework.source&lt;/code&gt; now accepts
&lt;code dir=&quot;auto&quot;&gt;github://owner/repo@ref&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;https://github.com/owner/repo.git@ref&lt;/code&gt;, doing a &lt;code dir=&quot;auto&quot;&gt;git clone --depth=1 --recurse-submodules&lt;/code&gt; 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sensitive value redaction&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16690&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16690&lt;/a&gt; by
&lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;) is now driven by &lt;code dir=&quot;auto&quot;&gt;cv.sensitive()&lt;/code&gt; 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.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;State reporting CLI control&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16746&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16746&lt;/a&gt; by
&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;) - the &lt;code dir=&quot;auto&quot;&gt;logs&lt;/code&gt; command gained a &lt;code dir=&quot;auto&quot;&gt;--states / --no-states&lt;/code&gt; flag
and an environment variable for the default, restoring control over whether state changes appear in the log
stream.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;light-component-enhancements&quot;&gt;Light Component Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; added two light improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;light.effect.next&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;light.effect.previous&lt;/code&gt; actions&lt;/strong&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16491&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16491&lt;/a&gt;) cycle through a light’s configured effects without
having to hardcode effect names. An &lt;code dir=&quot;auto&quot;&gt;include_none: true&lt;/code&gt; option lets the cycle pass through the un-effected
state. The target light must have at least one effect, checked at config validation time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lambda light effects receive the light as &lt;code dir=&quot;auto&quot;&gt;it&lt;/code&gt;&lt;/strong&gt;
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16815&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16815&lt;/a&gt;) - matches the existing behavior of addressable
lambda effects, so simple lambdas can reference the light directly without &lt;code dir=&quot;auto&quot;&gt;id(my_light)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; also added a &lt;code dir=&quot;auto&quot;&gt;rounded&lt;/code&gt; property to LVGL meter arcs
(&lt;a href=&quot;https://github.com/esphome/esphome/pull/16669&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16669&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;other-notable-features&quot;&gt;Other Notable Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Display metadata for LVGL validation&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16702&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16702&lt;/a&gt;) -
display drivers now register &lt;code dir=&quot;auto&quot;&gt;byte_order&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;rotation&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;draw_rounding&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;has_writer&lt;/code&gt;, and
&lt;code dir=&quot;auto&quot;&gt;has_hardware_rotation&lt;/code&gt; metadata, so LVGL can pick &lt;code dir=&quot;auto&quot;&gt;byte_order&lt;/code&gt; automatically, reject mixed byte orders,
and merge &lt;code dir=&quot;auto&quot;&gt;draw_rounding&lt;/code&gt; requirements from the attached display.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mitsubishi CN105 swing modes&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15653&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15653&lt;/a&gt; by
&lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt;) - vertical / horizontal / both swing for the Mitsubishi CN105 climate
component, with last non-swing vane positions tracked and restored when swing is disabled.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SDL display screen selection&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16363&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16363&lt;/a&gt; by
&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;) - the host-platform SDL display can now be centered on a
specific display when multiple are attached.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;homeassistant.time&lt;/code&gt; honors explicit timezones&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16583&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16583&lt;/a&gt;
by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;) - a &lt;code dir=&quot;auto&quot;&gt;timezone:&lt;/code&gt; configured locally is no longer silently
overridden by Home Assistant’s zone.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I2C host platform support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14489&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14489&lt;/a&gt; by
&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;) - basic I2C bus support when running ESPHome on a Linux host
platform, useful for testing and host-side integrations.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;notable-bug-fixes&quot;&gt;Notable Bug Fixes&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nextion device info storage rewrite&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16059&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16059&lt;/a&gt; by
&lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt;) - the &lt;code dir=&quot;auto&quot;&gt;connect_info&lt;/code&gt; parser was replaced with fixed-size field
extraction, eliminating all heap allocations from the &lt;code dir=&quot;auto&quot;&gt;comok&lt;/code&gt; response. Device info is now always logged in
&lt;code dir=&quot;auto&quot;&gt;dump_config()&lt;/code&gt;; the old &lt;code dir=&quot;auto&quot;&gt;dump_device_info&lt;/code&gt; YAML option is gone.&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;thank-you-contributors&quot;&gt;Thank You, Contributors&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;This release includes 178 pull requests from over 20 contributors. A huge thank you to everyone who made
2026.6.0 possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; - 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&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; - 19 PRs including the audio stack modernization
(&lt;code dir=&quot;auto&quot;&gt;RingBufferAudioSource&lt;/code&gt; rollout, any-bit-depth mixer, resampler pass-through, new &lt;code dir=&quot;auto&quot;&gt;router&lt;/code&gt; speaker)
and the W5500 ethernet SPI offload&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - 16 PRs including the new &lt;code dir=&quot;auto&quot;&gt;motion&lt;/code&gt; IMU hub with
BMI270 and LSM6DS drivers, LVGL display-metadata validation, and the Home Assistant timezone fix&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; - 9 PRs including YAML frontmatter support,
&lt;code dir=&quot;auto&quot;&gt;light.effect.next&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;light.effect.previous&lt;/code&gt; actions, the RP2040/RP2350 variant option,
&lt;code dir=&quot;auto&quot;&gt;esphome config --no-defaults&lt;/code&gt;, and 100% patch-coverage enforcement&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; - 4 PRs including the WiFi and ethernet lazy-init RAM
reclamation work&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt; - 2 PRs adding the FTDI FT23XX and Prolific PL2303
USB-serial drivers&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/PolarGoose&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@PolarGoose&lt;/a&gt; - 2 PRs on DSMR including EON Hungary meter support
and the &lt;code dir=&quot;auto&quot;&gt;dsmr_parser&lt;/code&gt; library update&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; - 2 PRs on the nRF52 native build and network
IPv6 enforcement&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rtyle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rtyle&lt;/a&gt; - 2 PRs fixing QMP6988 sensor I2C error handling&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Tomer27cz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Tomer27cz&lt;/a&gt; - the DLMS meter component overhaul using the external
&lt;code dir=&quot;auto&quot;&gt;dlms_parser&lt;/code&gt; library&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt; - Zephyr IPv6 networking support for nRF52&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/remcom&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@remcom&lt;/a&gt; - the new PCM5122 audio DAC component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/RT530&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@RT530&lt;/a&gt; - the new XDB401 pressure sensor component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt; - swing support for the Mitsubishi CN105 climate component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt; - the Nextion &lt;code dir=&quot;auto&quot;&gt;connect_info&lt;/code&gt; heap-allocation rewrite&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also thank you to &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, &lt;a href=&quot;https://github.com/Rapsssito&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Rapsssito&lt;/a&gt;,
&lt;a href=&quot;https://github.com/burundiocibu&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@burundiocibu&lt;/a&gt;, &lt;a href=&quot;https://github.com/leodrivera&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@leodrivera&lt;/a&gt;,
&lt;a href=&quot;https://github.com/SoCuul&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@SoCuul&lt;/a&gt;,
&lt;a href=&quot;https://github.com/david-collett&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@david-collett&lt;/a&gt;, &lt;a href=&quot;https://github.com/chemelli74&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@chemelli74&lt;/a&gt;,
&lt;a href=&quot;https://github.com/Eelviny&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Eelviny&lt;/a&gt;, &lt;a href=&quot;https://github.com/gnumpi&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@gnumpi&lt;/a&gt;,
&lt;a href=&quot;https://github.com/GuzTech&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@GuzTech&lt;/a&gt;, &lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt;,
&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt;, &lt;a href=&quot;https://github.com/i-am-no-magic&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@i-am-no-magic&lt;/a&gt;, and
&lt;a href=&quot;https://github.com/kpfleming&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kpfleming&lt;/a&gt; for their contributions, and to everyone who reported
issues, tested pre-releases, and helped in the community.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;platform-changes&quot;&gt;Platform Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WiFi (ESP8266)&lt;/strong&gt;: Default &lt;code dir=&quot;auto&quot;&gt;min_auth_mode&lt;/code&gt; flipped from &lt;code dir=&quot;auto&quot;&gt;WPA&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;WPA2&lt;/code&gt;, 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 &lt;code dir=&quot;auto&quot;&gt;min_auth_mode: WPA&lt;/code&gt; explicitly under &lt;code dir=&quot;auto&quot;&gt;wifi:&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16682&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16682&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DSMR&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;electricity_switch_position&lt;/code&gt; moved from &lt;code dir=&quot;auto&quot;&gt;sensor:&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;text_sensor:&lt;/code&gt; because Hungarian meters
emit it as a string (e.g. &lt;code dir=&quot;auto&quot;&gt;ON&lt;/code&gt;) rather than a number. Update existing configs to declare the entity
under &lt;code dir=&quot;auto&quot;&gt;text_sensor:&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16561&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16561&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DLMS Meter&lt;/strong&gt;: Refactored to use the external &lt;code dir=&quot;auto&quot;&gt;dlms_parser&lt;/code&gt; 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 &lt;code dir=&quot;auto&quot;&gt;provider:&lt;/code&gt; option is
now ignored with a deprecation warning and will be removed in 2026.11.0
&lt;a href=&quot;https://github.com/esphome/esphome/pull/15458&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15458&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nextion&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;dump_device_info&lt;/code&gt; YAML option has been removed. Device info is now always stored and
logged in &lt;code dir=&quot;auto&quot;&gt;dump_config()&lt;/code&gt;. Remove &lt;code dir=&quot;auto&quot;&gt;dump_device_info: true&lt;/code&gt; from any &lt;code dir=&quot;auto&quot;&gt;display:&lt;/code&gt; Nextion configs
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16059&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16059&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Home Assistant Time&lt;/strong&gt;: When a &lt;code dir=&quot;auto&quot;&gt;timezone:&lt;/code&gt; is explicitly configured on a &lt;code dir=&quot;auto&quot;&gt;time:&lt;/code&gt; component with
&lt;code dir=&quot;auto&quot;&gt;platform: homeassistant&lt;/code&gt;, 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 &lt;code dir=&quot;auto&quot;&gt;timezone:&lt;/code&gt; entry
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16583&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16583&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;core-changes&quot;&gt;Core Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;custom_components/&lt;/code&gt; folder removed&lt;/strong&gt;: The deprecated &lt;code dir=&quot;auto&quot;&gt;custom_components/&lt;/code&gt; directory auto-loader has
been removed. Use &lt;a href=&quot;https://esphome.io/components/external_components/&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;external_components&lt;/code&gt;&lt;/a&gt; instead. The deprecation
warning has been printing since 2025.6
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16679&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16679&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensitive value redaction&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;cv.sensitive()&lt;/code&gt; 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 &lt;code dir=&quot;auto&quot;&gt;esphome config&lt;/code&gt; output. No YAML change needed; pass &lt;code dir=&quot;auto&quot;&gt;--show-secrets&lt;/code&gt; to bypass
redaction as before
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16690&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16690&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;undocumented-api-changes&quot;&gt;Undocumented API Changes&lt;/h3&gt;&lt;/div&gt;

&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MIPI DSI display class renamed&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;mipi_dsi::MIPI_DSI&lt;/code&gt; is now &lt;code dir=&quot;auto&quot;&gt;mipi_dsi::MipiDsi&lt;/code&gt;. Any lambda or
external component that referenced the old type name must use the new spelling. No behavior change
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16837&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16837&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Before&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;mipi_dsi::MIPI_DSI &lt;/span&gt;&lt;span&gt;*&gt;&lt;/span&gt;&lt;span&gt;(...);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// After&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static_cast&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;mipi_dsi::MipiDsi &lt;/span&gt;&lt;span&gt;*&gt;&lt;/span&gt;&lt;span&gt;(...);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;Component::mark_failed&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;status_set_error&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt; overloads removed&lt;/strong&gt;: use the
&lt;code dir=&quot;auto&quot;&gt;const LogString *&lt;/code&gt; overloads via &lt;code dir=&quot;auto&quot;&gt;LOG_STR(&quot;...&quot;)&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16680&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16680&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;cv.only_with_esp_idf&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;CORE.using_esp_idf&lt;/code&gt; removed&lt;/strong&gt;: migrate to &lt;code dir=&quot;auto&quot;&gt;cv.only_on_esp32&lt;/code&gt; and
&lt;code dir=&quot;auto&quot;&gt;CORE.is_esp32&lt;/code&gt;; use &lt;code dir=&quot;auto&quot;&gt;CORE.using_toolchain_esp_idf&lt;/code&gt; for the rare actual toolchain check
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16681&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16681&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;text_sensor::TextSensor::raw_state&lt;/code&gt; public member removed&lt;/strong&gt;: use &lt;code dir=&quot;auto&quot;&gt;get_raw_state()&lt;/code&gt; instead
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16683&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16683&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;nfc::format_uid(span)&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;nfc::format_bytes(span)&lt;/code&gt; heap helpers removed&lt;/strong&gt;: switch to the stack-buffer
variants &lt;code dir=&quot;auto&quot;&gt;nfc::format_uid_to(buf, span)&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;nfc::format_bytes_to(buf, span)&lt;/code&gt; with
&lt;code dir=&quot;auto&quot;&gt;FORMAT_UID_BUFFER_SIZE&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;FORMAT_BYTES_BUFFER_SIZE&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16684&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16684&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;seq&amp;#x3C;&gt;&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;gens&amp;#x3C;&gt;&lt;/code&gt; tuple-unpack templates removed&lt;/strong&gt; from &lt;code dir=&quot;auto&quot;&gt;core/automation.h&lt;/code&gt;: use
&lt;code dir=&quot;auto&quot;&gt;std::index_sequence&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;std::index_sequence_for&lt;/code&gt;
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16685&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16685&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;audio::scale_audio_samples&lt;/code&gt; deprecated&lt;/strong&gt;: switch to &lt;code dir=&quot;auto&quot;&gt;esp_audio_libs::gain::apply&lt;/code&gt; from the bundled
&lt;code dir=&quot;auto&quot;&gt;esp-audio-libs&lt;/code&gt; (Q31 scale factor, byte buffers, explicit &lt;code dir=&quot;auto&quot;&gt;bytes_per_sample&lt;/code&gt;). Scheduled for removal
in 2026.12.0
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16831&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16831&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;cv.sensitive()&lt;/code&gt; schema marker&lt;/strong&gt;: external component schemas should now wrap sensitive fields with
&lt;code dir=&quot;auto&quot;&gt;cv.sensitive(...)&lt;/code&gt; for redaction in &lt;code dir=&quot;auto&quot;&gt;esphome config&lt;/code&gt; output. The old regex-based fallback stays as a
deprecation bridge through 2026.12.0
&lt;a href=&quot;https://github.com/esphome/esphome/pull/16690&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16690&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the
&lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-6-1---june-19&quot;&gt;Release 2026.6.1 - June 19&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[core] Honor transferred address cache in has_resolvable_address &lt;a href=&quot;https://github.com/esphome/esphome/pull/17025&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17025&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[build] Skip target-platform deps when populating host unit-test config &lt;a href=&quot;https://github.com/esphome/esphome/pull/17039&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17039&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uptime] Revert timestamp sensor device_class to timestamp &lt;a href=&quot;https://github.com/esphome/esphome/pull/17037&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17037&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Support &lt;code dir=&quot;auto&quot;&gt;esphome idedata&lt;/code&gt; with the native ESP-IDF toolchain &lt;a href=&quot;https://github.com/esphome/esphome/pull/17040&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17040&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Don’t overwrite PlatformIO’s factory.bin &lt;a href=&quot;https://github.com/esphome/esphome/pull/17042&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17042&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[logger] Hold recursion guard while draining the task log buffer &lt;a href=&quot;https://github.com/esphome/esphome/pull/17044&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17044&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.10 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17051&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17051&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-6-2---june-20&quot;&gt;Release 2026.6.2 - June 20&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[espidf] Resolve IDF tools path to avoid unnormalized path warning &lt;a href=&quot;https://github.com/esphome/esphome/pull/17055&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17055&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[fastled_base] Fix RMT5 intr_priority conflict &lt;a href=&quot;https://github.com/esphome/esphome/pull/17072&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17072&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[packet_transport] Mark encryption key as cv.sensitive &lt;a href=&quot;https://github.com/esphome/esphome/pull/17066&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17066&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.11 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17081&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17081&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ha-addon] Expose the device-builder public port only when port 6052 is mapped &lt;a href=&quot;https://github.com/esphome/esphome/pull/17076&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17076&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.12 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17091&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17091&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-6-3---june-26&quot;&gt;Release 2026.6.3 - June 26&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[core] Clarify resolve error when a device has no network log/OTA transport &lt;a href=&quot;https://github.com/esphome/esphome/pull/17107&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17107&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[audio] Fix mono channel MP3 playback &lt;a href=&quot;https://github.com/esphome/esphome/pull/17106&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17106&lt;/a&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_rgb] Fix offsets for Wave 5 1024x600 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17057&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17057&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[json] Bump ArduinoJson to 7.4.3 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17126&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17126&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.13 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17132&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump zeroconf from 0.149.16 to 0.150.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17137&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17137&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Don’t fail framework check on broken unrelated PATH tools &lt;a href=&quot;https://github.com/esphome/esphome/pull/17053&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17053&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.14 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17139&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17139&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_server] Fix set_value action with by-reference triggers &lt;a href=&quot;https://github.com/esphome/esphome/pull/17156&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17156&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Use POSIX path for secure-boot signing/verification keys Fixes #17164 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17166&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17166&lt;/a&gt; by &lt;a href=&quot;https://github.com/mnewton25&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mnewton25&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] Warn on MODE3 default for display without CS pin &lt;a href=&quot;https://github.com/esphome/esphome/pull/17153&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17153&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.15 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17170&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17170&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] Suppress sequence errors when page selection used &lt;a href=&quot;https://github.com/esphome/esphome/pull/17176&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17176&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[opentherm] Support power scaling disabled &lt;a href=&quot;https://github.com/esphome/esphome/pull/17183&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17183&lt;/a&gt; by &lt;a href=&quot;https://github.com/GeoffreyFrogeye&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@GeoffreyFrogeye&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.16 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17182&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17182&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.17 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17199&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17199&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Accept ’#’ as ESP-IDF source ref separator &lt;a href=&quot;https://github.com/esphome/esphome/pull/17193&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17193&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[network] Set IPv4 type tag on all lwIP platforms, not just esp32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17200&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17200&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Report STA IP, not SoftAP IP, in wifi_info on ESP8266 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17185&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17185&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi][mipi_spi] Swap native dimensions for swap_xy hardware transform &lt;a href=&quot;https://github.com/esphome/esphome/pull/17201&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17201&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[hbridge] Fix light stuck on one polarity &lt;a href=&quot;https://github.com/esphome/esphome/pull/17162&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17162&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.18 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17212&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17212&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.19 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17217&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17217&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-6-4---july-1&quot;&gt;Release 2026.6.4 - July 1&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[adc] Only call cyw43_thread_enter/exit for VSYS when WiFi is active on RP2040 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17203&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17203&lt;/a&gt; by &lt;a href=&quot;https://github.com/jlunz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jlunz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[config_validation] Fix multicast typo in error message &lt;a href=&quot;https://github.com/esphome/esphome/pull/17206&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17206&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[es8388] Fix DAC unable to unmute once muted &lt;a href=&quot;https://github.com/esphome/esphome/pull/17221&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17221&lt;/a&gt; by &lt;a href=&quot;https://github.com/frenck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@frenck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] Bug fixes &lt;a href=&quot;https://github.com/esphome/esphome/pull/17247&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17247&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bluetooth_proxy] Fix -Wtype-limits warning with active: false &lt;a href=&quot;https://github.com/esphome/esphome/pull/17273&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17273&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espnow] Drop oversized received frames to prevent buffer overflow &lt;a href=&quot;https://github.com/esphome/esphome/pull/17271&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17271&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.23 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17316&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17316&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-6-5---july-9&quot;&gt;Release 2026.6.5 - July 9&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.24 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17332&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17332&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.25 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17333&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17333&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.26 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17369&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17369&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.27 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17370&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17370&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.28 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17382&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17382&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.0.29 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17384&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17384&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump bundled esphome-device-builder to 1.1.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/17412&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#17412&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphome[bot]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.6.0/&quot;&gt;full 2026.6.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2026.5.0: Device Builder enters public beta</title><link>https://esphome.io/blog/2026/05/20/esphome-2026-5/</link><guid isPermaLink="true">https://esphome.io/blog/2026/05/20/esphome-2026-5/</guid><description>ESPHome 2026.5.0 launches the public beta of the new ESPHome Device Builder, reworks the main loop and watchdog, and modernizes the audio decoder pipeline.</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sendspin/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/music.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Sendspin&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/media_source/sendspin/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/music.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Sendspin ​Media ​Source&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/media_player/sendspin/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/music.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Sendspin ​Group&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/sendspin/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/music.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Sendspin ​Sensor&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/text_sensor/sendspin/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/music.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Sendspin ​Text ​Sensor&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/radio_frequency/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/remote.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Radio ​Frequency ​Core&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/media_source/audio_http/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/http.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Audio ​HTTP ​Media ​Source&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/modbus_server/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/modbus.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Modbus ​Server&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;The headline change in ESPHome 2026.5.0 is the public beta of the new &lt;strong&gt;ESPHome Device Builder&lt;/strong&gt;, a from-scratch web app that replaces the legacy in-tree dashboard with a real configuration editor, a firmware job queue, multi-select bulk actions, labels and areas, out-of-sync detection, cross-config search, distributed builds, and a proper settings UI. On the firmware side, a fundamental rework of the main loop, scheduler, and task watchdog recovers measurable CPU and power on every platform, alongside a broad set of measured optimizations across the API, audio, and helper hot paths. A native ESP-IDF toolchain ships next to PlatformIO with ESP-IDF v6.0.1 readiness work, and the audio decoder pipeline is modernized on top of the new microMP3 / microWAV / microFLAC streaming libraries. OTA gains its most expansive feature set in years with partition-table and bootloader updates, web-server OTA, and soft-brick recovery, while ESP32-based Zigbee, the new Sendspin multi-room audio component family, a fresh &lt;code dir=&quot;auto&quot;&gt;radio_frequency&lt;/code&gt; entity type, expanded nRF52 / Zephyr platform work, and a substantial codebase correctness sweep round out the release.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; in server mode, migrate to the new &lt;code dir=&quot;auto&quot;&gt;modbus_server&lt;/code&gt; component and rename &lt;code dir=&quot;auto&quot;&gt;server_registers&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;registers&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;server_courtesy_response&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;courtesy_response&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you rely on more than 5 concurrent API connections on &lt;code dir=&quot;auto&quot;&gt;esp32&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;bk72xx&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;rtl87xx&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;ln882x&lt;/code&gt;, set &lt;code dir=&quot;auto&quot;&gt;api.max_connections&lt;/code&gt; explicitly (the default dropped from 8 to 5)&lt;/li&gt;
&lt;li&gt;If you play WAV files only via YAML actions to arbitrary URLs (not embedded, not set as the preferred pipeline format), add &lt;code dir=&quot;auto&quot;&gt;audio: codecs: wav:&lt;/code&gt; so WAV decoding is still compiled in&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;codec_support_enabled&lt;/code&gt; on the speaker media player, drop it and use the pipeline &lt;code dir=&quot;auto&quot;&gt;format:&lt;/code&gt; setting instead (&lt;code dir=&quot;auto&quot;&gt;format: NONE&lt;/code&gt; includes all codecs, &lt;code dir=&quot;auto&quot;&gt;format: WAV&lt;/code&gt; matches the old &lt;code dir=&quot;auto&quot;&gt;none&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; mode)&lt;/li&gt;
&lt;li&gt;If you embed audio files larger than 5 MB into your speaker media player via the &lt;code dir=&quot;auto&quot;&gt;files:&lt;/code&gt; block, compress them or pick a more efficient codec before upgrading&lt;/li&gt;
&lt;li&gt;If you have multiple &lt;code dir=&quot;auto&quot;&gt;ota: - platform: esphome&lt;/code&gt; entries on different ports, consolidate to a single entry on one port&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;throttle_average&lt;/code&gt; filters with a &lt;code dir=&quot;auto&quot;&gt;time_period&lt;/code&gt; longer than 24 hours, lower it (the new schema cap is 24 h)&lt;/li&gt;
&lt;li&gt;If your lambdas call &lt;code dir=&quot;auto&quot;&gt;id(...).set_min_power(...)&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_max_power(...)&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;set_zero_means_zero(...)&lt;/code&gt; on a &lt;code dir=&quot;auto&quot;&gt;FloatOutput&lt;/code&gt;, add &lt;code dir=&quot;auto&quot;&gt;min_power: 0%&lt;/code&gt; (or any of the scaling keys) to one of your &lt;code dir=&quot;auto&quot;&gt;output:&lt;/code&gt; entries so the runtime setters stay compiled in&lt;/li&gt;
&lt;li&gt;If your external component implements &lt;code dir=&quot;auto&quot;&gt;ComponentIterator&lt;/code&gt; and doesn’t handle media players, add &lt;code dir=&quot;auto&quot;&gt;bool on_media_player(media_player::MediaPlayer *obj) override { return true; }&lt;/code&gt; guarded by &lt;code dir=&quot;auto&quot;&gt;#ifdef USE_MEDIA_PLAYER&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If your external component or lambda calls &lt;code dir=&quot;auto&quot;&gt;OneWireBus::skip()&lt;/code&gt;, handle the new &lt;code dir=&quot;auto&quot;&gt;bool&lt;/code&gt; return value (&lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; means the reset/presence pulse failed; bail out instead of writing to a dead bus)&lt;/li&gt;
&lt;li&gt;If your external component constructs &lt;code dir=&quot;auto&quot;&gt;PollingComponent()&lt;/code&gt; with no argument and never calls &lt;code dir=&quot;auto&quot;&gt;set_update_interval()&lt;/code&gt;, pass an interval explicitly; the default constructor no longer polls at all&lt;/li&gt;
&lt;li&gt;If your external component uses &lt;code dir=&quot;auto&quot;&gt;esphome::RingBuffer&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;esphome/core/ring_buffer.h&lt;/code&gt;, switch to &lt;code dir=&quot;auto&quot;&gt;esphome::ring_buffer::RingBuffer&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;esphome/components/ring_buffer/ring_buffer.h&lt;/code&gt; and add &lt;code dir=&quot;auto&quot;&gt;AUTO_LOAD = [&quot;ring_buffer&quot;]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If your external component uses heap-allocating helpers like &lt;code dir=&quot;auto&quot;&gt;str_lower_case&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;format_hex&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;format_mac_address_pretty&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;value_accuracy_to_string&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;base64_encode&lt;/code&gt;, include &lt;code dir=&quot;auto&quot;&gt;esphome/core/alloc_helpers.h&lt;/code&gt; directly (the &lt;code dir=&quot;auto&quot;&gt;helpers.h&lt;/code&gt; re-export is temporary)&lt;/li&gt;
&lt;li&gt;If you maintain an external &lt;code dir=&quot;auto&quot;&gt;climate&lt;/code&gt; platform, replace the deprecated &lt;code dir=&quot;auto&quot;&gt;set_supports_*&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;get_supports_*&lt;/code&gt; accessors with &lt;code dir=&quot;auto&quot;&gt;add_feature_flags()&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;has_feature_flags()&lt;/code&gt; (note &lt;code dir=&quot;auto&quot;&gt;two_point_target_temperature&lt;/code&gt; maps to &lt;code dir=&quot;auto&quot;&gt;CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;If you hold long-lived BLE connections via &lt;code dir=&quot;auto&quot;&gt;ble_client&lt;/code&gt; and notice WiFi throughput drops, this is the new &lt;code dir=&quot;auto&quot;&gt;esp32_ble_tracker&lt;/code&gt; coex behavior; open an issue with your config if it materially affects your workload&lt;/li&gt;
&lt;li&gt;If your &lt;code dir=&quot;auto&quot;&gt;ektf2232&lt;/code&gt; config still uses &lt;code dir=&quot;auto&quot;&gt;rts_pin&lt;/code&gt;, rename it to &lt;code dir=&quot;auto&quot;&gt;reset_pin&lt;/code&gt; (the friendly migration error has been removed)&lt;/li&gt;
&lt;/ul&gt;


&lt;div&gt;&lt;h2 id=&quot;introducing-the-new-esphome-device-builder-beta&quot;&gt;Introducing the New ESPHome Device Builder (Beta)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;strong&gt;ESPHome Device Builder&lt;/strong&gt;, &lt;a href=&quot;https://www.openhomefoundation.org/blog/building-whats-next-state-of-the-open-home-2026/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;announced at State of the Open Home 2026&lt;/a&gt; and now in public beta, is a from-scratch replacement for the legacy in-tree dashboard. It lives in two new repos, &lt;a href=&quot;https://github.com/esphome/device-builder&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;device-builder&lt;/a&gt; (Python backend) and &lt;a href=&quot;https://github.com/esphome/device-builder-frontend&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;device-builder-frontend&lt;/a&gt; (web UI), and consumes ESPHome through stable public interfaces instead of reaching into internal modules. The work is driven by the &lt;strong&gt;Open Home Foundation Ecosystems department&lt;/strong&gt;, which expanded significantly last year so OHF could deliver more to the community, working alongside the existing maintainer community. Most of the rewrite goes toward dashboard capabilities the existing user base has been blocked on for years (job queue, multi-select bulk actions, labels/areas, out-of-sync detection, cross-config search, distributed builds, real settings UI). Visual editing and pairing with hardware like the &lt;a href=&quot;https://apolloautomation.com/products/esk-1-esphome-starter-kit&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Apollo Automation ESPHome Starter Kit (ESK-1)&lt;/a&gt; make the same app a reasonable starting point for newcomers as well.&lt;/p&gt;
&lt;p&gt;Capabilities the legacy dashboard didn’t offer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Visual component and automation builder&lt;/strong&gt; alongside Monaco YAML, with a left-sidebar device navigator. Legacy was an Ace text editor over a &lt;code dir=&quot;auto&quot;&gt;.yaml&lt;/code&gt; file with no first-class component or automation objects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component catalog with dependency resolution&lt;/strong&gt; and a &lt;strong&gt;per-board pin info viewer&lt;/strong&gt; that maps GPIO capabilities and shows which component is using each pin.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firmware job queue&lt;/strong&gt; with progress, history, and cancel for compile / install / clean. Legacy ran one operation at a time with no concurrency or history.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote builder.&lt;/strong&gt; One Device Builder instance can offload compile/install jobs to another over a peer-paired link (mDNS discovery, SHA-256 fingerprint confirmation, identity rotation, per-peer auto-route).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Labels&lt;/strong&gt; (colored, searchable, filterable), &lt;strong&gt;areas&lt;/strong&gt; as a first-class field, &lt;strong&gt;friendly name&lt;/strong&gt; as a separate editable field, &lt;strong&gt;device cloning&lt;/strong&gt;, and &lt;strong&gt;multi-select bulk actions&lt;/strong&gt; (update / delete / archive on an arbitrary subset of devices). Legacy’s only bulk action was an all-or-nothing “update all”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Out-of-sync detection&lt;/strong&gt; with per-device badges for version, config-hash, and encryption-state mismatches. Legacy showed only “update available.”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;YAML diff view&lt;/strong&gt;, &lt;strong&gt;cross-config YAML search&lt;/strong&gt; with surrounding context, and a &lt;strong&gt;command palette&lt;/strong&gt; (⌘K / Ctrl-K).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Card and table views&lt;/strong&gt; with configurable columns and faceted filters (platform / status / area / labels). Legacy was cards only.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real settings UI&lt;/strong&gt; with light/dark/system theme, English / Français / Nederlands localization, editor layout, and remote-builder controls. Legacy exposed almost nothing in-UI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;First-run Wi-Fi onboarding&lt;/strong&gt; and &lt;strong&gt;USB-plug detection&lt;/strong&gt; with a “set this up” prompt when a board is connected.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing features like Web Serial flashing and Take Control / Adopt carry over and are surfaced more prominently in the new install-method dialog, which adds server-side USB, Home Assistant host USB auto-detection, and &lt;code dir=&quot;auto&quot;&gt;web.esphome.io&lt;/code&gt; download as transports.&lt;/p&gt;
&lt;p&gt;Supporting ESPHome-side plumbing landed in 2026.5.0: stable backend API surface (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16206&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16206&lt;/a&gt;) with documented helper contracts like &lt;code dir=&quot;auto&quot;&gt;write_file&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16290&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16290&lt;/a&gt;); stable WiFi capability helpers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16300&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16300&lt;/a&gt;) and the new &lt;code dir=&quot;auto&quot;&gt;esphome.upload_targets&lt;/code&gt; module (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16346&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16346&lt;/a&gt;); the &lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;config-hash&lt;/code&gt; CLI command&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15548&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15548&lt;/a&gt;) plus an &lt;strong&gt;mDNS &lt;code dir=&quot;auto&quot;&gt;config_hash&lt;/code&gt; TXT record&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16145&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16145&lt;/a&gt;) that let Device Builder skip re-flash when the running config matches; schema visibility hints for the visual editor (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16267&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16267&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16276&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16276&lt;/a&gt;); tightened &lt;code dir=&quot;auto&quot;&gt;esphome rename&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16296&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16296&lt;/a&gt;); restored &lt;code dir=&quot;auto&quot;&gt;ProgressBar&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;--dashboard&lt;/code&gt; mode (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16357&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16357&lt;/a&gt;); downstream CI against PR Python code (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16214&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16214&lt;/a&gt;); and legacy-dashboard guardrails on contributor PRs (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16378&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16378&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The legacy dashboard remains the default in 2026.5.0. Home Assistant users can try Device Builder today by installing the &lt;strong&gt;ESPHome (beta)&lt;/strong&gt; app (formerly add-on), where it is &lt;strong&gt;enabled by default&lt;/strong&gt;. The stable and beta apps run side by side, or stable-app users can opt in via the &lt;strong&gt;Use new Device Builder Preview&lt;/strong&gt; toggle in the add-on’s &lt;strong&gt;Configuration&lt;/strong&gt; tab:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://esphome.io/images/device-builder-settings.png&quot; alt=&quot;Toggle &amp;#x22;Use new Device Builder Preview&amp;#x22; under the ESPHome Device Builder Configuration tab in Home Assistant&quot;&gt;&lt;/p&gt;
&lt;p&gt;Feedback from beta testers shapes the next release, and we’re excited to already be seeing the first community pull requests landing on the &lt;a href=&quot;https://github.com/esphome/device-builder&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;device-builder&lt;/a&gt; and &lt;a href=&quot;https://github.com/esphome/device-builder-frontend&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;device-builder-frontend&lt;/a&gt; repos.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;main-loop-and-watchdog-architecture-overhaul&quot;&gt;Main Loop and Watchdog Architecture Overhaul&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release lands one of the most consequential changes to ESPHome’s runtime in years: a fundamental rework of how the main loop, scheduler, and task watchdog interact. Led by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, with &lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt; contributing the configurable ESP32 watchdog timeout (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15908&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15908&lt;/a&gt;) that the new auto-scaling feed interval keys off and the OpenThread proof-of-concept that produced the 2.0 mA → 1.1 mA power-savings measurement, these changes recover meaningful CPU on every supported platform and finally make &lt;code dir=&quot;auto&quot;&gt;App.set_loop_interval()&lt;/code&gt; work the way the documentation has always described.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Main-loop cadence decoupled from the scheduler&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15792&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15792&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every component’s &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; now actually runs at the configured &lt;code dir=&quot;auto&quot;&gt;loop_interval_&lt;/code&gt; cadence (default ~62 Hz) instead of being silently pulled forward to ~128 Hz by unrelated scheduler activity.&lt;/li&gt;
&lt;li&gt;Background-driven events (MQTT RX, USB RX, BLE, mWW, espnow, lwIP sockets, etc.) still wake their component within a single tick via &lt;code dir=&quot;auto&quot;&gt;wake_loop_threadsafe()&lt;/code&gt;, even with multi-second &lt;code dir=&quot;auto&quot;&gt;loop_interval_&lt;/code&gt; values for deep power-save configurations.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;App.set_loop_interval()&lt;/code&gt; now actually enables power savings. Independent testing on an OpenThread proof-of-concept measured average current drop from &lt;strong&gt;2.0 mA to 1.1 mA&lt;/strong&gt; on top of an earlier version of this work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Watchdog feed rate corrected after a 1000x cost regression&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15846&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15846&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15984&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15984&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The 3 ms feed throttle dated to ESPHome’s 2019 C++ port, when feeding the watchdog cost a hundred nanoseconds. The 2021 switch to ESP-IDF made each feed cost ~10-12 µs without the constant being revisited. The bug only surfaced under raised &lt;code dir=&quot;auto&quot;&gt;loop_interval_&lt;/code&gt;, where 26% of CPU was being burned inside &lt;code dir=&quot;auto&quot;&gt;arch_feed_wdt()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The idle-tick feed interval is now per-platform instead of a universal 3 ms: &lt;strong&gt;1000 ms by default on ESP32&lt;/strong&gt; (1/5 of the configured watchdog timeout, scaling automatically with the new &lt;code dir=&quot;auto&quot;&gt;esp32.watchdog_timeout&lt;/code&gt; knob from #15908), &lt;strong&gt;100 ms on ESP8266&lt;/strong&gt;, &lt;strong&gt;2000 ms on LibreTiny BK72xx&lt;/strong&gt;, and &lt;strong&gt;300 ms&lt;/strong&gt; on the remaining platforms. Real ESP32+BT proxy measurements show the &lt;code dir=&quot;auto&quot;&gt;wdt&lt;/code&gt; bucket dropping from &lt;strong&gt;46.5 ms to 21.6 ms per 60 s window&lt;/strong&gt; with no loss of safety margin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Loop-when-idle gated everywhere it makes sense&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15636&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15636&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15642&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15642&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15884&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15884&lt;/a&gt; and many more): the &lt;code dir=&quot;auto&quot;&gt;esphome&lt;/code&gt; OTA component, &lt;code dir=&quot;auto&quot;&gt;status_led&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;bl0906&lt;/code&gt;, and others now disable their own &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; when idle and rely on wake hooks (socket-event callbacks, ISR-safe wake flags, etc.) to come back to life only when there is real work to do. OTA in particular ran every tick forever just to check whether a client had connected; on Xtensa each idle tick pulled a &lt;code dir=&quot;auto&quot;&gt;memw&lt;/code&gt; plus a volatile load, paid for the entire lifetime of every ESPHome device that exists.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scheduler self-keyed timer API&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16127&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16127&lt;/a&gt;) lets small action and filter classes drop &lt;code dir=&quot;auto&quot;&gt;Component&lt;/code&gt; inheritance entirely. Follow-ups across &lt;a href=&quot;https://github.com/esphome/esphome/pull/16129&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16129&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16131&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16131&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16132&lt;/a&gt;, and &lt;a href=&quot;https://github.com/esphome/esphome/pull/16191&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16191&lt;/a&gt; migrate &lt;code dir=&quot;auto&quot;&gt;DelayAction&lt;/code&gt; and the &lt;code dir=&quot;auto&quot;&gt;binary_sensor&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;sensor&lt;/code&gt; filter family (&lt;code dir=&quot;auto&quot;&gt;DelayedOnFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;DelayedOffFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;DebounceFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;HeartbeatFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SettleFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;AutorepeatFilter&lt;/code&gt;, and others), saving ~8 bytes per instance baseline (and ~32 bytes more when &lt;code dir=&quot;auto&quot;&gt;runtime_stats:&lt;/code&gt; is enabled).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;performance-optimizations&quot;&gt;Performance Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Beyond the structural changes above, this release contains an unusual concentration of measured micro-optimizations across the codebase, particularly on the API and audio paths. Led by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; and &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;, with &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; contributing the &lt;code dir=&quot;auto&quot;&gt;CallbackManager&lt;/code&gt; copy reduction (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16093&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16093&lt;/a&gt;) and a sweep of &lt;code dir=&quot;auto&quot;&gt;performance-unnecessary-copy-initialization&lt;/code&gt; fixes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16101&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16101&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-platform &lt;code dir=&quot;auto&quot;&gt;millis()&lt;/code&gt; overhaul.&lt;/strong&gt; A coordinated rewrite hits every supported runtime. ESP8266 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15662&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15662&lt;/a&gt;) drops from 3348 ns/call to 1077 ns/call (&lt;strong&gt;2.7x&lt;/strong&gt;) by wrapping Arduino’s &lt;code dir=&quot;auto&quot;&gt;millis()&lt;/code&gt; at link time with a 32-bit accumulator, replacing four 64-bit multiplies routed through the LX106’s software &lt;code dir=&quot;auto&quot;&gt;__umulsidi3&lt;/code&gt; helper. ESP32 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15661&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15661&lt;/a&gt;) switches to &lt;code dir=&quot;auto&quot;&gt;xTaskGetTickCount()&lt;/code&gt; directly when the FreeRTOS tick rate is 1 kHz; LibreTiny (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15918&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15918&lt;/a&gt;) inlines the same &lt;code dir=&quot;auto&quot;&gt;xTaskGetTickCount()&lt;/code&gt; fast path; the host platform (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15994&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15994&lt;/a&gt;) replaces floating-point math with integer arithmetic; and &lt;code dir=&quot;auto&quot;&gt;Millis64Impl::compute()&lt;/code&gt; is force-inlined on single-threaded platforms (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15684&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15684&lt;/a&gt;). On a typical 10-component ESP8266 device, runtime stats showed &lt;code dir=&quot;auto&quot;&gt;main_loop active_total&lt;/code&gt; drop by &lt;strong&gt;41 ms per minute of CPU&lt;/strong&gt;, roughly 7% of the scheduler+overhead budget reclaimed for actual work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BLE advertisement encode is 20-33% faster&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15988&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15988&lt;/a&gt;). A new &lt;code dir=&quot;auto&quot;&gt;(mac_address)&lt;/code&gt; proto field option unrolls the varint encoder for 48-bit MAC addresses into a 7-byte fast path. CodSpeed measured the &lt;code dir=&quot;auto&quot;&gt;CalculateSize_BLERawAdvs12&lt;/code&gt; benchmark improving by &lt;strong&gt;33%&lt;/strong&gt; and the full &lt;code dir=&quot;auto&quot;&gt;CalcAndEncode_BLERawAdvs12&lt;/code&gt; benchmark by &lt;strong&gt;22.5%&lt;/strong&gt;. On real ESP32 hardware, encode dropped 27.6% (11647 ns/op to 8430 ns/op) on a 12-advertisement batch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API socket fast-path tightened&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15996&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15996&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15888&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15888&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15889&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15889&lt;/a&gt;). The Xtensa &lt;code dir=&quot;auto&quot;&gt;memw&lt;/code&gt; instruction in the per-socket ready check is now hoisted to once per main-loop iteration; &lt;code dir=&quot;auto&quot;&gt;api_is_connected()&lt;/code&gt; is inlined and reduced to a single byte load; the proxy message families (Z-Wave, IR/RF, serial) are now marked &lt;code dir=&quot;auto&quot;&gt;speed_optimized&lt;/code&gt; and have CodSpeed coverage (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16157&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16157&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16159&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16159&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scheduler fast paths force-inlined&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15683&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15683&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15685&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15685&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15686&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15686&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15947&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15947&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;cleanup_()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;process_to_add()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;process_defer_queue_()&lt;/code&gt; are inlined at the call site; the multi-threaded-no-atomics path now uses lock-free &lt;code dir=&quot;auto&quot;&gt;__atomic&lt;/code&gt; builtins.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Defer queue: don’t sleep while non-empty&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15968&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15968&lt;/a&gt;). The scheduler now skips its select/sleep when the defer queue still has items pending, eliminating a per-tick latency spike on action chains that defer between steps (&lt;code dir=&quot;auto&quot;&gt;script.execute&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;delay&lt;/code&gt;, etc.). Latency-sensitive automations no longer pay an extra select round-trip per deferred step.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HAL trivial dispatches inlined&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15977&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15977&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16111&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16111&lt;/a&gt;-&lt;a href=&quot;https://github.com/esphome/esphome/pull/16116&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16116&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16183&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16183&lt;/a&gt;). The HAL split moves bodies into per-platform &lt;code dir=&quot;auto&quot;&gt;hal.cpp&lt;/code&gt; files and inlines the trivial wrappers (&lt;code dir=&quot;auto&quot;&gt;millis()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;micros()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;feed_wdt()&lt;/code&gt;, etc.) at the call site, removing a per-call function-call overhead that compounded across every component’s main-loop work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;zwave_proxy&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;bluetooth_proxy&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; fast paths inlined.&lt;/strong&gt; On &lt;code dir=&quot;auto&quot;&gt;zwave_proxy&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15887&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15887&lt;/a&gt;) the &lt;code dir=&quot;auto&quot;&gt;response_handler_&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;process_uart_&lt;/code&gt; hot-path branches are now inlined at the &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; call site. On &lt;code dir=&quot;auto&quot;&gt;bluetooth_proxy&lt;/code&gt;, a partial revert of an earlier &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt;→&lt;code dir=&quot;auto&quot;&gt;set_interval&lt;/code&gt; migration (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15992&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15992&lt;/a&gt;) restores tighter scheduling for proxy traffic, and a redundant &lt;code dir=&quot;auto&quot;&gt;remote_bda_&lt;/code&gt; write in the connect handler (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16000&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16000&lt;/a&gt;) is gone. Bluetooth proxy is one of the most-deployed ESPHome configurations, so these compound across thousands of devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mDNS update polling event-driven on ESP8266 and RP2040&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15961&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15961&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;MDNS.update()&lt;/code&gt; is now driven by IP-state events on ESP8266 and RP2040 instead of being polled every main-loop tick. Idle devices stop touching the mDNS state machine entirely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;i2s_audio software volume control is 45% cheaper&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16278&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16278&lt;/a&gt;). The new Q31 scaling factor uses Xtensa’s &lt;code dir=&quot;auto&quot;&gt;mulsh&lt;/code&gt; instruction (30 bits of precision) and a precomputed scalar generated only when volume changes. Speaker-task CPU usage at 48 kHz stereo drops from &lt;strong&gt;7.8% to 4.3%&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;value_accuracy_to_buf&lt;/code&gt; got a non-&lt;code dir=&quot;auto&quot;&gt;snprintf&lt;/code&gt; fast path&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15596&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15596&lt;/a&gt;). Sensor value formatting now uses a direct integer-to-decimal conversion for the common case (accuracy 0-3 with finite, in-range values), with &lt;code dir=&quot;auto&quot;&gt;snprintf&lt;/code&gt; kept as the fallback for NaN, infinity, larger accuracies, and out-of-range values. This is a major win for &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt;, which formats every sensor state into JSON on each SSE push and on every REST request; high-update-rate dashboards and devices with many sensors see noticeably lower CPU per push, with the largest gains on ESP8266 where &lt;code dir=&quot;auto&quot;&gt;snprintf&lt;/code&gt; carries the most overhead.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Light, callback, and helper hot paths&lt;/strong&gt; all saw improvements: &lt;code dir=&quot;auto&quot;&gt;LightCall&lt;/code&gt; flag accessors are force-inlined (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15729&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15729&lt;/a&gt;), &lt;code dir=&quot;auto&quot;&gt;format_hex_internal&lt;/code&gt; was rewritten to avoid &lt;code dir=&quot;auto&quot;&gt;snprintf&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15594&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15594&lt;/a&gt;), and &lt;code dir=&quot;auto&quot;&gt;CallbackManager&lt;/code&gt; call paths reduce copies (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16093&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16093&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;memory-footprint-reductions&quot;&gt;Memory Footprint Reductions&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A parallel effort by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; and &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;, with &lt;a href=&quot;https://github.com/schdro&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@schdro&lt;/a&gt; contributing the static loop-task allocation, focused on shrinking the per-instance and static-RAM cost of common components.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;APIServer client list moved to a compile-time array&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15889&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15889&lt;/a&gt;) eliminates the persistent heap-held vector that grew via doubling reallocations. Measured &lt;strong&gt;-92 B flash on ESP32-S3, -152 B flash on ESP8266&lt;/strong&gt;, plus zero heap fragmentation. At one client connected (the typical Home Assistant deployment), net RAM is &lt;strong&gt;-4 B&lt;/strong&gt;. The new compile-time &lt;code dir=&quot;auto&quot;&gt;MAX_API_CONNECTIONS&lt;/code&gt; constant lets the array size and accept-time cap derive from one source.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FloatOutput power scaling gated&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15998&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15998&lt;/a&gt;) saves 12 bytes per output instance plus ~248 bytes flash, applied across every PWM channel, DAC channel, LEDC output, and dimmer-chip channel. On a 5-channel H801 RGBWW LED Controller this measured at &lt;strong&gt;-64 B static RAM and -248 B flash&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Per-instance action fields folded into stateless lambdas&lt;/strong&gt;: every YAML automation that calls a &lt;code dir=&quot;auto&quot;&gt;light.control&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;light.toggle&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;light.dim_relative&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16037&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16037&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16038&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16038&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16039&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16039&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16118&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16118&lt;/a&gt;), &lt;code dir=&quot;auto&quot;&gt;climate.control&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16044&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16044&lt;/a&gt;), &lt;code dir=&quot;auto&quot;&gt;cover.control&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;cover.template.publish&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16046&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16046&lt;/a&gt;), &lt;code dir=&quot;auto&quot;&gt;fan.turn_on&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16122&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16122&lt;/a&gt;), or &lt;code dir=&quot;auto&quot;&gt;valve.control&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16123&lt;/a&gt;) action previously stored every optional parameter (transition lengths, RGB/brightness targets, modes, position, direction, etc.) as fields on the &lt;code dir=&quot;auto&quot;&gt;Action&lt;/code&gt; instance, costing &lt;strong&gt;60-120 bytes of RAM per action instance&lt;/strong&gt; depending on the action type. These are now packed into a single stateless lambda captured at compile time, so unused parameters cost nothing per action instance and every action drops to &lt;strong&gt;20 bytes or less per instance&lt;/strong&gt;. A config with 20 &lt;code dir=&quot;auto&quot;&gt;light.*&lt;/code&gt; automations reclaims well over a kilobyte of RAM, and configurations with many such automations see the largest savings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;ThrottleAverageFilter&lt;/code&gt; packed&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16169&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16169&lt;/a&gt;) drops from 28 B to 24 B per instance by packing the &lt;code dir=&quot;auto&quot;&gt;have_nan_&lt;/code&gt; flag alongside the 31-bit &lt;code dir=&quot;auto&quot;&gt;n_&lt;/code&gt; field in a single 32-bit word.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LD24xx sensors and template restorers inlined&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15676&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15676&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15883&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15883&lt;/a&gt;) eliminate heap allocations for small fixed-purpose objects.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Loop task uses static allocation&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15659&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15659&lt;/a&gt;): ~152 bytes of heap metadata reclaimed by moving the ESP32 loop task TCB and stack into &lt;code dir=&quot;auto&quot;&gt;.bss&lt;/code&gt; instead of being allocated at boot from the heap.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ring buffer can target internal memory&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16187&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16187&lt;/a&gt;). A new memory-preference parameter on &lt;code dir=&quot;auto&quot;&gt;RingBuffer::create()&lt;/code&gt; allows audio paths to skip the slow ESP32 PSRAM cache when small buffers benefit from the faster internal SRAM.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scheduler pool replaced with intrusive freelist&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16172&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16172&lt;/a&gt;). The previous &lt;code dir=&quot;auto&quot;&gt;std::vector&lt;/code&gt;-backed &lt;code dir=&quot;auto&quot;&gt;SchedulerItem&lt;/code&gt; pool grew via doubling reallocations and hung on to its peak capacity for the lifetime of the device. The replacement is an &lt;strong&gt;unbounded intrusive freelist&lt;/strong&gt; that recycles freed items in O(1) without ever resizing or fragmenting an external container. Scheduler-heavy configurations stop carrying high-watermark vector capacity around as dead RAM.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;safe_mode&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;rtttl&lt;/code&gt; callback storage gated&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16002&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16002&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16003&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16003&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;on_safe_mode&lt;/code&gt; callbacks now use a &lt;code dir=&quot;auto&quot;&gt;StaticCallbackManager&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;rtttl&lt;/code&gt;’s &lt;code dir=&quot;auto&quot;&gt;on_finished_playback&lt;/code&gt; callback storage is gated behind a &lt;code dir=&quot;auto&quot;&gt;#define&lt;/code&gt; that only activates when the YAML actually subscribes. Both are tiny per-instance wins, but &lt;code dir=&quot;auto&quot;&gt;safe_mode&lt;/code&gt; is on essentially every device and &lt;code dir=&quot;auto&quot;&gt;rtttl&lt;/code&gt; is on every speaker setup that uses RTTTL playback.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;light&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;validate_&lt;/code&gt; clamp shrunk&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15728&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15728&lt;/a&gt;). The unit-range clamp helper used by every light component dropped its branch count and code size, with the speed-up showing up across PWM, RGB, RGBW, RGBWW, monochromatic, and addressable light platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;dsmr&lt;/code&gt; no longer allocates during parsing&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15875&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15875&lt;/a&gt;). The DSMR rewrite eliminates dynamic allocations in the parse path entirely and decrypts in place, saving roughly &lt;strong&gt;1500 bytes&lt;/strong&gt; of runtime allocation per telegram. See &lt;em&gt;Other Notable Features&lt;/em&gt; for the security-fix and OBIS-sensor side of the same PR.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;native-esp-idf-toolchain-support&quot;&gt;Native ESP-IDF Toolchain Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/diorcety&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@diorcety&lt;/a&gt; delivered a substantial new build pathway in &lt;a href=&quot;https://github.com/esphome/esphome/pull/14678&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14678&lt;/a&gt;: ESPHome can now build firmware directly with the native ESP-IDF toolchain via &lt;code dir=&quot;auto&quot;&gt;idf.py&lt;/code&gt;, alongside the existing PlatformIO build path. This is independent of &lt;code dir=&quot;auto&quot;&gt;framework.type&lt;/code&gt;, which still selects the runtime framework (&lt;code dir=&quot;auto&quot;&gt;arduino&lt;/code&gt; vs &lt;code dir=&quot;auto&quot;&gt;esp-idf&lt;/code&gt;); the new &lt;code dir=&quot;auto&quot;&gt;toolchain&lt;/code&gt; key selects the build system used to compile it.&lt;/p&gt;
&lt;p&gt;Opt in by setting &lt;code dir=&quot;auto&quot;&gt;toolchain&lt;/code&gt; under the &lt;code dir=&quot;auto&quot;&gt;esp32:&lt;/code&gt; block:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esp32&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;board&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp32dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;toolchain&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp-idf&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# or &apos;platformio&apos; (default)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;framework&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp-idf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The same selection is available on the command line and overrides the YAML value for one-off builds:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--toolchain&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;esp-idf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-device.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Precedence is &lt;code dir=&quot;auto&quot;&gt;--toolchain&lt;/code&gt; (CLI), then &lt;code dir=&quot;auto&quot;&gt;esp32.toolchain&lt;/code&gt; (YAML), then &lt;code dir=&quot;auto&quot;&gt;platformio&lt;/code&gt; (default toolchain).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automatic ESP-IDF installation&lt;/strong&gt; on first run with &lt;code dir=&quot;auto&quot;&gt;toolchain: esp-idf&lt;/code&gt;, into &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;data_dir&gt;/idf/&lt;/code&gt; (or &lt;code dir=&quot;auto&quot;&gt;$ESPHOME_ESP_IDF_PREFIX&lt;/code&gt; when set). ESPHome downloads the matching ESP-IDF release plus its Python environment, then builds through &lt;code dir=&quot;auto&quot;&gt;idf.py&lt;/code&gt; directly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic conversion of PlatformIO library entries&lt;/strong&gt; into ESP-IDF components (including the patches required), so projects that rely on &lt;code dir=&quot;auto&quot;&gt;lib_deps&lt;/code&gt; from the PlatformIO ecosystem keep working under the native toolchain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI workflow&lt;/strong&gt; added to compile components against the native toolchain on every PR so the path stays building as the codebase evolves.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The default toolchain remains &lt;code dir=&quot;auto&quot;&gt;platformio&lt;/code&gt; in 2026.5.0, so existing projects keep building exactly as they did before. The native path is opt-in for power users and contributors who want to work against the unmodified upstream IDF.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESP-IDF v6.0.1 readiness&lt;/strong&gt; lands across a chain of supporting PRs, primarily by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; with &lt;a href=&quot;https://github.com/diorcety&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@diorcety&lt;/a&gt; and &lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; contributing the dependency bumps: a new ESP-IDF 6.0.1 platform entry (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16146&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16146&lt;/a&gt;), an &lt;code dir=&quot;auto&quot;&gt;esp_wireguard&lt;/code&gt; bump to 0.4.5 for v6 compatibility (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15804&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15804&lt;/a&gt;), newlib compatibility for the Zigbee SDK on IDF 6 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16174&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16174&lt;/a&gt;) plus init-order and missing-field warning fixes on native ESP-IDF (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16389&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16389&lt;/a&gt;), relaxed &lt;code dir=&quot;auto&quot;&gt;-Werror=reorder&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;-Werror=maybe-uninitialized&lt;/code&gt; for managed components built under IDF 6 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16392&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16392&lt;/a&gt;), and a PlatformIO-style RAM/Flash summary printed after native ESP-IDF builds for parity with the existing flow (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16394&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16394&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;audio-stack-modernization&quot;&gt;Audio Stack Modernization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; led a comprehensive rewrite of the audio decoder pipeline across more than a dozen PRs, aligning ESPHome with a new family of streaming codec libraries published by the esphome-libs organization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New microDecoder family of libraries:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;microMP3&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16236&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16236&lt;/a&gt;), &lt;code dir=&quot;auto&quot;&gt;microWAV&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16251&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16251&lt;/a&gt;), &lt;code dir=&quot;auto&quot;&gt;microFLAC&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16279&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16279&lt;/a&gt;) replace the older Helix/esp-audio-libs decoders. Every codec now either streams from its source or buffers internally, which eliminates a &lt;code dir=&quot;auto&quot;&gt;memmove&lt;/code&gt; operation on the transfer buffer that, for MP3, used more CPU than the decoding itself.&lt;/li&gt;
&lt;li&gt;The unified &lt;code dir=&quot;auto&quot;&gt;microDecoder&lt;/code&gt; library (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15679&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15679&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16237&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16237&lt;/a&gt;) handles HTTP source reads, decoding, and threading internally. &lt;code dir=&quot;auto&quot;&gt;audio_file&lt;/code&gt; and the new &lt;code dir=&quot;auto&quot;&gt;audio_http&lt;/code&gt; media source (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15741&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15741&lt;/a&gt;) both build on it.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;esp-audio-libs&lt;/code&gt; was bumped to v3.0.0 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16263&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16263&lt;/a&gt;), keeping the resampler and optimized gain helpers but dropping the codec decoders to reduce compile time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New &lt;code dir=&quot;auto&quot;&gt;audio_http&lt;/code&gt; media source&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15741&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15741&lt;/a&gt;) plays audio from arbitrary HTTP URLs and serves as a replacement for prior workarounds. 48 kHz stereo MP3 now decodes with &lt;strong&gt;~40% less CPU on an ESP32-S3&lt;/strong&gt; thanks to the eliminated staging buffer and &lt;code dir=&quot;auto&quot;&gt;memmove&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advanced codec configuration&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16166&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16166&lt;/a&gt;) exposes per-codec options under &lt;code dir=&quot;auto&quot;&gt;audio.codecs.*&lt;/code&gt; so users can pick memory locations (internal vs PSRAM), enable specific codecs additively, and tune options like Opus’s pseudostack size. Users of slower ESP32s (no fast PSRAM) can now configure decoder buffers to live in internal memory and reduce stuttering at the start of playback.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RingBuffer made a first-class component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16298&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16298&lt;/a&gt;) by moving the core ring buffer into a dedicated &lt;code dir=&quot;auto&quot;&gt;ring_buffer&lt;/code&gt; helper component. External component authors can now iterate on it via &lt;code dir=&quot;auto&quot;&gt;external_components&lt;/code&gt;; the deprecation period for the old &lt;code dir=&quot;auto&quot;&gt;esphome/core/ring_buffer.h&lt;/code&gt; location is 6 months. A new &lt;code dir=&quot;auto&quot;&gt;RingBufferAudioSource&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16314&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16314&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16315&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16315&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16316&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16316&lt;/a&gt;) consolidates the speaker and mixer audio-source plumbing.&lt;/p&gt;
&lt;p&gt;Users with audio files referenced only via YAML actions (rather than embedded or set as the preferred format) may need to add &lt;code dir=&quot;auto&quot;&gt;audio.codecs.wav:&lt;/code&gt; to keep WAV decoding compiled in; see the Breaking Changes section for migration details.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;ota-platform-enhancements&quot;&gt;OTA Platform Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;OTA gained the broadest set of capabilities it has had in any single release, led by &lt;a href=&quot;https://github.com/Mat931&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Mat931&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Partition table updates&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15780&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15780&lt;/a&gt;) make it possible to convert devices from other firmwares (such as Tasmota) to ESPHome over the air. The updater verifies the new partition table, runs sanity checks, and only commits if it can prove the device will boot. Setting &lt;code dir=&quot;auto&quot;&gt;allow_partition_access: true&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;ota: platform: esphome&lt;/code&gt; enables the workflow; the docs walk through the Tasmota conversion step by step.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bootloader updates&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16238&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16238&lt;/a&gt;) build on the new extended OTA protocol (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16164&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16164&lt;/a&gt;) and let &lt;code dir=&quot;auto&quot;&gt;esphome upload --bootloader&lt;/code&gt; push a fresh bootloader image.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Soft-brick recovery via factory partition&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16339&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16339&lt;/a&gt;). When OTA is impossible because the alternate app partition is the wrong type but contains a valid app (for example, a Tasmota safeboot image), &lt;code dir=&quot;auto&quot;&gt;safe_mode&lt;/code&gt; can now boot into the factory partition so the device can be re-flashed instead of requiring a USB cable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web server OTA platform&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16207&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16207&lt;/a&gt;). A new &lt;code dir=&quot;auto&quot;&gt;--ota-platform {esphome,web_server}&lt;/code&gt; flag on &lt;code dir=&quot;auto&quot;&gt;esphome upload&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;esphome run&lt;/code&gt; lets users force the HTTP-based &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt; OTA path, which is auto-selected when only &lt;code dir=&quot;auto&quot;&gt;platform: web_server&lt;/code&gt; is configured. The native API path remains the default because it uses challenge-response auth with hashed nonces (the OTA password is never on the wire), while &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt; uses HTTP Basic auth.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Host platform OTA backend&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16304&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16304&lt;/a&gt;) implements working OTA for the host target via &lt;code dir=&quot;auto&quot;&gt;execv&lt;/code&gt;, unlocking integration-test coverage of one of the highest-risk regression surfaces in ESPHome. Tests can now exercise the full native OTA wire protocol (handshake, MD5, chunked transfer, automation triggers, reboot) on every CI run without needing real hardware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Better OTA error messages&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16327&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16327&lt;/a&gt;) and the use of &lt;code dir=&quot;auto&quot;&gt;WatchdogManager&lt;/code&gt; during ESP32 OTA writes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16138&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16138&lt;/a&gt;) round out the package.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;faster-configuration-validation-and-cli-startup&quot;&gt;Faster Configuration Validation and CLI Startup&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Four related changes by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; make &lt;code dir=&quot;auto&quot;&gt;esphome compile&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esphome upload&lt;/code&gt;, and especially &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt; noticeably faster on projects with remote dependencies, and shave wall-clock time off every CLI invocation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deferred heavy module-scope imports&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15955&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15955&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;esphome.__main__&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esphome.loader&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;esphome.config&lt;/code&gt; no longer pull &lt;code dir=&quot;auto&quot;&gt;voluptuous&lt;/code&gt;, codegen, and the component registry at import time; the heavy imports happen lazily inside the codepaths that actually need them. Every &lt;code dir=&quot;auto&quot;&gt;esphome&lt;/code&gt; CLI invocation, including &lt;code dir=&quot;auto&quot;&gt;esphome version&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;esphome config&lt;/code&gt;, and the dashboard’s per-request shells, starts faster, and the dashboard’s import-time regression is now guarded by CI.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skip external file refresh on &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt;&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16016&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16016&lt;/a&gt;). The &lt;code dir=&quot;auto&quot;&gt;skip_external_update&lt;/code&gt; flag is unified into a single &lt;code dir=&quot;auto&quot;&gt;CORE.skip_external_update&lt;/code&gt; source of truth and &lt;code dir=&quot;auto&quot;&gt;external_files.download_content()&lt;/code&gt; now honors it. For a Home Assistant Voice PE config (16+ remote audio files, several &lt;code dir=&quot;auto&quot;&gt;micro_wake_word&lt;/code&gt; models), the validation phase no longer spends ~20 sequential HTTP HEAD requests before logs can start streaming.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parallel external_files downloads&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16021&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16021&lt;/a&gt;) fan out per-file checks across an 8-worker thread pool. Wall time drops from &lt;code dir=&quot;auto&quot;&gt;sum(latency)&lt;/code&gt; to roughly &lt;code dir=&quot;auto&quot;&gt;max(latency)&lt;/code&gt; when the cache is warm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cached validated configs&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16381&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16381&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;esphome compile&lt;/code&gt; now writes the fully validated config to disk; &lt;code dir=&quot;auto&quot;&gt;upload&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;logs&lt;/code&gt; reload it instead of re-running &lt;code dir=&quot;auto&quot;&gt;read_config()&lt;/code&gt; from scratch. The cache is regenerated by every &lt;code dir=&quot;auto&quot;&gt;compile&lt;/code&gt;, so a follow-up &lt;code dir=&quot;auto&quot;&gt;upload&lt;/code&gt; to a freshly compiled binary skips the entire validation pipeline. No flag, no opt-in.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;sendspin-synchronized-multi-room-audio&quot;&gt;Sendspin Synchronized Multi-Room Audio&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; built a complete new component family for &lt;a href=&quot;https://www.sendspin-audio.com&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Sendspin&lt;/a&gt;, a multi-room synchronized audio protocol, across a chain of PRs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hub component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15924&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15924&lt;/a&gt;) provides the basic connection and group state distribution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controller role and switch action&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15929&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15929&lt;/a&gt;) lets devices move between active groups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Group media player platform&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15948&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15948&lt;/a&gt;) controls playback for a whole group (volume, transport, repeat, shuffle) without producing audio itself.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media source platform&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15950&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15950&lt;/a&gt;) plays synchronized audio, with fixed and runtime-tunable delay compensation for downstream DAC/amp latency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metadata text and numeric sensors&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15969&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15969&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15971&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15971&lt;/a&gt;) report title/artist/album plus a polling track-progress sensor designed to drive displays.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stutter reduction via sendspin-cpp v0.4.0&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16178&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16178&lt;/a&gt;) marks decoder paths hot, allows player buffers in internal memory, and raises the player task priority above the websocket server. Combined with the new audio codec configuration, this enables real-time stereo Opus playback on a plain ESP32.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;radio-frequency-entity-type&quot;&gt;Radio Frequency Entity Type&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; introduced a new top-level &lt;code dir=&quot;auto&quot;&gt;radio_frequency&lt;/code&gt; entity type (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15556&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15556&lt;/a&gt;) for representing RF transceivers in Home Assistant, alongside an &lt;code dir=&quot;auto&quot;&gt;ir_rf_proxy&lt;/code&gt; platform (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15744&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15744&lt;/a&gt;) that extends the existing infrared proxy with RF capability advertising (tunable frequency range, supported modulations).&lt;/p&gt;
&lt;p&gt;A driver-agnostic &lt;code dir=&quot;auto&quot;&gt;on_control&lt;/code&gt; trigger (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16368&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16368&lt;/a&gt;) lets any RF front-end chip (CC1101, RFM69, SX127x, custom externals) integrate with &lt;code dir=&quot;auto&quot;&gt;radio_frequency&lt;/code&gt; entities through YAML triggers alone, with no custom C++ wiring required. Chip-state turnaround for transmit/receive is handled through &lt;code dir=&quot;auto&quot;&gt;remote_transmitter&lt;/code&gt;’s existing &lt;code dir=&quot;auto&quot;&gt;on_transmit&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;on_complete&lt;/code&gt; triggers, keeping &lt;code dir=&quot;auto&quot;&gt;radio_frequency&lt;/code&gt; itself driver-agnostic. The implementation shares wire messages with the IR proxy to conserve protobuf message IDs.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;lvgl-improvements&quot;&gt;LVGL Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; continued landing LVGL refinements throughout the release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Flexible grid layouts&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16041&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16041&lt;/a&gt;) accept new shorthands like &lt;code dir=&quot;auto&quot;&gt;3x&lt;/code&gt; (3 rows, columns auto-derived) and &lt;code dir=&quot;auto&quot;&gt;x4&lt;/code&gt; (4 columns, rows derived from widget count). Either &lt;code dir=&quot;auto&quot;&gt;grid_rows&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;grid_columns&lt;/code&gt; can now be a single integer that expands to that many equal &lt;code dir=&quot;auto&quot;&gt;FR(1)&lt;/code&gt; cells.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Checked-state binary sensors&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16073&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16073&lt;/a&gt;) report toggle widget state directly, not just press state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Percentage line points&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16209&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16209&lt;/a&gt;) make resolution-independent line widgets straightforward.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Touch coordinates in event lambdas&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16272&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16272&lt;/a&gt;). &lt;code dir=&quot;auto&quot;&gt;on_pressed&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_pressing&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;on_release&lt;/code&gt; now receive an additional &lt;code dir=&quot;auto&quot;&gt;point&lt;/code&gt; parameter with object-relative coordinates.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;on_update&lt;/code&gt; trigger and &lt;code dir=&quot;auto&quot;&gt;trigger:&lt;/code&gt; option&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16312&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16312&lt;/a&gt;) distinguish programmatic value changes from user interactions for numbers and sensors.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The standalone &lt;code dir=&quot;auto&quot;&gt;mapping&lt;/code&gt; component also gained default values and metadata for cross-component validation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15861&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15861&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;zigbee-expanded-to-esp32-h2-and-c6&quot;&gt;Zigbee Expanded to ESP32 H2 and C6&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; brought ESP32-based Zigbee support to ESPHome in &lt;a href=&quot;https://github.com/esphome/esphome/pull/11553&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11553&lt;/a&gt;, porting the standalone &lt;code dir=&quot;auto&quot;&gt;zigbee_esphome&lt;/code&gt; external component into core. The implementation runs on the radio-equipped ESP32-C6 and ESP32-H2 variants and publishes ESPHome &lt;code dir=&quot;auto&quot;&gt;binary_sensor&lt;/code&gt; entities as Zigbee &lt;code dir=&quot;auto&quot;&gt;binary_input&lt;/code&gt; clusters, recognized automatically by ZHA and zigbee2mqtt. Zigbee router and end devices are supported.&lt;/p&gt;
&lt;p&gt;Follow-ups in this release expand the feature set:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sensors over Zigbee&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16026&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16026&lt;/a&gt;) exposes ESPHome &lt;code dir=&quot;auto&quot;&gt;sensor&lt;/code&gt; entities through the analog Zigbee data model.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;on_join&lt;/code&gt; trigger&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16060&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16060&lt;/a&gt;) fires when the device joins or rejoins the Zigbee network, with a bool indicating which case.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;power_source&lt;/code&gt; option&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16062&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16062&lt;/a&gt;) lets devices advertise their power source (battery vs mains).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;nrf52-and-zephyr-platform-improvements&quot;&gt;nRF52 and Zephyr Platform Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; continued landing the work that turns nRF52/Zephyr into a first-class ESPHome target, with substantial follow-ups across deep sleep, Zigbee, OTA, and native builds:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deep sleep with Zigbee wakeup&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13950&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13950&lt;/a&gt;) lets battery-powered nRF52 Zigbee devices sleep between events while still being woken by the radio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nRF52 Zigbee router&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16034&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16034&lt;/a&gt;) extends the existing Zigbee end-device support to router devices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loop-wake primitives implemented&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16032&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16032&lt;/a&gt;): &lt;code dir=&quot;auto&quot;&gt;wake_loop_threadsafe()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;wakeable_delay()&lt;/code&gt; now have real nRF52 implementations, so components that depend on these primitives (sockets, BLE, etc.) work the same way they do on ESP32.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional reset pin for DFU&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11684&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11684&lt;/a&gt;) makes the nRESET pin optional during DFU entry; less reliable, but feasible on boards that don’t break the pin out.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;zephyr_ble_server&lt;/code&gt; numeric comparison pairing&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14400&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14400&lt;/a&gt;) adds the &lt;code dir=&quot;auto&quot;&gt;on_numeric_comparison_request&lt;/code&gt; trigger for secure BLE pairing flows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bootloader reserve area&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16204&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16204&lt;/a&gt;) carves out a dedicated flash region so bootloader updates don’t collide with app flash.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crash logging on Zephyr&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16203&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16203&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16330&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16330&lt;/a&gt;) gives the logger a chance to print before reset, with a separate fix for a long-standing logger crash on Zephyr.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OTA-safe watchdog feeding&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16218&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16218&lt;/a&gt;) feeds the watchdog early during OTA so the device doesn’t roll back mid-update.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;west update&lt;/code&gt; progress messaging&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16321&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16321&lt;/a&gt;) makes it clear when Zephyr is fetching modules rather than hanging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native build preparation&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16193&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16193&lt;/a&gt;) and &lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;run_compile&lt;/code&gt; hook for external components&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16179&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16179&lt;/a&gt;) set up the path for the nRF52/Zephyr toolchain to follow the same native build model as the new ESP-IDF pathway above.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI coverage&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16188&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16188&lt;/a&gt;) adds nRF52 component tests so Zephyr-only changes actually get exercised in CI, and the Zephyr main loop drops a redundant &lt;code dir=&quot;auto&quot;&gt;yield()&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15694&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15694&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt; landed two OpenThread fixes that ride along on the same platform pathway: a coroutine-with-priority &lt;code dir=&quot;auto&quot;&gt;COMMUNICATION&lt;/code&gt; profile (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16318&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16318&lt;/a&gt;) and removal of a stale &lt;code dir=&quot;auto&quot;&gt;freertos/portmacro.h&lt;/code&gt; include that broke builds against newer toolchains (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16338&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16338&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-hardware-and-display-support&quot;&gt;New Hardware and Display Support&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32-P4 USB High Speed&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14584&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14584&lt;/a&gt;) by &lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt;: a new &lt;code dir=&quot;auto&quot;&gt;max_packet_size&lt;/code&gt; option on &lt;code dir=&quot;auto&quot;&gt;usb_host&lt;/code&gt; lets ESP32-P4 use 512-byte USB transfers instead of being fragmented to 64-byte Full Speed packets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configurable ESP32 watchdog timeout&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15908&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15908&lt;/a&gt;) by &lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt;: &lt;code dir=&quot;auto&quot;&gt;esp32.watchdog_timeout&lt;/code&gt; accepts 5-60 seconds for power-managed configurations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;esp32_ble&lt;/code&gt; PSRAM allocation&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15644&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15644&lt;/a&gt;) by &lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt;: a &lt;code dir=&quot;auto&quot;&gt;use_psram: true&lt;/code&gt; option directs Bluedroid to allocate from SPIRAM, freeing approximately &lt;strong&gt;40 kB of internal RAM&lt;/strong&gt; on PSRAM-equipped ESP32 boards.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SPDIF speaker output&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/8065&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#8065&lt;/a&gt;) by &lt;a href=&quot;https://github.com/johnboiles&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@johnboiles&lt;/a&gt;: a new I2S-based SPDIF speaker platform sends digital audio to optical receivers via any GPIO pin.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;modbus_server&lt;/code&gt; split&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15509&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15509&lt;/a&gt;) by &lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt;: a new dedicated &lt;code dir=&quot;auto&quot;&gt;modbus_server&lt;/code&gt; component, with flash savings of roughly 60% over the old wedged-in server mode (1.8 KB vs 4.5 KB) and 40% off the client-mode &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; (3.9 KB vs 6.4 KB).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New display variants&lt;/strong&gt;: epaper SSD1683 + Goodisplay GDEY042T81 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13910&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13910&lt;/a&gt;), Waveshare 3.97” e-paper (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15466&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15466&lt;/a&gt;), Waveshare ESP32-C6 LCD 1.47 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15776&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15776&lt;/a&gt;), Sunton ESP32-2424S012 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15812&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15812&lt;/a&gt;), Sunton 5”/7” mipi_rgb displays (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15858&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15858&lt;/a&gt;), Seeed reTerminal D1001 DSI display (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15867&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15867&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WiFi &lt;code dir=&quot;auto&quot;&gt;phy_mode&lt;/code&gt; for ESP8266&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16055&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16055&lt;/a&gt;) lets users pin the radio to &lt;code dir=&quot;auto&quot;&gt;11B&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;11G&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;11N&lt;/code&gt; from YAML to work around routers that misbehave with ESP8266 802.11n associations.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;ble-reliability-fix-for-bluetooth-proxies&quot;&gt;BLE Reliability Fix for Bluetooth Proxies&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/plazarre&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@plazarre&lt;/a&gt; tracked down a long-standing &lt;code dir=&quot;auto&quot;&gt;status=0x85&lt;/code&gt; (133) error class in &lt;a href=&quot;https://github.com/esphome/esphome/pull/16036&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16036&lt;/a&gt; that hit &lt;code dir=&quot;auto&quot;&gt;bluetooth_proxy&lt;/code&gt; users with sustained WiFi traffic, most visibly Yale/August lock owners. The fix tracks &lt;code dir=&quot;auto&quot;&gt;CONNECTED&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ESTABLISHED&lt;/code&gt; clients (not just transient connecting states) and holds &lt;code dir=&quot;auto&quot;&gt;ESP_COEX_PREFER_BT&lt;/code&gt; for the lifetime of any active connection. Same lock, same firmware, before vs after the patch:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Heavy WiFi traffic:&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;status=133&lt;/code&gt; timeout after 19 s &lt;strong&gt;becomes&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;status=0&lt;/code&gt; success in 228 ms.&lt;/li&gt;
&lt;li&gt;Production validation against a Yale BETA211123 lock with host BlueZ disabled: clean unlock via the patched proxy.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;other-notable-features&quot;&gt;Other Notable Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Voice assistant second audio channel&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16265&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16265&lt;/a&gt;) by &lt;a href=&quot;https://github.com/synesthesiam&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@synesthesiam&lt;/a&gt;: a &lt;code dir=&quot;auto&quot;&gt;MULTI_CHANNEL_AUDIO&lt;/code&gt; feature flag and a second microphone source let voice-pipeline stages receive separately optimized audio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;config-hash&lt;/code&gt; CLI command&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15548&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15548&lt;/a&gt;) by &lt;a href=&quot;https://github.com/ccutrer&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ccutrer&lt;/a&gt;: determines whether a re-flash is required by comparing a config hash to what is currently on the device.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;round_to_significant_digits&lt;/code&gt; filter&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11157&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11157&lt;/a&gt;) by &lt;a href=&quot;https://github.com/gapple&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@gapple&lt;/a&gt;: useful for ambient-light style sensors that span six orders of magnitude.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AC dimmer zero-crossing interrupt type&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15862&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15862&lt;/a&gt;) by &lt;a href=&quot;https://github.com/aselafernando&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@aselafernando&lt;/a&gt;: user-configurable interrupt edge for zero-cross detection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;lock&lt;/code&gt; open states&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15120&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15120&lt;/a&gt;) by &lt;a href=&quot;https://github.com/egormanga&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@egormanga&lt;/a&gt;: the &lt;code dir=&quot;auto&quot;&gt;lock&lt;/code&gt; entity gained &lt;code dir=&quot;auto&quot;&gt;OPENING&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;OPEN&lt;/code&gt; states.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SX126x cold sleep&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16144&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16144&lt;/a&gt;) by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;: a new &lt;code dir=&quot;auto&quot;&gt;cold:&lt;/code&gt; option on the sleep action reaches ~0.6 µA (roughly 1000x lower than warm sleep) for ESP32-deep-sleep-paired use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DSMR rewrite&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15875&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15875&lt;/a&gt;) by &lt;a href=&quot;https://github.com/PolarGoose&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@PolarGoose&lt;/a&gt; removes the &lt;code dir=&quot;auto&quot;&gt;Crypto-no-arduino&lt;/code&gt; dependency, eliminates dynamic allocations during parsing, in-place decrypts (saving ~1500 bytes), fixes a potential event-loop hang, fixes a missing GCM tag verification (a security vulnerability), and adds several missing OBIS sensors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Climate / water heater temperature unit API&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15815&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15815&lt;/a&gt;) by &lt;a href=&quot;https://github.com/jhenkens&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jhenkens&lt;/a&gt;: protobuf-level support for native Fahrenheit operation; the C++ implementation is staged for a follow-up release.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mitsubishi CN105 remote temperature API&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15558&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15558&lt;/a&gt;) by &lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt;: override the AC unit’s internal sensor with a value from an external sensor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nRF52 optional reset pin&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11684&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11684&lt;/a&gt;) by &lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt;: DFU entry without the nRESET pin (less reliable but feasible).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;codebase-correctness-and-developer-tooling&quot;&gt;Codebase Correctness and Developer Tooling&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A substantial sweep of correctness work landed alongside the features, led by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; (59 PRs this release) with help from &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; on the HAL split and CodSpeed coverage, &lt;a href=&quot;https://github.com/jpeletier&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jpeletier&lt;/a&gt; on substitution error messages, and &lt;a href=&quot;https://github.com/Komzpa&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Komzpa&lt;/a&gt; on reproducible builds.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;clang-tidy 22.1&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16078&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16078&lt;/a&gt;) replaces the years-old 18.1.8, surfacing latent issues across components.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nested namespace concatenation&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16294&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16294&lt;/a&gt;-&lt;a href=&quot;https://github.com/esphome/esphome/pull/16307&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16307&lt;/a&gt;) walks the entire component tree (a→c, d→h, i→m, n→r, s, t→z plus tests) collapsing &lt;code dir=&quot;auto&quot;&gt;namespace foo { namespace bar { ... } }&lt;/code&gt; into the modern &lt;code dir=&quot;auto&quot;&gt;namespace foo::bar { ... }&lt;/code&gt; and enabling the check to prevent regression.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;bugprone-unchecked-optional-access&lt;/code&gt; fixes&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16102&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16102&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16103&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16107&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16107&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16121&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16121&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16124&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16124&lt;/a&gt;) eliminate a class of unchecked &lt;code dir=&quot;auto&quot;&gt;std::optional&lt;/code&gt; access bugs across &lt;code dir=&quot;auto&quot;&gt;sprinkler&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pn532&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;feedback&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;time&lt;/code&gt; (&lt;code dir=&quot;auto&quot;&gt;CronTrigger&lt;/code&gt;), &lt;code dir=&quot;auto&quot;&gt;tormatic&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;haier&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CodSpeed coverage expansion&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15593&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15593&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15688&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15688&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15696&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15696&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15995&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15995&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16157&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16157&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16402&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16402&lt;/a&gt;) adds benchmarks for hot helper functions, SubscribeLogsResponse encode, Z-Wave/IR/RF/serial proxy messages, and the compiled-config cache fast path. The benchmark target now matches firmware optimization level (&lt;code dir=&quot;auto&quot;&gt;-Os&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HAL split per platform&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15977&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15977&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15978&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15978&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16111&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16111&lt;/a&gt;-&lt;a href=&quot;https://github.com/esphome/esphome/pull/16116&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16116&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16183&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16183&lt;/a&gt;) moves HAL bodies into per-platform files under &lt;code dir=&quot;auto&quot;&gt;components/&amp;#x3C;platform&gt;/hal.cpp&lt;/code&gt; and inlines trivial dispatches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Substitution error messages&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15874&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15874&lt;/a&gt;) by &lt;a href=&quot;https://github.com/jpeletier&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jpeletier&lt;/a&gt;: undefined-variable errors now show a full include stack trace (&lt;code dir=&quot;auto&quot;&gt;Included from packages[3] in my_project.yaml 11:2&lt;/code&gt;) instead of a flat &lt;code dir=&quot;auto&quot;&gt;packages-&gt;3-&gt;packages-&gt;net-&gt;wifi-&gt;ssid&lt;/code&gt; path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reproducible ESP-IDF builds&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/16008&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16008&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/16053&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16053&lt;/a&gt;) make ESPHome builds bit-for-bit reproducible.&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;thank-you-contributors&quot;&gt;Thank You, Contributors&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;This release includes 395 pull requests from over 50 contributors. A huge thank you to everyone who made 2026.5.0 possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; - 59 PRs including the seven-part nested-namespace clang-tidy sweep across the entire component tree, a clang-tidy 22 upgrade with the resulting correctness fixes, the SX126x cold sleep option, and substantial native ESP-IDF build polish&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; - 37 PRs including the audio stack rewrite on top of the new microMP3, microWAV, microFLAC, and microDecoder libraries, the &lt;code dir=&quot;auto&quot;&gt;ring_buffer&lt;/code&gt; helper component, the new &lt;code dir=&quot;auto&quot;&gt;audio_http&lt;/code&gt; media source, and the new Sendspin multi-room synchronized audio component family&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - 17 PRs including LVGL layout, gradient, percentage-line-point, touch-point, and &lt;code dir=&quot;auto&quot;&gt;on_update&lt;/code&gt; trigger improvements, new mipi_spi and mipi_dsi display models, and ESPNOW method-visibility cleanup&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; - 16 PRs including least-privilege workflow tokens, CI tooling tightening, and various build/release infrastructure improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; - 13 PRs including nRF52 + Zephyr native-build preparation, deep sleep with Zigbee wakeup, an nRF52 Zigbee router, and Zephyr OTA/watchdog/logger fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Mat931&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Mat931&lt;/a&gt; - 10 PRs including OTA partition-table and bootloader updates, the extended OTA protocol, &lt;code dir=&quot;auto&quot;&gt;safe_mode&lt;/code&gt; soft-brick recovery via the factory partition, and WatchdogManager fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; - 7 PRs including the new experimental &lt;code dir=&quot;auto&quot;&gt;radio_frequency&lt;/code&gt; entity type, the &lt;code dir=&quot;auto&quot;&gt;ir_rf_proxy&lt;/code&gt; RF extension and driver-agnostic &lt;code dir=&quot;auto&quot;&gt;on_control&lt;/code&gt; trigger, and i2s_audio refactoring&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; - 5 PRs expanding ESP32-based Zigbee support with binary sensors, sensors, the &lt;code dir=&quot;auto&quot;&gt;on_join&lt;/code&gt; trigger, and the &lt;code dir=&quot;auto&quot;&gt;power_source&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt; - 5 PRs including &lt;code dir=&quot;auto&quot;&gt;mitsubishi_cn105&lt;/code&gt; remote temperature API, half-degree setpoints, unified timeout handling, and vane / wide-vane support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/diorcety&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@diorcety&lt;/a&gt; - 4 PRs including the native ESP-IDF toolchain support and ESP-IDF v6 readiness work&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt; - 3 PRs including the configurable ESP32 &lt;code dir=&quot;auto&quot;&gt;watchdog_timeout&lt;/code&gt; and OpenThread improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Komzpa&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Komzpa&lt;/a&gt; - 3 PRs making ESP-IDF and Arduino builds bit-for-bit reproducible&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/egormanga&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@egormanga&lt;/a&gt; - 2 PRs adding &lt;code dir=&quot;auto&quot;&gt;OPENING&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;OPEN&lt;/code&gt; states to the &lt;code dir=&quot;auto&quot;&gt;lock&lt;/code&gt; component and its API protocol&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/guillempages&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@guillempages&lt;/a&gt; - 2 PRs including the &lt;code dir=&quot;auto&quot;&gt;tm1637&lt;/code&gt; brightness setter and Sunton mipi_rgb display definitions&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt; - 2 PRs including the &lt;code dir=&quot;auto&quot;&gt;esp32_ble&lt;/code&gt; &lt;code dir=&quot;auto&quot;&gt;use_psram&lt;/code&gt; option and a &lt;code dir=&quot;auto&quot;&gt;nextion&lt;/code&gt; TFT upload fix&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jpeletier&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jpeletier&lt;/a&gt; - 2 PRs including the include-stack-trace substitution error messages and a remote-packages &lt;code dir=&quot;auto&quot;&gt;vars&lt;/code&gt; substitution fix&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/PolarGoose&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@PolarGoose&lt;/a&gt; - 2 PRs rewriting &lt;code dir=&quot;auto&quot;&gt;dsmr&lt;/code&gt; for performance, dropping the &lt;code dir=&quot;auto&quot;&gt;Crypto-no-arduino&lt;/code&gt; dependency, and adding missing sensors and a GCM tag verification fix&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/johnboiles&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@johnboiles&lt;/a&gt; - the new SPDIF speaker output platform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; - the new &lt;code dir=&quot;auto&quot;&gt;modbus_server&lt;/code&gt; component split out of &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/plazarre&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@plazarre&lt;/a&gt; - the &lt;code dir=&quot;auto&quot;&gt;esp32_ble_tracker&lt;/code&gt; coex fix that resolves long-standing &lt;code dir=&quot;auto&quot;&gt;status=133&lt;/code&gt; GATT failures on &lt;code dir=&quot;auto&quot;&gt;bluetooth_proxy&lt;/code&gt; setups&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/synesthesiam&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@synesthesiam&lt;/a&gt; - the second audio channel for &lt;code dir=&quot;auto&quot;&gt;voice_assistant&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also thank you to &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, &lt;a href=&quot;https://github.com/gapple&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@gapple&lt;/a&gt;, &lt;a href=&quot;https://github.com/lboue&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@lboue&lt;/a&gt;, &lt;a href=&quot;https://github.com/balloob&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@balloob&lt;/a&gt;, &lt;a href=&quot;https://github.com/Eelviny&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Eelviny&lt;/a&gt;, &lt;a href=&quot;https://github.com/CircuitSetup&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@CircuitSetup&lt;/a&gt;, &lt;a href=&quot;https://github.com/ximex&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ximex&lt;/a&gt;, &lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt;, &lt;a href=&quot;https://github.com/mikeytdisco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mikeytdisco&lt;/a&gt;, &lt;a href=&quot;https://github.com/angelnu&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@angelnu&lt;/a&gt;, &lt;a href=&quot;https://github.com/puddly&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@puddly&lt;/a&gt;, &lt;a href=&quot;https://github.com/rwalker777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwalker777&lt;/a&gt;, &lt;a href=&quot;https://github.com/TimoPtr&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@TimoPtr&lt;/a&gt;, &lt;a href=&quot;https://github.com/Farmer-shin&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Farmer-shin&lt;/a&gt;, &lt;a href=&quot;https://github.com/ccutrer&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ccutrer&lt;/a&gt;, &lt;a href=&quot;https://github.com/SaVi456&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@SaVi456&lt;/a&gt;, &lt;a href=&quot;https://github.com/DidierA&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@DidierA&lt;/a&gt;, &lt;a href=&quot;https://github.com/schdro&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@schdro&lt;/a&gt;, &lt;a href=&quot;https://github.com/rishabmehta7&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rishabmehta7&lt;/a&gt;, &lt;a href=&quot;https://github.com/yvesf&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@yvesf&lt;/a&gt;, &lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt;, &lt;a href=&quot;https://github.com/jhenkens&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jhenkens&lt;/a&gt;, &lt;a href=&quot;https://github.com/ruimarinho&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ruimarinho&lt;/a&gt;, &lt;a href=&quot;https://github.com/aselafernando&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@aselafernando&lt;/a&gt;, &lt;a href=&quot;https://github.com/dbl-0&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dbl-0&lt;/a&gt;, &lt;a href=&quot;https://github.com/GelidusResearch&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@GelidusResearch&lt;/a&gt;, &lt;a href=&quot;https://github.com/oarcher&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@oarcher&lt;/a&gt;, &lt;a href=&quot;https://github.com/RubenKelevra&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@RubenKelevra&lt;/a&gt;, &lt;a href=&quot;https://github.com/dmik&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dmik&lt;/a&gt;, &lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt;, and &lt;a href=&quot;https://github.com/ggalt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ggalt&lt;/a&gt; for their contributions, and to everyone who reported issues, tested pre-releases, and helped in the community.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: server mode has been split out of &lt;code dir=&quot;auto&quot;&gt;modbus_controller&lt;/code&gt; into a new &lt;code dir=&quot;auto&quot;&gt;modbus_server&lt;/code&gt; component. Move &lt;code dir=&quot;auto&quot;&gt;server_registers&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;registers&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;server_courtesy_response&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;courtesy_response&lt;/code&gt; under a top-level &lt;code dir=&quot;auto&quot;&gt;modbus_server:&lt;/code&gt; block &lt;a href=&quot;https://github.com/esphome/esphome/pull/15509&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15509&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API&lt;/strong&gt;: default &lt;code dir=&quot;auto&quot;&gt;max_connections&lt;/code&gt; lowered from 8 to 5 on &lt;code dir=&quot;auto&quot;&gt;esp32&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;bk72xx&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;rtl87xx&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;ln882x&lt;/code&gt;. Set &lt;code dir=&quot;auto&quot;&gt;api.max_connections&lt;/code&gt; explicitly if you need more than 5 concurrent API connections &lt;a href=&quot;https://github.com/esphome/esphome/pull/15889&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15889&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OTA (esphome platform)&lt;/strong&gt;: multiple &lt;code dir=&quot;auto&quot;&gt;ota: - platform: esphome&lt;/code&gt; entries with different &lt;code dir=&quot;auto&quot;&gt;port:&lt;/code&gt; values are now rejected at config time. Use a single entry on one port &lt;a href=&quot;https://github.com/esphome/esphome/pull/15636&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15636&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;FloatOutput&lt;/code&gt; runtime power scaling (&lt;code dir=&quot;auto&quot;&gt;min_power&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;max_power&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;zero_means_zero&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;output.set_min_power&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;output.set_max_power&lt;/code&gt; actions) is now gated behind a build flag. You are only affected if you call &lt;code dir=&quot;auto&quot;&gt;id(...).set_min_power(...)&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;set_max_power(...)&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;set_zero_means_zero(...)&lt;/code&gt; from a lambda without ever using the YAML keys or actions. Add &lt;code dir=&quot;auto&quot;&gt;min_power: 0%&lt;/code&gt; (or any of the other keys) to a single &lt;code dir=&quot;auto&quot;&gt;output:&lt;/code&gt; entry to re-enable the runtime setters; the build will emit a clear &lt;code dir=&quot;auto&quot;&gt;static_assert&lt;/code&gt; error with the fix when this applies &lt;a href=&quot;https://github.com/esphome/esphome/pull/15998&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15998&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensor&lt;/strong&gt;: the &lt;code dir=&quot;auto&quot;&gt;throttle_average&lt;/code&gt; filter now rejects &lt;code dir=&quot;auto&quot;&gt;time_period&lt;/code&gt; values longer than 24 hours &lt;a href=&quot;https://github.com/esphome/esphome/pull/16169&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16169&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;audio-stack&quot;&gt;Audio Stack&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Audio / Media Player / Speaker&lt;/strong&gt;: WAV decoding is no longer always compiled in. WAV is still automatically enabled when you embed a WAV file, set &lt;code dir=&quot;auto&quot;&gt;format: WAV&lt;/code&gt; as the preferred pipeline format, or use the speaker media player with &lt;code dir=&quot;auto&quot;&gt;format: NONE&lt;/code&gt;. If you only ever play WAV from arbitrary URLs via YAML actions, add &lt;code dir=&quot;auto&quot;&gt;audio: codecs: wav:&lt;/code&gt; to your configuration &lt;a href=&quot;https://github.com/esphome/esphome/pull/16244&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16244&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media Player / Speaker / Speaker Source&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;codec_support_enabled&lt;/code&gt; on the speaker media player is now inert and deprecated. Codec inclusion is determined from the pipeline &lt;code dir=&quot;auto&quot;&gt;format:&lt;/code&gt; setting (use &lt;code dir=&quot;auto&quot;&gt;format: NONE&lt;/code&gt; to include all codecs, equivalent to the old &lt;code dir=&quot;auto&quot;&gt;all&lt;/code&gt; mode; &lt;code dir=&quot;auto&quot;&gt;format: WAV&lt;/code&gt; is the closest equivalent to the old &lt;code dir=&quot;auto&quot;&gt;none&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; mode) &lt;a href=&quot;https://github.com/esphome/esphome/pull/14771&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14771&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speaker Media Player&lt;/strong&gt;: files built into firmware via the &lt;code dir=&quot;auto&quot;&gt;files:&lt;/code&gt; block now have a 5 MB per-file size limit. Compress oversized files (or switch to a more efficient codec) before upgrading &lt;a href=&quot;https://github.com/esphome/esphome/pull/16266&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16266&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;behavior-changes&quot;&gt;Behavior Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Core (main loop)&lt;/strong&gt;: every component’s &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; now actually runs at the configured &lt;code dir=&quot;auto&quot;&gt;loop_interval_&lt;/code&gt; cadence (default ~62 Hz) instead of being pulled forward to ~128 Hz by unrelated scheduler activity. Background events (MQTT RX, USB RX, BLE, etc.) still wake their components within one tick. If your YAML implicitly depended on &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; being pulled forward by other scheduled work, components will now run less often; use &lt;code dir=&quot;auto&quot;&gt;HighFrequencyLoopRequester&lt;/code&gt; for fast wakes &lt;a href=&quot;https://github.com/esphome/esphome/pull/15792&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15792&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 BLE Tracker&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;ESP_COEX_PREFER_BT&lt;/code&gt; is now held for the full lifetime of any active BLE connection rather than reverting to balanced coex as soon as the handshake settles. This fixes &lt;code dir=&quot;auto&quot;&gt;status=0x85&lt;/code&gt; / 133 GATT failures on &lt;code dir=&quot;auto&quot;&gt;bluetooth_proxy&lt;/code&gt; setups under heavy WiFi load (notably Yale/August locks). Configurations holding long-lived BLE connections (for example a &lt;code dir=&quot;auto&quot;&gt;ble_client&lt;/code&gt; persistent sensor) may see lower WiFi throughput while the connection is up &lt;a href=&quot;https://github.com/esphome/esphome/pull/16036&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16036&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One Wire&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;OneWireBus::skip()&lt;/code&gt; now performs a bus reset before issuing the &lt;code dir=&quot;auto&quot;&gt;SKIP ROM&lt;/code&gt; command, fixing a long-standing 1-Wire protocol violation that could cause unreliable readings (such as the DS18B20 power-on &lt;code dir=&quot;auto&quot;&gt;25 °C&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;85 °C&lt;/code&gt; values). External components or lambdas calling &lt;code dir=&quot;auto&quot;&gt;skip()&lt;/code&gt; must handle the new &lt;code dir=&quot;auto&quot;&gt;bool&lt;/code&gt; return value (&lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; if reset/presence pulse failed) &lt;a href=&quot;https://github.com/esphome/esphome/pull/14669&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14669&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;undocumented-api-changes&quot;&gt;Undocumented API Changes&lt;/h3&gt;&lt;/div&gt;



&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;OneWireBus::skip()&lt;/code&gt; signature&lt;/strong&gt;: now returns &lt;code dir=&quot;auto&quot;&gt;bool&lt;/code&gt; (true on successful presence pulse, false on reset/no-device); also performs a bus reset before the &lt;code dir=&quot;auto&quot;&gt;SKIP ROM&lt;/code&gt; command. Callers must handle the return value &lt;a href=&quot;https://github.com/esphome/esphome/pull/14669&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14669&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;ComponentIterator::on_media_player&lt;/code&gt; is now pure virtual&lt;/strong&gt;: subclasses that don’t handle media players must add an &lt;code dir=&quot;auto&quot;&gt;override { return true; }&lt;/code&gt; stub guarded by &lt;code dir=&quot;auto&quot;&gt;#ifdef USE_MEDIA_PLAYER&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/15618&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15618&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heap-allocating helpers moved to &lt;code dir=&quot;auto&quot;&gt;alloc_helpers.h&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;alloc_helpers.cpp&lt;/code&gt;&lt;/strong&gt;: functions like &lt;code dir=&quot;auto&quot;&gt;str_lower_case&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;str_snprintf&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;format_hex&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;format_hex_pretty&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;format_mac_address_pretty&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;value_accuracy_to_string&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;base64_encode&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;base64_decode&lt;/code&gt; (vector overload), &lt;code dir=&quot;auto&quot;&gt;get_mac_address&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_mac_address_pretty&lt;/code&gt; and similar have been moved. &lt;code dir=&quot;auto&quot;&gt;helpers.h&lt;/code&gt; re-exports &lt;code dir=&quot;auto&quot;&gt;alloc_helpers.h&lt;/code&gt; for backward compatibility until 2026.11.0; update your includes before then &lt;a href=&quot;https://github.com/esphome/esphome/pull/15623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15623&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;PollingComponent()&lt;/code&gt; default constructor&lt;/strong&gt;: now initializes to &lt;code dir=&quot;auto&quot;&gt;SCHEDULER_DONT_RUN&lt;/code&gt; (&lt;code dir=&quot;auto&quot;&gt;UINT32_MAX&lt;/code&gt;) instead of &lt;code dir=&quot;auto&quot;&gt;1&lt;/code&gt;. External components that bypass codegen, call &lt;code dir=&quot;auto&quot;&gt;PollingComponent()&lt;/code&gt; with no argument, and never call &lt;code dir=&quot;auto&quot;&gt;set_update_interval()&lt;/code&gt; will stop polling. Pass an interval to the constructor or call &lt;code dir=&quot;auto&quot;&gt;set_update_interval()&lt;/code&gt; explicitly &lt;a href=&quot;https://github.com/esphome/esphome/pull/15832&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15832&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API &lt;code dir=&quot;auto&quot;&gt;clients_&lt;/code&gt; storage&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;APIServer::clients_&lt;/code&gt; changed from &lt;code dir=&quot;auto&quot;&gt;std::vector&lt;/code&gt; to compile-time &lt;code dir=&quot;auto&quot;&gt;std::array&lt;/code&gt;; the &lt;code dir=&quot;auto&quot;&gt;set_max_connections()&lt;/code&gt; runtime setter was removed and the cap is now the &lt;code dir=&quot;auto&quot;&gt;MAX_API_CONNECTIONS&lt;/code&gt; compile-time define populated from YAML &lt;a href=&quot;https://github.com/esphome/esphome/pull/15889&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15889&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;FloatOutput&lt;/code&gt; power scaling members gated&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;min_power_&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;max_power_&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;zero_means_zero_&lt;/code&gt; and the corresponding setters are now gated behind &lt;code dir=&quot;auto&quot;&gt;USE_OUTPUT_FLOAT_POWER_SCALING&lt;/code&gt;. Lambdas that call these setters require the YAML to opt in (see the user breaking-changes section); a compile-time &lt;code dir=&quot;auto&quot;&gt;static_assert&lt;/code&gt; documents the fix at the call site &lt;a href=&quot;https://github.com/esphome/esphome/pull/15998&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15998&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESPNOW method visibility and naming&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;play()&lt;/code&gt; is now correctly protected (was public); some methods/properties have been renamed for consistency with the YAML triggers (e.g. &lt;code dir=&quot;auto&quot;&gt;broadcasted&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;broadcast&lt;/code&gt;). External components extending the ESPNOW classes will need to update method names and visibility expectations &lt;a href=&quot;https://github.com/esphome/esphome/pull/16109&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16109&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Climate &lt;code dir=&quot;auto&quot;&gt;ClimateTraits&lt;/code&gt; accessors removed&lt;/strong&gt;: the 10 deprecated &lt;code dir=&quot;auto&quot;&gt;get/set_supports_*&lt;/code&gt; accessors (&lt;code dir=&quot;auto&quot;&gt;current_temperature&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;current_humidity&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;two_point_target_temperature&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;target_humidity&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;action&lt;/code&gt;) are gone after their 6-month window. Use &lt;code dir=&quot;auto&quot;&gt;add_feature_flags()&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;has_feature_flags()&lt;/code&gt; with the matching &lt;code dir=&quot;auto&quot;&gt;CLIMATE_*&lt;/code&gt; flag; note &lt;code dir=&quot;auto&quot;&gt;two_point_target_temperature&lt;/code&gt; maps to &lt;code dir=&quot;auto&quot;&gt;CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/16289&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16289&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EKTF2232 &lt;code dir=&quot;auto&quot;&gt;rts_pin&lt;/code&gt; migration shim removed&lt;/strong&gt;: the schema-level &lt;code dir=&quot;auto&quot;&gt;rts_pin&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;reset_pin&lt;/code&gt; rename helper is gone; configs still using &lt;code dir=&quot;auto&quot;&gt;rts_pin&lt;/code&gt; get a generic schema rejection instead of the friendly renamed-to error &lt;a href=&quot;https://github.com/esphome/esphome/pull/16289&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16289&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core ring buffer moved to &lt;code dir=&quot;auto&quot;&gt;ring_buffer&lt;/code&gt; helper component&lt;/strong&gt;: include from &lt;code dir=&quot;auto&quot;&gt;esphome/components/ring_buffer/ring_buffer.h&lt;/code&gt; and use the &lt;code dir=&quot;auto&quot;&gt;esphome::ring_buffer::RingBuffer&lt;/code&gt; namespace instead of &lt;code dir=&quot;auto&quot;&gt;esphome::RingBuffer&lt;/code&gt;. The old &lt;code dir=&quot;auto&quot;&gt;esphome/core/ring_buffer.h&lt;/code&gt; location is deprecated with a 6-month removal window; add &lt;code dir=&quot;auto&quot;&gt;AUTO_LOAD = [&quot;ring_buffer&quot;]&lt;/code&gt; to your component’s codegen &lt;a href=&quot;https://github.com/esphome/esphome/pull/16298&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#16298&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the &lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-5-1---may-25&quot;&gt;Release 2026.5.1 - May 25&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Bump zeroconf from 0.149.12 to 0.149.13 &lt;a href=&quot;https://github.com/esphome/esphome/pull/16520&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16520&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump zeroconf from 0.149.13 to 0.149.16 &lt;a href=&quot;https://github.com/esphome/esphome/pull/16533&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16533&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Filter noisy ‘git rev-parse’ errors when .git is stripped &lt;a href=&quot;https://github.com/esphome/esphome/pull/16521&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16521&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Fix tarfile extract crashing on Python 3.11 with None mode &lt;a href=&quot;https://github.com/esphome/esphome/pull/16530&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16530&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Write version.txt after extract so bootloader shows the real version &lt;a href=&quot;https://github.com/esphome/esphome/pull/16532&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16532&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Persist &amp;#x26; restore CORE.toolchain through StorageJSON &lt;a href=&quot;https://github.com/esphome/esphome/pull/16531&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16531&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Backport ninja linux-arm64 entry into tools.json on aarch64 hosts &lt;a href=&quot;https://github.com/esphome/esphome/pull/16527&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16527&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Default to remote HEAD when cg.add_library URL has no #ref &lt;a href=&quot;https://github.com/esphome/esphome/pull/16535&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16535&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espidf] Honor the dict shorthand for library.json dependencies &lt;a href=&quot;https://github.com/esphome/esphome/pull/16537&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16537&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Defer esp_panic_handler wrap so arduino-esp32 IDF component skips it &lt;a href=&quot;https://github.com/esphome/esphome/pull/16538&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16538&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[tuya] Restore null guard on status_pin lost in #16353 &lt;a href=&quot;https://github.com/esphome/esphome/pull/16539&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16539&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Break api_connection/api_server include cycle to drop custom unique_ptr deleter &lt;a href=&quot;https://github.com/esphome/esphome/pull/16542&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16542&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sx126x] Assert NSS before wait_busy so commands wake the chip from sleep &lt;a href=&quot;https://github.com/esphome/esphome/pull/16546&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16546&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Refresh compiled config cache after upload/logs fallback &lt;a href=&quot;https://github.com/esphome/esphome/pull/16548&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16548&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sendspin] Bump sendspin-cpp to v0.6.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/16553&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16553&lt;/a&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[dashboard] Fix flaky test_websocket_refresh_command on Windows CI &lt;a href=&quot;https://github.com/esphome/esphome/pull/16565&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16565&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[libretiny] Fix LN882H IRAM_ATTR injection point in patch_linker.py &lt;a href=&quot;https://github.com/esphome/esphome/pull/16570&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16570&lt;/a&gt; by &lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp8266] Use os_timer-based esp_delay() in delay() &lt;a href=&quot;https://github.com/esphome/esphome/pull/16563&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16563&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Wake main loop on ESP8266 software serial RX &lt;a href=&quot;https://github.com/esphome/esphome/pull/16562&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16562&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Demote IDF #warning deprecations from error under ESP-IDF toolchain &lt;a href=&quot;https://github.com/esphome/esphome/pull/16584&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16584&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bluetooth_proxy] Recover slot stuck in DISCONNECTING when CLOSE_EVT is dropped &lt;a href=&quot;https://github.com/esphome/esphome/pull/16588&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16588&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Replace per-class -Wno-error=X demotes with blanket -Wno-error for ESP-IDF toolchain &lt;a href=&quot;https://github.com/esphome/esphome/pull/16599&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16599&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Disable IDF’s COMPILER_DISABLE_DEFAULT_ERRORS so -Wno-error actually undoes -Werror &lt;a href=&quot;https://github.com/esphome/esphome/pull/16604&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16604&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-5-2---june-2&quot;&gt;Release 2026.5.2 - June 2&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[writer] Mark storage_should_clean as public API for device-builder &lt;a href=&quot;https://github.com/esphome/esphome/pull/16443&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16443&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Decode crash PCs via IDF toolchain on IDF builds &lt;a href=&quot;https://github.com/esphome/esphome/pull/16626&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16626&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[packages] Resolve git symlinks on Windows when materialized as text &lt;a href=&quot;https://github.com/esphome/esphome/pull/16657&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16657&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[libretiny] Fix RTL8710B IRAM_ATTR section being dropped from flashed image &lt;a href=&quot;https://github.com/esphome/esphome/pull/16616&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16616&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sx126x] fix a typo in image calibration on 863 - 870 Mhz frequency &lt;a href=&quot;https://github.com/esphome/esphome/pull/16731&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16731&lt;/a&gt; by &lt;a href=&quot;https://github.com/Fyleo&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Fyleo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Persist esphome.area in StorageJSON &lt;a href=&quot;https://github.com/esphome/esphome/pull/16710&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16710&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Clean build when the toolchain changes &lt;a href=&quot;https://github.com/esphome/esphome/pull/16744&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16744&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fix crash loop on VoiceAssistantConfigurationRequest &lt;a href=&quot;https://github.com/esphome/esphome/pull/16757&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16757&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-5-3---june-5&quot;&gt;Release 2026.5.3 - June 5&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[remote_base] Fix RC5 decoding at either receive polarity &lt;a href=&quot;https://github.com/esphome/esphome/pull/16767&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16767&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32][core] Restore ESP-IDF version on logs/upload fast path and clean build on framework change &lt;a href=&quot;https://github.com/esphome/esphome/pull/16770&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16770&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rp2040] Fix lwipopts template load on Windows extended-length paths &lt;a href=&quot;https://github.com/esphome/esphome/pull/16783&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16783&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_server] Fix duplicate Device Information Service with string UUIDs &lt;a href=&quot;https://github.com/esphome/esphome/pull/16784&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16784&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.5.0/&quot;&gt;full 2026.5.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2026.4.0: Faster ESP32 defaults and signed OTA</title><link>https://esphome.io/blog/2026/04/15/esphome-2026-4/</link><guid isPermaLink="true">https://esphome.io/blog/2026/04/15/esphome-2026-4/</guid><description>ESPHome 2026.4.0 raises ESP32 CPU frequency by default, adds signed OTA and an ESP8266 crash handler, and speeds up state logging and config loading.</description><pubDate>Wed, 15 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/spa06/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/spa06.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;SPA0​6​&lt;/div&gt;&lt;div&gt;Temperature ​&amp;#x26;​ ​Pressure&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/bmp581/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bmp581.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;BMP5​8​1​&lt;/div&gt;&lt;div&gt;Temperature ​&amp;#x26;​ ​Pressure&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hdc2080/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/hdc2080.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;HDC2​0​8​0​&lt;/div&gt;&lt;div&gt;Temperature ​&amp;#x26;​ ​Humidity&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/climate/mitsubishi_cn105/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/mitsubishi_electric.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Mitsubishi ​CN1​0​5​ ​Climate&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/emontx/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/emontx5.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;EmonTx&lt;/div&gt;&lt;div&gt;Voltage ​&amp;#x26;​ ​Current ​&amp;#x26;​ ​Power ​&amp;#x26;​ ​Energy ​&amp;#x26;​ ​Temperature&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/text_sensor/text/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/description.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Text ​component ​Text ​Sensor&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/number/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/description.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Number ​Sensor&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/ethernet/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ethernet.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;RP2​0​4​0​ ​Ethernet&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/internal_temperature/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/thermometer.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;nRF5​2​ ​Internal ​Temperature&lt;/div&gt;&lt;div&gt;Temperature&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.4.0 delivers major performance and reliability improvements across all platforms. ESP32 devices default to maximum CPU frequency (33% faster API operations), unlock 40KB extra IRAM, signed OTA verification, and custom partition tables. ESP8266 gets a crash handler matching ESP32/RP2040, and a new client-side state logging architecture achieves up to 46x faster sensor publishing by moving log formatting off the device. Bluetooth Proxy advertisement forwarding (the constant hot path) dropped to just ~1.8% of main loop time on ESP32-C3. 31 PRs prepare the codebase for ESP-IDF 6.0, and CodSpeed benchmarking infrastructure now catches performance regressions before they ship. The substitution system has been redesigned for up to 18x faster config loading with dynamic &lt;code dir=&quot;auto&quot;&gt;!include&lt;/code&gt; paths, Ethernet expands with 5 new chip types across ESP32 and RP2040, and GPIO expanders gain interrupt-driven operation cutting idle I2C traffic by 99.7%. This release also adds LVGL v9.5.0, native Mitsubishi CN105 climate control, 4 new sensor components, and a &lt;code dir=&quot;auto&quot;&gt;esphome bundle&lt;/code&gt; CLI command to assist with remote compilation.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;If you use LVGL with &lt;code dir=&quot;auto&quot;&gt;rotation&lt;/code&gt; configured on the display component, move the &lt;code dir=&quot;auto&quot;&gt;rotation&lt;/code&gt; setting to the &lt;code dir=&quot;auto&quot;&gt;lvgl:&lt;/code&gt; block, and remove touchscreen &lt;code dir=&quot;auto&quot;&gt;transform:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you use the &lt;code dir=&quot;auto&quot;&gt;i2s_audio&lt;/code&gt; media player, migrate to the &lt;code dir=&quot;auto&quot;&gt;speaker&lt;/code&gt; media player component (the &lt;code dir=&quot;auto&quot;&gt;i2s_audio&lt;/code&gt; media player has been removed)&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;use_legacy&lt;/code&gt; in your &lt;code dir=&quot;auto&quot;&gt;i2s_audio&lt;/code&gt; config, remove it (the legacy I2S driver has been removed)&lt;/li&gt;
&lt;li&gt;If you have battery-powered ESP32/S2/S3/C5 devices, add &lt;code dir=&quot;auto&quot;&gt;cpu_frequency: 160MHZ&lt;/code&gt; to your config (the default is now 240MHz)&lt;/li&gt;
&lt;li&gt;If you have two YAML keys that resolve to the same substituted name, note that the later key now takes precedence (“last writer wins”)&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;sen5x&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;voc_baseline&lt;/code&gt;, remove it (it was dead code that never worked; use &lt;code dir=&quot;auto&quot;&gt;store_baseline: true&lt;/code&gt; instead)&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;rp2040_pio_led_strip&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;chipset: CUSTOM&lt;/code&gt;, use explicit &lt;code dir=&quot;auto&quot;&gt;bit0_high&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;bit0_low&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;bit1_high&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;bit1_low&lt;/code&gt; timing parameters instead&lt;/li&gt;
&lt;li&gt;If you use Nextion &lt;code dir=&quot;auto&quot;&gt;get_wave_chan_id()&lt;/code&gt; in lambdas, switch to &lt;code dir=&quot;auto&quot;&gt;get_wave_channel_id()&lt;/code&gt; (the old method is deprecated, removal in 2026.10.0)&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;sensor.raw_state&lt;/code&gt; in lambdas, migrate to using filtered state or &lt;code dir=&quot;auto&quot;&gt;on_raw_value&lt;/code&gt; triggers (&lt;code dir=&quot;auto&quot;&gt;.raw_state&lt;/code&gt; is deprecated)&lt;/li&gt;
&lt;li&gt;If you maintain external components that call &lt;code dir=&quot;auto&quot;&gt;TEMPLATABLE_VALUE&lt;/code&gt; macro-generated setters with raw C++ constants, route values through &lt;code dir=&quot;auto&quot;&gt;cg.templatable()&lt;/code&gt; in Python codegen&lt;/li&gt;
&lt;li&gt;If you maintain external components using &lt;code dir=&quot;auto&quot;&gt;ButtonPressTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SensorStateTrigger&lt;/code&gt;, or similar trigger classes, migrate to &lt;code dir=&quot;auto&quot;&gt;build_callback_automation()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you maintain external components using &lt;code dir=&quot;auto&quot;&gt;FlushResult&lt;/code&gt;, rename to &lt;code dir=&quot;auto&quot;&gt;UARTFlushResult&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;UART_FLUSH_RESULT_&lt;/code&gt; prefix&lt;/li&gt;
&lt;/ul&gt;


&lt;div&gt;&lt;h2 id=&quot;esp32-performance-and-security-improvements&quot;&gt;ESP32 Performance and Security Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Several ESP32 platform changes improve performance, security, and flexibility.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Default CPU Frequency Raised to Maximum&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15143&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15143&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;ESP32, ESP32-S2, ESP32-S3, and ESP32-C5 now default to &lt;strong&gt;240MHz&lt;/strong&gt; instead of 160MHz. This restores the performance level that Arduino users had before May 2025 and delivers ~34% faster CPU-bound operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API encryption handshake&lt;/strong&gt;: 90ms to 64ms (29% faster)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protobuf encoding&lt;/strong&gt; (BLE proxy): 34% faster&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Noise encryption&lt;/strong&gt;: 33-34% faster across all payload sizes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Users on battery power or with thermal constraints can override with &lt;code dir=&quot;auto&quot;&gt;cpu_frequency: 160MHZ&lt;/code&gt;. This is a breaking change as it increases power consumption on affected variants.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESP32 crash handler improvements&lt;/strong&gt;: The existing crash handler now captures backtraces from &lt;strong&gt;both cores&lt;/strong&gt; on dual-core ESP32 variants (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15559&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15559&lt;/a&gt;) and preserves crash data across OTA rollback reboots (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15578&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15578&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;40KB extra IRAM on original ESP32&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14874&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14874&lt;/a&gt;): A new option reclaims 40KB of previously reserved SRAM1 as IRAM, expanding the flash cache window and reducing cache misses for WiFi, BLE, and API operations, at no cost to heap. ESPHome will automatically detect your bootloader version at boot and suggest enabling this option only when it is safe to do so. &lt;strong&gt;Do not enable this option without the bootloader check confirming it is safe&lt;/strong&gt;; enabling it with a pre-v5.1 bootloader will brick the device (requiring USB reflash to recover). See the &lt;a href=&quot;https://esphome.io/components/esp32#advanced-configuration&quot;&gt;ESP32 documentation&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Signed OTA verification&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15357&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15357&lt;/a&gt;): New &lt;code dir=&quot;auto&quot;&gt;signed_ota_verification&lt;/code&gt; option enables firmware signature verification during OTA updates without requiring hardware Secure Boot (eFuse burning). Two workflows are supported:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Private key mode&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;signing_key&lt;/code&gt;) - Firmware is automatically signed during build. Simplest setup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public key mode&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;verification_key&lt;/code&gt;) - Only the public key is embedded; binaries are signed externally (e.g., in CI/CD with the private key in a secure vault).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esp32&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;framework&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp-idf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;advanced&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;signed_ota_verification&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;signing_key&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;secure_boot_signing_key.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;signing_scheme&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;rsa3072&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Custom partition tables&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7682&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#7682&lt;/a&gt;): Components and YAML configs can now define custom data/app partitions that are appended to the flash layout. The partition table generation has been unified across Arduino and IDF, and NVS has been moved to the end of flash with increased size (20KB to 384KB on Arduino). See the &lt;a href=&quot;https://esphome.io/components/esp32#partitions&quot;&gt;ESP32 documentation&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESP-IDF 5.5.4 and Arduino 3.3.8&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15666&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15666&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15705&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15705&lt;/a&gt;): Platform bumped to pioarduino 55.03.38-1 with ESP-IDF 5.5.4 and Arduino 3.3.8. PlatformIO is now run in a subprocess to isolate its virtualenv from ESPHome, preventing import errors after build.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ADC crash fix&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15717&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15717&lt;/a&gt;): ADC oneshot control functions are now placed in IRAM for cache safety. Previously, ADC reads could crash when flash cache was disabled during background NVS writes by WiFi, BLE, Zigbee, Thread, or power management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web server OTA brick hazard fix&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15720&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15720&lt;/a&gt;): Fixed a long-standing brick hazard in the captive portal and web server OTA flow where an interrupted upload followed by a retry could write concatenated firmware to flash, producing an invalid image that soft-bricked the device and required a serial flash to recover. The OTA backend now resets on each new upload.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mDNS crash fix&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15670&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15670&lt;/a&gt;): Bumped espressif/mdns to 1.11.0, fixing heap corruption when processing sustained mDNS browse traffic that caused deterministic LoadProhibited crashes, and a null pointer exception in &lt;code dir=&quot;auto&quot;&gt;mdns_parse_packet&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp8266-crash-handler-without-a-serial-cable&quot;&gt;ESP8266 Crash Handler, Without a Serial Cable&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Completing the platform coverage started in &lt;a href=&quot;https://esphome.io/blog/2026/03/18/esphome-2026-3/#crash-handlers-without-a-serial-cable&quot;&gt;2026.3.0&lt;/a&gt; (which added crash handlers for ESP32 and RP2040), ESP8266 devices now have the same post-mortem crash diagnostics (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15465&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15465&lt;/a&gt;). When a device crashes, the exception details and up to 16 stack-scanned backtrace addresses are saved to RTC memory and reported over the API on the next boot. &lt;strong&gt;No USB cable required&lt;/strong&gt;; crash data appears in &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt; (which automatically decodes addresses to source locations via &lt;code dir=&quot;auto&quot;&gt;addr2line&lt;/code&gt;) and the Home Assistant log viewer, entirely over WiFi.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[E][esp8266]: *** CRASH DETECTED ON PREVIOUS BOOT ***&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[E][esp8266]:   Reason: Exception - StoreProhibit (exccause=29)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[E][esp8266]:   PC: 0x40212EC5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[E][esp8266]:   EXCVADDR: 0x00000000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[E][esp8266]:   BT0: 0x40212F5A&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[E][esp8266]:   BT1: 0x40203B10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;PC&lt;/code&gt; is the program counter where the crash occurred, &lt;code dir=&quot;auto&quot;&gt;EXCVADDR&lt;/code&gt; is the memory address that caused the fault, and &lt;code dir=&quot;auto&quot;&gt;BT0&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;BT1&lt;/code&gt;/etc. are the stack backtrace showing the call chain leading to the crash. When using &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt;, these addresses are automatically decoded to source file and line numbers via &lt;code dir=&quot;auto&quot;&gt;addr2line&lt;/code&gt;, so you see the actual function names instead of raw hex.&lt;/p&gt;
&lt;p&gt;No configuration needed; it’s automatically enabled for all ESP8266 devices. Resource cost is minimal: 0 bytes RAM, 119 bytes IRAM, ~1KB flash.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;client-side-state-logging&quot;&gt;Client-Side State Logging&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;State change logging has been fundamentally redesigned to eliminate the single biggest CPU bottleneck on every ESPHome device (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15155&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15155&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Every entity state change (&lt;code dir=&quot;auto&quot;&gt;&apos;CO2&apos; &gt;&gt; 420 ppm&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;&apos;Light&apos; - Setting ON&lt;/code&gt;) previously ran &lt;code dir=&quot;auto&quot;&gt;vsnprintf&lt;/code&gt; on the device to format a log string and sent it over UART, even when nobody was watching the serial console (which is 99.9% of devices). CodSpeed benchmarks revealed this was consuming &lt;strong&gt;95%+ of sensor publish time&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;State change logs are now reconstructed on the client instead of the device. When &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt; or the dashboard connects, it subscribes to compact protobuf state messages and formats them locally. The protobuf messages are a fraction of the size of formatted strings, and formatting happens on your computer instead of the microcontroller. This achieves up to &lt;strong&gt;46x faster&lt;/strong&gt; in the publish path, with flash savings of &lt;strong&gt;1.4KB&lt;/strong&gt; (ESP32-C3) to &lt;strong&gt;2.2KB&lt;/strong&gt; (ESP8266). State changes still appear in logs as &lt;code dir=&quot;auto&quot;&gt;[S]&lt;/code&gt; lines in bright cyan:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[18:03:14.677][S][sensor]: &apos;CO2&apos; &gt;&gt; 420 ppm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[18:03:14.677][S][sensor]: &apos;Temperature&apos; &gt;&gt; 35.63 °C&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[18:03:51.747][S][light]: &apos;Light&apos; &gt;&gt; ON&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A new &lt;code dir=&quot;auto&quot;&gt;--no-states&lt;/code&gt; flag (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15160&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15160&lt;/a&gt;) lets users suppress state change lines entirely for the first time, useful for debugging when the log is flooded with sensor readings. Users who need the old device-side state logging can opt back in by setting &lt;code dir=&quot;auto&quot;&gt;logger: level: VERBOSE&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;preliminary-esp-idf-6-0-compatibility&quot;&gt;Preliminary ESP-IDF 6.0 Compatibility&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release includes &lt;strong&gt;31 pull requests&lt;/strong&gt; preparing ESPHome for ESP-IDF 6.0, which brings GCC 15, picolibc, and significant API changes from Espressif. Led by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;, this effort touches cryptography, drivers, and toolchain compatibility across the entire codebase. While ESP-IDF 6.0 is not yet the default framework version, these changes ensure ESPHome is ready when it ships. All related PRs are tagged with the &lt;a href=&quot;https://github.com/esphome/esphome/pulls?q=label%3Aidf-6+is%3Amerged&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;idf-6&lt;/code&gt;&lt;/a&gt; label.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PSA Crypto API migration:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;IDF 6.0 deprecates the legacy mbedTLS crypto APIs. All ESPHome cryptographic operations have been migrated to the new PSA Crypto API:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SHA-256 hashing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14809&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14809&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;HMAC-SHA256 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14814&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14814&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;BLE tracker PSA Crypto (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14811&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14811&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;BTHome/Xiaomi BLE CCM decryption (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14816&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14816&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;DLMS meter GCM decryption (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14817&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14817&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Driver and API compatibility fixes across 20+ components:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WiFi, ADC, LEDC, RMT (LED strips, remote transmitter/receiver), MIPI DSI, PSRAM, I2S audio, I2C, deep sleep, MQTT, USB host, OpenTherm timer, ethernet, debug, and camera components all updated for IDF 6.0 API changes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Toolchain compatibility:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PicoLibC &lt;code dir=&quot;auto&quot;&gt;std::isnan&lt;/code&gt; conflict resolved (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14768&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14768&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;vfprintf&lt;/code&gt; printf stub fixed for picolibc (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15172&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15172&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Implicit &lt;code dir=&quot;auto&quot;&gt;int&lt;/code&gt;-to-&lt;code dir=&quot;auto&quot;&gt;gpio_num_t&lt;/code&gt; conversions fixed for GCC 15 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14830&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14830&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Legacy I2S driver removed in preparation for IDF 6.0 where it no longer exists (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14932&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14932&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;substitution-system-overhaul&quot;&gt;Substitution System Overhaul&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/jpeletier&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jpeletier&lt;/a&gt;, the YAML configuration system receives two major improvements that make complex, multi-file configurations far more powerful and faster to load.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Substitutions in &lt;code dir=&quot;auto&quot;&gt;!include&lt;/code&gt; paths&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12213&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12213&lt;/a&gt;): You can now use substitution variables and Jinja expressions directly in &lt;code dir=&quot;auto&quot;&gt;!include&lt;/code&gt; filenames, enabling dynamic file selection:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;substitutions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;eth_model&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;LAN8720&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;packages&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;!include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;network/${eth_model}/config.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This works with command-line substitutions too, allowing the same YAML to target different hardware configurations without duplicating files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;18x faster config loading&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14918&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14918&lt;/a&gt;): The substitution engine has been redesigned to perform all variable substitutions in a single linear pass instead of the previous multi-pass approach. This achieves up to &lt;strong&gt;18x faster config load times&lt;/strong&gt; for large projects with many packages and includes. The rewrite also fixes several edge cases where cross-file variable references (&lt;code dir=&quot;auto&quot;&gt;${A * B}&lt;/code&gt; mixing local and root variables) were unreliable. Note that &lt;code dir=&quot;auto&quot;&gt;merge_config&lt;/code&gt; argument order for duplicate substituted keys has changed to “last writer wins.”&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;ethernet-expansion&quot;&gt;Ethernet Expansion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Building on RP2040/RP2350’s &lt;a href=&quot;https://esphome.io/blog/2026/03/18/esphome-2026-3/#rp2040rp2350-first-class-platform-support&quot;&gt;first-class platform support in 2026.3.0&lt;/a&gt;, this release dramatically expands Ethernet support across platforms, adding &lt;strong&gt;5 new chip types&lt;/strong&gt; and bringing SPI Ethernet to the RP2040 platform for the first time. RP2040 boards like the WIZnet EVB-Pico series can now be used as wired IoT controllers without WiFi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New RP2040 Ethernet Support:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;W5500&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14820&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14820&lt;/a&gt;) - 100Mbps SPI Ethernet, stress tested with 344 successful API connections on a WIZnet W5500-EVB-Pico&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;W5100/W5100S&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15131&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15131&lt;/a&gt;) - 10/100Mbps SPI Ethernet for boards like the W5100S-EVB-Pico&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;W6100 and W6300&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15543&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15543&lt;/a&gt;) - Next-generation WIZnet controllers with IPv6 support for boards like the W6300-EVB-Pico2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cross-Platform Additions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ENC28J60&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14945&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14945&lt;/a&gt;) - Microchip’s widely-available 10BASE-T controller now supported on both ESP32 (IDF) and RP2040&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ESP32 Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SPI interface selection&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10285&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#10285&lt;/a&gt;) - New &lt;code dir=&quot;auto&quot;&gt;interface&lt;/code&gt; config variable lets ESP32 users select &lt;code dir=&quot;auto&quot;&gt;spi2&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;spi3&lt;/code&gt; host, resolving conflicts with display components on boards like the M5Stack CoreS3&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;gpio-expander-interrupt-support&quot;&gt;GPIO Expander Interrupt Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://esphome.io/components/pcf8574&quot;&gt;PCF8574&lt;/a&gt;, &lt;a href=&quot;https://esphome.io/components/pca9554&quot;&gt;PCA9554&lt;/a&gt;, &lt;a href=&quot;https://esphome.io/components/mcp230xx&quot;&gt;MCP23008/MCP23017&lt;/a&gt;, &lt;a href=&quot;https://esphome.io/components/mcp23Sxx&quot;&gt;MCP23S08/MCP23S17&lt;/a&gt;, &lt;a href=&quot;https://esphome.io/components/pi4ioe5v6408&quot;&gt;PI4IOE5V6408&lt;/a&gt;, &lt;a href=&quot;https://esphome.io/components/mcp230xx/#mcp23016-label&quot;&gt;MCP23016&lt;/a&gt;, &lt;a href=&quot;https://esphome.io/components/pca6416a&quot;&gt;PCA6416A&lt;/a&gt;, and &lt;a href=&quot;https://esphome.io/components/tca9555&quot;&gt;TCA9555&lt;/a&gt; GPIO expander components now support an optional &lt;code dir=&quot;auto&quot;&gt;interrupt_pin&lt;/code&gt; that eliminates I2C/SPI polling entirely (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15444&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15444&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15445&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15445&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15616&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15616&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15614&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15614&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15613&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15613&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Supported Expanders:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PCF8574, PCA9554, PCA6416A, TCA9555&lt;/strong&gt; - I2C GPIO expanders&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP23008, MCP23017, MCP23S08, MCP23S17, MCP23016&lt;/strong&gt; - I2C and SPI GPIO expander family&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PI4IOE5V6408&lt;/strong&gt; - I2C GPIO expander&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Measured Impact (ESP32-IDF, PCF8574 + 3 binary sensors):&lt;/strong&gt;&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Metric&lt;/th&gt;&lt;th&gt;Polling&lt;/th&gt;&lt;th&gt;Interrupt&lt;/th&gt;&lt;th&gt;Improvement&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;I2C reads/min (idle)&lt;/td&gt;&lt;td&gt;4100ms&lt;/td&gt;&lt;td&gt;12ms&lt;/td&gt;&lt;td&gt;&lt;strong&gt;99.7% reduction&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Loop iterations per gate cycle&lt;/td&gt;&lt;td&gt;7477&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;strong&gt;468x fewer&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Binary sensor read time&lt;/td&gt;&lt;td&gt;~0.6ms (I2C)&lt;/td&gt;&lt;td&gt;~0.002ms (cache)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;300x faster&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;When configured, binary sensors return from cache (no bus reads) between interrupts, and the main loop is completely disabled until a pin change occurs. The MCP23x17 automatically enables the MIRROR bit so a single interrupt wire catches changes on all 16 pins.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pcf8574&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;my_pcf8574&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;interrupt_pin&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;GPIO16&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;performance-benchmarking-with-codspeed&quot;&gt;Performance Benchmarking with CodSpeed&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release introduces comprehensive C++ benchmarking infrastructure using &lt;a href=&quot;https://codspeed.io/esphome/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;CodSpeed&lt;/a&gt;, enabling continuous performance tracking and regression prevention. While initially added to protect the gains from 2026.3.0, the benchmarks quickly revealed remaining bottlenecks and drove a wave of targeted optimizations throughout this release cycle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benchmarks added:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Protobuf encoding/decoding (API messages, BLE advertisements, ListEntities)&lt;/li&gt;
&lt;li&gt;Noise encryption handshakes and payload encryption&lt;/li&gt;
&lt;li&gt;Sensor, binary sensor, light, cover, climate, fan, number, select, switch, text_sensor, and button publish/call paths&lt;/li&gt;
&lt;li&gt;Scheduler interval and timeout operations&lt;/li&gt;
&lt;li&gt;Plaintext and encrypted API frame writes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API layer optimizations&lt;/strong&gt; (the native API is the primary communication path between ESPHome devices and Home Assistant). The goal was to make Bluetooth Proxy lightweight enough that every ESP32-C3 can run it without worrying about performance impact, and this release delivers: combined with changes from 2026.3.0, the API and BLE proxy advertisement forwarding (the constant hot path) now consume only ~1.8% of main loop runtime on ESP32-C3, down from ~3.3% in 2026.3.0 and a fraction of what it was a year ago:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Protobuf encoding&lt;/strong&gt;: 17-20% faster with register-optimized write path (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15290&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15290&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Precomputed tag bytes&lt;/strong&gt;: Varint and length-delimited field tags computed at compile time (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15067&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15067&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frame write hot path&lt;/strong&gt;: Peeled first write iteration, inlined socket writes, zero-gap batch encoding. Single sensor state writes &lt;strong&gt;72% faster&lt;/strong&gt;, batch writes &lt;strong&gt;21% faster&lt;/strong&gt;, stack frame reduced from 352 to 48 bytes (-86%) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15063&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15063&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Varint encoding optimized&lt;/strong&gt;: Plaintext varint encoding and write_protobuf_packet devirtualized (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14758&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14758&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Command dispatch devirtualized&lt;/strong&gt;: Eliminates virtual call overhead on every incoming API message (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15044&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15044&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protobuf decode non-virtual&lt;/strong&gt;: ProtoDecodableMessage::decode() devirtualized (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15076&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15076&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Constant-size varint codegen&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;max_value&lt;/code&gt; proto option eliminates variable-length encoding for bounded fields (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15424&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15424&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entity name/object_id optimized&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;max_data_length&lt;/code&gt; proto option for known-bounded string fields (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15426&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15426&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fixed32 decode&lt;/strong&gt;: Uses memcpy on little-endian platforms instead of byte-shifting (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15292&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15292&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raw tag+value writes&lt;/strong&gt;: Forced fixed32 key fields emit raw bytes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15051&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15051&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Float zero checks&lt;/strong&gt;: Integer comparison instead of floating-point (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15490&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15490&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code size reduction&lt;/strong&gt;: Buffer and nodelay optimizations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14797&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14797&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Overflow buffer extracted&lt;/strong&gt;: Frame helper buffer management simplified (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14871&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14871&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Noise encryption speedup&lt;/strong&gt;: Continuing from the &lt;a href=&quot;https://esphome.io/blog/2026/03/18/esphome-2026-3/#api-and-protobuf-performance&quot;&gt;ChaCha20-Poly1305 optimization in 2026.3.0&lt;/a&gt; (which achieved 8-32% faster encryption), this release enables &lt;code dir=&quot;auto&quot;&gt;HAVE_WEAK_SYMBOLS&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;HAVE_INLINE_ASM&lt;/code&gt; for libsodium, replacing a volatile byte-by-byte &lt;code dir=&quot;auto&quot;&gt;sodium_memzero()&lt;/code&gt; fallback with word-sized &lt;code dir=&quot;auto&quot;&gt;memset()&lt;/code&gt;. Small messages (the common case for sensor updates and service calls) see the biggest gains: &lt;strong&gt;24% faster on ESP32, 11% on ESP8266, 10% on RP2040&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15038&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15038&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Noise handshake&lt;/strong&gt;: Split state_action_ to reduce stack pressure (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15464&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PSK update&lt;/strong&gt;: Avoided heap allocation in timeout lambda (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14921&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14921&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Batch encoding&lt;/strong&gt;: Simplified encode_to_buffer to single resize call, inlined DeferredBatch::add_item (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15355&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15355&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15353&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15353&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enum auto-derivation&lt;/strong&gt;: Auto-derive max_value for enum fields in protobuf codegen (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15469&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15469&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sub-message inlining&lt;/strong&gt;: New &lt;code dir=&quot;auto&quot;&gt;(inline_encode)&lt;/code&gt; proto option inlines small sub-messages directly into parent encoders, eliminating function pointer indirection. Applied to &lt;code dir=&quot;auto&quot;&gt;BluetoothLERawAdvertisement&lt;/code&gt; (encoded up to 12 times per BLE batch): &lt;strong&gt;40-55% faster&lt;/strong&gt; BLE advertisement encoding (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15599&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15599&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;speed_optimized&lt;/code&gt; hot paths&lt;/strong&gt;: New proto option emits &lt;code dir=&quot;auto&quot;&gt;__attribute__((optimize(&quot;O2&quot;)))&lt;/code&gt; on specific encode paths so they remain inlined even under firmware’s default &lt;code dir=&quot;auto&quot;&gt;-Os&lt;/code&gt; flag. Applied to &lt;code dir=&quot;auto&quot;&gt;SensorStateResponse&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;BluetoothLERawAdvertisementsResponse&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;SubscribeLogsResponse&lt;/code&gt;: BLE advertisement &lt;code dir=&quot;auto&quot;&gt;calculate_size&lt;/code&gt; is an additional &lt;strong&gt;41% faster&lt;/strong&gt;, with similar gains for sensor state and log encoding (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15691&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15691&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15698&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15698&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Core framework optimizations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scheduler&lt;/strong&gt;: Integer math for interval offset calculation, reschedules fired intervals directly into the heap, early-exit cancel path, and inlined fast-path checks (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14755&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14755&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15516&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15516&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14902&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14902&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14905&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14905&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Main loop inlined&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;Application::loop()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;calculate_looping_components_&lt;/code&gt; inlined to eliminate stack frames (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15041&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15041&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14944&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14944&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;std::bind eliminated&lt;/strong&gt;: Replaced across 20+ components with lambdas to fit within small-buffer optimization (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14961&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14961&lt;/a&gt; and related PRs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation call chain collapsed&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;Trigger::trigger()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;Automation::trigger()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;ActionList::play()&lt;/code&gt; forwarding chain is force-inlined, collapsing 3 stack frames into 1. Combined with ControllerRegistry dispatch inlining and &lt;code dir=&quot;auto&quot;&gt;call_loop_&lt;/code&gt; removal, a button→lambda automation went from &lt;strong&gt;16 stack frames to 10&lt;/strong&gt;, significantly reducing stack overflow risk on devices with deep automation chains (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15042&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15042&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15173&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15173&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14931&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14931&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IfAction compile-time optimization&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;HasElse&lt;/code&gt; parameter eliminates the else-branch check at compile time when no else block is configured (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15134&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15134&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logger&lt;/strong&gt;: Reduced per-message overhead by inlining hot path helpers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14851&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14851&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;errno caching&lt;/strong&gt;: Avoids duplicate &lt;code dir=&quot;auto&quot;&gt;__errno()&lt;/code&gt; calls across API, async_tcp, captive_portal, and web_server_idf (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14751&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14751&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loop elimination&lt;/strong&gt;: Many components were running their &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; every single main loop iteration just to check a condition or timestamp. These have been converted to event-driven patterns that only run when needed:
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt;: Loop completely disabled when no SSE clients are connected; most devices have zero browser clients 99%+ of the time (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15428&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15428&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;total_daily_energy&lt;/code&gt;: Replaced loop() with a single timeout that fires at midnight (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15432&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15432&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;CronTrigger&lt;/code&gt;: Replaced loop() with &lt;code dir=&quot;auto&quot;&gt;set_interval&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15433&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15433&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;preferences&lt;/code&gt;: Loop compiled out entirely when &lt;code dir=&quot;auto&quot;&gt;flash_write_interval&lt;/code&gt; is non-zero (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14943&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14943&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;GPIO expanders (PCF8574, PCA9554, MCP23xxx, PI4IOE5V6408): Loop disabled when all pins are outputs (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15455&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15455&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15460&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15460&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;sx127x&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;cc1101&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;sx126x&lt;/code&gt;: Use GPIO interrupt to wake the loop instead of polling, with loop disabled entirely when packet mode is inactive (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15627&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15627&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15606&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15606&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;hbridge&lt;/code&gt; light: Loop only runs when both cold and warm white channels are active and multiplexing is needed; disabled for single-channel or off states (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15615&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15615&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bluetooth Proxy&lt;/strong&gt;: BLE event handler dispatch devirtualized, eliminating virtual call overhead on every BLE advertisement and GATT event (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15310&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15310&lt;/a&gt;). BLE &lt;code dir=&quot;auto&quot;&gt;is_active&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;is_running&lt;/code&gt; inlined and STL bloat removed (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14875&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14875&lt;/a&gt;). Advertisement flushing replaced &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; (which ran ~7,400 times/60s just to check a timestamp) with &lt;code dir=&quot;auto&quot;&gt;set_interval(100ms)&lt;/code&gt; so the flush logic only runs when needed (~600 times/60s), eliminating ~6,800 wasted iterations per minute (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15347&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15347&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Devirtualization&lt;/strong&gt;: Preferences backend, PollingComponent::set_update_interval (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14825&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14825&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14938&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14938&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Light&lt;/strong&gt;: Reciprocal multiply in normalize_color, pass LightTraits to avoid redundant virtual calls (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15401&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15401&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15403&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15403&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CodSpeed runs on every pull request and push to &lt;code dir=&quot;auto&quot;&gt;dev&lt;/code&gt;, providing a continuous baseline that catches regressions before they ship. It was CodSpeed’s benchmark visualization that revealed &lt;code dir=&quot;auto&quot;&gt;vsnprintf&lt;/code&gt; was consuming 95%+ of sensor publish time, leading to the &lt;a href=&quot;#client-side-state-logging&quot;&gt;client-side state logging&lt;/a&gt; change that achieved a &lt;strong&gt;46x speedup&lt;/strong&gt; on the sensor publish path. Visit &lt;a href=&quot;https://codspeed.io/esphome/esphome&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;codspeed.io/esphome/esphome&lt;/a&gt; to explore the benchmark results. Thank you to &lt;a href=&quot;https://codspeed.io&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;CodSpeed&lt;/a&gt; for providing their service free to open source projects.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;memory-optimizations&quot;&gt;Memory Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Driven by the increased visibility from benchmarking and memory analysis tooling, this release includes significant RAM and flash savings across the framework.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Component allocations moved from heap to BSS&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15079&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15079&lt;/a&gt;): This is a major architectural change; all component instances (&lt;code dir=&quot;auto&quot;&gt;new_Pvariable&lt;/code&gt;) are now allocated via placement new into statically-sized BSS storage instead of individual heap allocations. Previously, every component, sensor, automation, and filter was a separate &lt;code dir=&quot;auto&quot;&gt;new&lt;/code&gt; call, fragmenting the heap over time. Now these allocations are packed into a single contiguous BSS region, freeing heap space for WiFi, BLE, and network buffers that genuinely need dynamic allocation. This eliminates hundreds of small heap allocations per device and significantly reduces heap fragmentation on long-running devices.&lt;/p&gt;
&lt;p&gt;ESPHome’s CI automatically runs a home-grown memory impact analysis on every pull request, showing contributors the exact flash and RAM impact of their changes before merging. Previously, component memory was invisible to this tooling because it was all allocated at runtime on the heap. Once the BSS change landed, every component’s memory became a statically-visible symbol that the CI could measure and attribute. The &lt;a href=&quot;https://esphome.io/guides/cli#analyze-memory-command&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;analyze-memory&lt;/code&gt;&lt;/a&gt; tool was extended to attribute placement new storage symbols back to their owning components (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15092&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15092&lt;/a&gt;), making it easy to spot which components still had room for improvement. This visibility drove the wave of targeted optimizations below.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core framework savings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Component base class&lt;/strong&gt;: Shrunk from 12 to 8 bytes per instance, saving ~200-400 bytes across typical configs (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15103&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CallbackManager&lt;/strong&gt;: Replaced &lt;code dir=&quot;auto&quot;&gt;std::function&lt;/code&gt; (16 bytes) with lightweight &lt;code dir=&quot;auto&quot;&gt;Callback&lt;/code&gt; (8 bytes) across all callback registrations. Small lambdas like &lt;code dir=&quot;auto&quot;&gt;[this]&lt;/code&gt; are now stored inline in the function pointer context with zero heap allocation, covering 96% of all callback registrations. Measured &lt;strong&gt;+488 bytes free heap&lt;/strong&gt; on an ESP8266 config with MQTT + web_server + many entities (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14853&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14853&lt;/a&gt;). A follow-up replaced &lt;code dir=&quot;auto&quot;&gt;std::vector&lt;/code&gt; with a trivial-copy container, eliminating per-signature template instantiations of vector reallocation machinery and saving &lt;strong&gt;996 bytes of flash&lt;/strong&gt; on ESP8266 plus &lt;strong&gt;4 bytes of RAM per CallbackManager instance&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15272&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15272&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trigger trampolines eliminated across 23 components&lt;/strong&gt;: Previously, every &lt;code dir=&quot;auto&quot;&gt;on_press&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_value&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_state&lt;/code&gt;, etc. automation instantiated a separate Trigger object just to forward a callback, a 4+ byte heap-allocated object that existed solely to hold a pointer. A new &lt;code dir=&quot;auto&quot;&gt;build_callback_automation()&lt;/code&gt; pattern collapses the trigger into a pointer-sized forwarder struct stored inline in the callback manager, eliminating the separate allocation entirely. The initial PR (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15174&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15174&lt;/a&gt;) migrated the core entity types (button, sensor, binary_sensor, switch, text_sensor, number, event) saving 88-208 bytes RAM, then &lt;strong&gt;22 follow-up PRs&lt;/strong&gt; migrated alarm_control_panel, lock, media_player, ld2450, rtttl, online_image, rotary_encoder, dfplayer, hlk_fm22x, pn532, pn7150/pn7160, sim800l, fingerprint_grow, ltr_als_ps, ltr501, nextion, ezo, haier, modbus_controller, rf_bridge, factory_reset, sml, and safe_mode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TemplatableValue → TemplatableFn&lt;/strong&gt;: The function-pointer pattern was first proven on &lt;code dir=&quot;auto&quot;&gt;LightControlAction&lt;/code&gt;, shrinking each instance from 128 to 72 bytes (44% reduction, saving 616 bytes RAM on an ESP8266 light config with 11 actions) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15132&lt;/a&gt;). This was then generalized codebase-wide: ~340 &lt;code dir=&quot;auto&quot;&gt;TEMPLATABLE_VALUE&lt;/code&gt; fields automatically dropped from 8 to 4 bytes each by storing function pointers instead of tagged unions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15545&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15545&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ActionList&lt;/strong&gt;: Removed &lt;code dir=&quot;auto&quot;&gt;actions_end_&lt;/code&gt; pointer to save RAM per automation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15283&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15283&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Entity and component savings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Binary sensor&lt;/strong&gt;: Removed redundant &lt;code dir=&quot;auto&quot;&gt;optional&amp;#x3C;bool&gt;&lt;/code&gt; state, saving 8 bytes per instance (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15095&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15095&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Text sensor&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;raw_callback_&lt;/code&gt; gated behind &lt;code dir=&quot;auto&quot;&gt;USE_TEXT_SENSOR_FILTER&lt;/code&gt;, saving 4 bytes per instance when unused (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15097&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15097&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Light&lt;/strong&gt;: Reordered LightState fields to eliminate padding (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15112&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15112&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPIO binary sensor&lt;/strong&gt;: Packed fields and removed redundant &lt;code dir=&quot;auto&quot;&gt;last_state_&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15113&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15113&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPIO switch&lt;/strong&gt;: Compiled out interlock fields when unused (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15111&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15111&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Climate/Fan&lt;/strong&gt;: Custom mode vectors stored on entity directly, eliminating heap allocation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15206&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15206&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15209&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15209&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebServerBase&lt;/strong&gt;: Reduced by 4 bytes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15251&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15251&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/runtime_stats&quot;&gt;Runtime stats&lt;/a&gt;&lt;/strong&gt;: Stored inline on Component, eliminating &lt;code dir=&quot;auto&quot;&gt;std::map&lt;/code&gt; lookup (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15345&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15345&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Heap allocation elimination:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sensor filters&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;OrFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;CalibrateLinearFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;CalibratePolynomialFilter&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ValueList&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;FilterOut&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ThrottleWithPriority&lt;/code&gt; migrated to &lt;code dir=&quot;auto&quot;&gt;std::array&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15262&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15262&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15263&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15263&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15264&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15264&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15265&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15265&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Text sensor filters&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;SubstituteFilter&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;MapFilter&lt;/code&gt; migrated to &lt;code dir=&quot;auto&quot;&gt;std::array&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15266&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15266&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15269&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15269&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation conditions&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;And&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Or&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Xor&lt;/code&gt; conditions migrated to &lt;code dir=&quot;auto&quot;&gt;std::array&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15282&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15282&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PID&lt;/strong&gt;: Replaced &lt;code dir=&quot;auto&quot;&gt;std::deque&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;FixedRingBuffer&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14733&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14733&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensor sliding window&lt;/strong&gt;: Replaced with &lt;code dir=&quot;auto&quot;&gt;FixedRingBuffer&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14736&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14736&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ESP8266 RAM savings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API dump strings&lt;/strong&gt;: Moved to PROGMEM (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14982&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14982&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logger&lt;/strong&gt;: Log level lookup tables and task log buffer moved to PROGMEM/BSS (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15003&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15003&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15153&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15153&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;config-bundle-for-remote-compilation&quot;&gt;Config Bundle for Remote Compilation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;code dir=&quot;auto&quot;&gt;esphome bundle&lt;/code&gt; CLI command packages a YAML config and all its local dependencies (fonts, images, certificates, local external_components, secrets) into a self-contained &lt;code dir=&quot;auto&quot;&gt;.esphomebundle.tar.gz&lt;/code&gt; archive (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13791&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13791&lt;/a&gt;). This is the foundation for &lt;strong&gt;remote compilation support&lt;/strong&gt;, enabling devices like the Home Assistant Green to offload compilation to a remote build server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automatic dependency discovery&lt;/strong&gt; - Finds all referenced files (YAML includes, fonts, images, animations, certificates, C++ includes, web assets)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secrets filtering&lt;/strong&gt; - Only includes secrets actually referenced by bundled YAML files&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deterministic archives&lt;/strong&gt; - Sorted entries and zeroed timestamps for reproducibility&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incremental builds&lt;/strong&gt; - Preserves PlatformIO build caches across re-extractions&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bundle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my_device.yaml&lt;/span&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;# Create bundle&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bundle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my_device.yaml&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--list-only&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Preview files&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my_device.esphomebundle.tar.gz&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Compile from bundle&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;lvgl-v9-upgrade&quot;&gt;LVGL v9 Upgrade&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Led by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; with 27 PRs, ESPHome’s LVGL integration has been upgraded from v8 to &lt;strong&gt;LVGL v9.5.0&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12312&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12312&lt;/a&gt;). This is a major library migration that brings a new rendering pipeline, improved performance, and new widget capabilities. Existing configurations should compile and run, though some properties are deprecated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key changes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Native rotation with hardware acceleration&lt;/strong&gt; - Rotation is now handled directly by &lt;a href=&quot;https://esphome.io/components/lvgl&quot;&gt;LVGL&lt;/a&gt; instead of the display driver, with runtime rotation changes via &lt;code dir=&quot;auto&quot;&gt;lvgl.display.set_rotation&lt;/code&gt; and automatic use of hardware rotation when available.
On ESP32-P4, rotation uses the PPA (Pixel Processing Accelerator) for zero-CPU-cost transforms (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14955&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14955&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15453&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15453&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic touchscreen rotation&lt;/strong&gt; - Touch input is automatically rotated to match display orientation, eliminating the need for manual coordinate transforms in most cases.
Users will need to move their &lt;code dir=&quot;auto&quot;&gt;rotation&lt;/code&gt; config from the display component to the &lt;code dir=&quot;auto&quot;&gt;lvgl:&lt;/code&gt; block, and remove or adjust the &lt;code dir=&quot;auto&quot;&gt;transform:&lt;/code&gt; block in the touchscreen component.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in dark theme&lt;/strong&gt; - A single &lt;code dir=&quot;auto&quot;&gt;dark_mode: true&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;theme:&lt;/code&gt; enables LVGL’s native dark default theme, replacing the tedious process of manually replicating dark theme properties (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15389&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15389&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;All LVGL 9 events&lt;/strong&gt; - Complete mapping of LVGL 9 events to ESPHome automation triggers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15362&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15362&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drop shadow support&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;bitmap_mask_src&lt;/code&gt; style property and A8 image format for drop shadow effects (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15334&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15334&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-sensors-and-hardware-support&quot;&gt;New Sensors and Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release adds support for several new sensors and hardware platforms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/spa06&quot;&gt;SPA06-003&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/danielkent-net&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@danielkent-net&lt;/a&gt; - Goermicro digital pressure and temperature sensor with both I2C and SPI interfaces, available from Adafruit and Seeed Grove (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14521&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14521&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14522&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14522&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14523&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14523&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hdc2080&quot;&gt;HDC2080&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/G-Pereira&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@G-Pereira&lt;/a&gt; - Texas Instruments temperature and humidity sensor (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9331&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#9331&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://esphome.io/components/sensor/emontx&quot;&gt;emonTx&lt;/a&gt;&lt;/strong&gt; by &lt;a href=&quot;https://github.com/FredM67&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@FredM67&lt;/a&gt; - OpenEnergyMonitor emonTx/emonPi energy monitoring via UART serial bridge, with JSON triggers and command actions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9027&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#9027&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BMP581 SPI support&lt;/strong&gt; by &lt;a href=&quot;https://github.com/danielkent-net&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@danielkent-net&lt;/a&gt; - The BMP581 pressure sensor now supports SPI in addition to I2C (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13124&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13124&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BMP585 support&lt;/strong&gt; by &lt;a href=&quot;https://github.com/nytaros&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@nytaros&lt;/a&gt; - Adds the newer BMP585 ASIC ID to the BMP581 component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15277&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15277&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32-C61 PSRAM&lt;/strong&gt; - Quad mode PSRAM support at 40MHz and 80MHz (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14795&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14795&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internal temperature&lt;/strong&gt; for nRF52 Zephyr by &lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15297&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15297&lt;/a&gt;) and LN882H by &lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15370&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15370&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;other-notable-features&quot;&gt;Other Notable Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Number-to-sensor and text-to-text_sensor bridges&lt;/strong&gt; - New read-only sensor/text_sensor views of number/text components for use in automations and displays (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15125&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15125&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15090&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15090&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 Hosted SPI transport&lt;/strong&gt; - SPI transport and 1-bit SDIO bus width support for the &lt;code dir=&quot;auto&quot;&gt;esp32_hosted&lt;/code&gt; WiFi offloading component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15551&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15551&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nextion custom protocol triggers&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;on_custom_switch&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_custom_sensor&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_custom_text_sensor&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_custom_binary_sensor&lt;/code&gt; triggers for event-driven Nextion workflows without entities (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13248&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13248&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MQTT alarm panel JSON payloads&lt;/strong&gt; - Alarm control panel command topic now accepts JSON payloads with PIN codes, e.g. &lt;code dir=&quot;auto&quot;&gt;{&quot;state&quot;: &quot;DISARM&quot;, &quot;code&quot;: &quot;1234&quot;}&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14731&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14731&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media player enqueue action&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;media_player.enqueue&lt;/code&gt; action for queueing media URLs from automations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14775&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14775&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MIPI RGB optional sync pins&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;hsync_pin&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;vsync_pin&lt;/code&gt; now optional for displays like the BigTreeTech PandaTouch (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14870&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14870&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brennenstuhl remote switches&lt;/strong&gt; - New 433MHz rolling code protocol for Brennenstuhl comfort-line switches (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9407&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#9407&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DSMR thermal MBUS id&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;thermal_mbus_id&lt;/code&gt; option for Warmtelink heat meters (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7519&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#7519&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VBus DeltaSol CS4&lt;/strong&gt; - Support for Citrin Solar 1.3 controller (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12477&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12477&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TM1637 buffer manipulation&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;set_buffer&lt;/code&gt; method for raw segment writes and custom glyphs (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13686&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13686&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HUB75 scan wiring&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;SCAN_1_8_32PX_FULL&lt;/code&gt; wiring option (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15130&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15130&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;*/N&lt;/code&gt; cron syntax&lt;/strong&gt; - Time-based automations now support &lt;code dir=&quot;auto&quot;&gt;*/5&lt;/code&gt; style step expressions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15434&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15434&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;microFLAC audio decoding&lt;/strong&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; - New FLAC decoder is &lt;strong&gt;9% faster&lt;/strong&gt; on ESP32-S3 with CRC validation re-enabled, plus true streaming support that eliminates unnecessary memory copies (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15372&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15372&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;mitsubishi-cn105-climate-component&quot;&gt;Mitsubishi CN105 Climate Component&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Built by &lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt; across 5 PRs, the new &lt;a href=&quot;https://esphome.io/components/climate/mitsubishi_cn105&quot;&gt;mitsubishi_cn105&lt;/a&gt; component brings native support for controlling Mitsubishi A/C units through the CN105 connector, one of the most requested climate integrations in ESPHome. The component implements the same CN105 protocol used by the popular SwiCago HeatPump project, ensuring compatibility with the same &lt;a href=&quot;https://github.com/SwiCago/HeatPump/issues/13&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;range of devices&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/15315&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15315&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15358&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15358&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15437&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15462&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15462&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15483&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full climate control&lt;/strong&gt; - Power, mode, target temperature, and fan speed can be controlled directly from Home Assistant&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-blocking protocol driver&lt;/strong&gt; - Custom UART parser designed for performance and reliability&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smart temperature polling&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;current_temperature_min_interval&lt;/code&gt; option rate-limits room temperature reads to prevent rapid oscillations near measurement boundaries while keeping a fast &lt;code dir=&quot;auto&quot;&gt;update_interval&lt;/code&gt; for responsive control&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Broad platform support&lt;/strong&gt; - Works on ESP32, ESP32 IDF, ESP8266, and RP2040/RP2350&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;climate&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mitsubishi_cn105&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Air Condition&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;uart_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ac_uart&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;update_interval&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;current_temperature_min_interval&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;60s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;codebase-correctness-sweep&quot;&gt;Codebase Correctness Sweep&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Continuing the &lt;a href=&quot;https://esphome.io/blog/2026/03/18/esphome-2026-3/#codebase-correctness-sweep&quot;&gt;correctness sweep started in 2026.3.0&lt;/a&gt;, &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; contributed another &lt;strong&gt;99 bug fix and validation PRs&lt;/strong&gt; in this release, addressing missing &lt;code dir=&quot;auto&quot;&gt;state_class&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;device_class&lt;/code&gt; on sensor schemas, incorrect config validation (wrong types, missing range checks, broken &lt;code dir=&quot;auto&quot;&gt;ensure_list&lt;/code&gt; usage), dead code removal, format specifier warnings, and codegen type mismatches across 100+ components. This sustained effort has significantly improved the reliability and correctness of the ESPHome codebase.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;thank-you-contributors&quot;&gt;Thank You, Contributors&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;This release includes 507 pull requests from over 40 contributors. A huge thank you to everyone who made 2026.4.0 possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; - 121 PRs including a correctness sweep across 100+ components, ESP-IDF 6.0 compatibility across dozens of components, and the ESP32 CPU frequency default change&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - 27 PRs including the LVGL v9.5.0 migration, native rotation support, and display component improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt; - 14 PRs including Nextion custom protocol triggers, performance optimizations, and code quality improvements across the Nextion component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jpeletier&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jpeletier&lt;/a&gt; - 10 PRs including the substitution system redesign for 18x faster config loading and &lt;code dir=&quot;auto&quot;&gt;!include&lt;/code&gt; path substitution support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; - 10 PRs including signed OTA verification without hardware secure boot, IR receiver frequency metadata, and sensor code cleanups&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; - 7 PRs including the media player enqueue action, microFLAC decoding, and audio pipeline improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/danielkent-net&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@danielkent-net&lt;/a&gt; - 5 PRs including the new SPA06-003 pressure/temperature sensor (I2C and SPI) and BMP581 SPI support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt; - 5 PRs building the new Mitsubishi CN105 climate component from scaffold to full read/write control&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; - 4 PRs including modbus helper refactoring and integration tests&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt; - 4 PRs including CI improvements and unbounded percentage validators&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/diorcety&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@diorcety&lt;/a&gt; - 4 PRs including git subpath support and compiler compatibility fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/FredM67&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@FredM67&lt;/a&gt; - 2 PRs including the new emonTx energy monitoring component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; - 2 PRs including debug peripherals status and Zigbee logging improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/P4uLT&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@P4uLT&lt;/a&gt; - 2 PRs including PID FixedRingBuffer optimization&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Kamilcuk&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Kamilcuk&lt;/a&gt; - 2 PRs including placement new allocation for Pvariables&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/luar123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@luar123&lt;/a&gt; - custom ESP32 partition tables and partition table refactoring&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/G-Pereira&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@G-Pereira&lt;/a&gt; - the new HDC2080 temperature and humidity sensor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also thank you to &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;, &lt;a href=&quot;https://github.com/thomwiggers&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@thomwiggers&lt;/a&gt;, &lt;a href=&quot;https://github.com/aanban&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@aanban&lt;/a&gt;, &lt;a href=&quot;https://github.com/rtyle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rtyle&lt;/a&gt;, &lt;a href=&quot;https://github.com/Szewcson&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Szewcson&lt;/a&gt;, &lt;a href=&quot;https://github.com/Pernotto&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Pernotto&lt;/a&gt;, &lt;a href=&quot;https://github.com/mike1703&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mike1703&lt;/a&gt;, &lt;a href=&quot;https://github.com/tuct&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tuct&lt;/a&gt;, &lt;a href=&quot;https://github.com/CFlix&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@CFlix&lt;/a&gt;, &lt;a href=&quot;https://github.com/heythisisnate&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@heythisisnate&lt;/a&gt;, &lt;a href=&quot;https://github.com/warthog618&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@warthog618&lt;/a&gt;, &lt;a href=&quot;https://github.com/FWeinb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@FWeinb&lt;/a&gt;, &lt;a href=&quot;https://github.com/droscy&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@droscy&lt;/a&gt;, &lt;a href=&quot;https://github.com/intcreator&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@intcreator&lt;/a&gt;, &lt;a href=&quot;https://github.com/szupi-ipuzs&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@szupi-ipuzs&lt;/a&gt;, &lt;a href=&quot;https://github.com/fblaese&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@fblaese&lt;/a&gt;, &lt;a href=&quot;https://github.com/glmnet&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@glmnet&lt;/a&gt;, &lt;a href=&quot;https://github.com/nytaros&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@nytaros&lt;/a&gt;, &lt;a href=&quot;https://github.com/Ardumine&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Ardumine&lt;/a&gt;, &lt;a href=&quot;https://github.com/rguca&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rguca&lt;/a&gt;, &lt;a href=&quot;https://github.com/Bl00d-B0b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Bl00d-B0b&lt;/a&gt;, &lt;a href=&quot;https://github.com/RAR&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@RAR&lt;/a&gt;, &lt;a href=&quot;https://github.com/Passific&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Passific&lt;/a&gt;, and &lt;a href=&quot;https://github.com/Tomer27cz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Tomer27cz&lt;/a&gt; for their contributions, and to everyone who reported issues, tested pre-releases, and helped in the community.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;platform-changes&quot;&gt;Platform Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP32 CPU frequency&lt;/strong&gt;: Default CPU frequency changed to maximum supported per variant (ESP32/S2/S3/C5: 160MHz to 240MHz). This improves performance ~33% but increases power consumption. Battery-powered devices should add &lt;code dir=&quot;auto&quot;&gt;cpu_frequency: 160MHZ&lt;/code&gt; to their config. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15143&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15143&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP32 partition table&lt;/strong&gt;: Partition layout changed for both Arduino and IDF frameworks. NVS moved to end of flash with increased size (20KB to 384KB on Arduino). Existing devices will get the new partition table on next OTA update. NVS data is preserved since the library finds it by name, not position. &lt;a href=&quot;https://github.com/esphome/esphome/pull/7682&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#7682&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP8266 RTC preferences&lt;/strong&gt;: RTC preferences capacity reduced from 96 to 78 words to accommodate the new crash handler. Overflow goes to flash. Very unlikely to affect real configs. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15465&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15465&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LVGL rotation&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;rotation&lt;/code&gt; option must now be configured under &lt;code dir=&quot;auto&quot;&gt;lvgl:&lt;/code&gt; instead of the display component. LVGL now handles rotation for the display and touchscreen directly, with support for runtime rotation changes via &lt;code dir=&quot;auto&quot;&gt;lvgl.display.set_rotation&lt;/code&gt;.
Users must move their &lt;code dir=&quot;auto&quot;&gt;rotation&lt;/code&gt; setting from the display config to the &lt;code dir=&quot;auto&quot;&gt;lvgl:&lt;/code&gt; block. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14955&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14955&lt;/a&gt; and remove or adjust the &lt;code dir=&quot;auto&quot;&gt;transform:&lt;/code&gt; block in their touchscreen config if they have one.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;I2S Audio&lt;/strong&gt;: The legacy I2S driver (&lt;code dir=&quot;auto&quot;&gt;use_legacy&lt;/code&gt; option) has been removed. The new I2S driver is always used. The &lt;code dir=&quot;auto&quot;&gt;i2s_audio&lt;/code&gt; media player sub-component has been removed entirely; users should migrate to the &lt;a href=&quot;https://esphome.io/components/media_player/speaker&quot;&gt;speaker media player&lt;/a&gt; component. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14932&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14932&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Binary Sensor multi_click&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;on_multi_click&lt;/code&gt; timing sequences are now limited to 255 entries (previously unlimited). No real config would approach this limit. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15267&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15267&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Binary Sensor autorepeat&lt;/strong&gt;: Autorepeat timing lists are now limited to 254 entries (previously unlimited). No real config would approach this limit. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15268&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15268&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;configuration-system-changes&quot;&gt;Configuration System Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Substitutions&lt;/strong&gt;: When two YAML keys in the same dict resolve to the same substituted name, the later-appearing key’s value now takes precedence (“last writer wins”). Previously, the existing resolved value took precedence on dict merges. This only affects the edge case of duplicate substituted keys. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14918&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14918&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;undocumented-api-changes&quot;&gt;Undocumented API Changes&lt;/h3&gt;&lt;/div&gt;

&lt;p&gt;Several internal C++ APIs have changed in this release. While these are not part of the public API, they may affect users who write lambdas or maintain external components.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;component-and-preferences-infrastructure&quot;&gt;Component and Preferences Infrastructure&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Component&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;set_component_source(const LogString *)&lt;/code&gt; removed and replaced with protected &lt;code dir=&quot;auto&quot;&gt;set_component_source_(uint8_t)&lt;/code&gt;. The &lt;code dir=&quot;auto&quot;&gt;warn_if_blocking_over_&lt;/code&gt; field changed from &lt;code dir=&quot;auto&quot;&gt;uint16_t&lt;/code&gt; (milliseconds) to &lt;code dir=&quot;auto&quot;&gt;uint8_t&lt;/code&gt; (centiseconds). Component base class shrunk from 12 to 8 bytes. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15103&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Preferences&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;ESPPreferenceBackend&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ESPPreferences&lt;/code&gt; abstract base classes removed. They are now type aliases to concrete platform-specific &lt;code dir=&quot;auto&quot;&gt;final&lt;/code&gt; classes. All existing code using &lt;code dir=&quot;auto&quot;&gt;global_preferences&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;ESPPreferenceObject&lt;/code&gt; continues to work unchanged. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14825&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14825&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;automation-trigger-changes&quot;&gt;Automation Trigger Changes&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Trigger classes removed&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;ButtonPressTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SensorStateTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SensorRawStateTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;PressTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ReleaseTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;StateTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;StateChangeTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SwitchStateTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SwitchTurnOnTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SwitchTurnOffTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;TextSensorStateTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;TextSensorStateRawTrigger&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;NumberStateTrigger&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;EventTrigger&lt;/code&gt; are no longer instantiated. Lambdas using &lt;code dir=&quot;auto&quot;&gt;trigger_id&lt;/code&gt; to access these objects will break. Use &lt;code dir=&quot;auto&quot;&gt;Script&lt;/code&gt; for action control instead. The &lt;code dir=&quot;auto&quot;&gt;Automation::trigger_&lt;/code&gt; protected field was also removed. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15174&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15174&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;templatablevalue-changes&quot;&gt;TemplatableValue Changes&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TemplatableValue for non-string types&lt;/strong&gt;: No longer accepts stateful lambdas (lambdas with captures). No external usage was found. If you need a stateful callable, use &lt;code dir=&quot;auto&quot;&gt;std::function&amp;#x3C;T(X...)&gt;&lt;/code&gt; directly. The &lt;code dir=&quot;auto&quot;&gt;TEMPLATABLE_VALUE&lt;/code&gt; macro now uses &lt;code dir=&quot;auto&quot;&gt;TemplatableFn&lt;/code&gt; (4 bytes) for trivially copyable types. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15545&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15545&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;component-specific-changes&quot;&gt;Component-Specific Changes&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Nextion&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_wave_chan_id()&lt;/code&gt; deprecated in favor of &lt;code dir=&quot;auto&quot;&gt;get_wave_channel_id()&lt;/code&gt; (removal in 2026.10.0). Getter methods now return by &lt;code dir=&quot;auto&quot;&gt;const&lt;/code&gt; reference instead of by value. &lt;code dir=&quot;auto&quot;&gt;get_queue_type_string()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;. Waveform-related methods are now gated behind &lt;code dir=&quot;auto&quot;&gt;USE_NEXTION_WAVEFORM&lt;/code&gt; and may not be available if no waveform sensors are configured. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15204&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15204&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15273&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15273&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ATM90E32&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_phase_angle_()&lt;/code&gt; return type changed from &lt;code dir=&quot;auto&quot;&gt;uint16_t&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;float&lt;/code&gt; (fixes precision loss). &lt;code dir=&quot;auto&quot;&gt;last_periodic_millis&lt;/code&gt; member removed (was never used). &lt;a href=&quot;https://github.com/esphome/esphome/pull/15238&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15238&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AS5600&lt;/strong&gt;: Dead &lt;code dir=&quot;auto&quot;&gt;angle_sensor_&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;raw_angle_sensor_&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;position_sensor_&lt;/code&gt; members and their setters removed (were never wired to config schema). &lt;a href=&quot;https://github.com/esphome/esphome/pull/15254&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15254&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SEN5x&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;voc_baseline&lt;/code&gt; config option removed (was never wired to C++). Use &lt;code dir=&quot;auto&quot;&gt;store_baseline: true&lt;/code&gt; instead. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15391&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15391&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Graph&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;legend&lt;/code&gt; config no longer accepts a list (only the first element was ever used). Single-value configs continue to work. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15522&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15522&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Haier&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;control_method&lt;/code&gt; config no longer accepts a list. Single-value configs continue to work. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15523&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15523&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;RP2040 PIO LED Strip&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;CUSTOM&lt;/code&gt; removed from &lt;code dir=&quot;auto&quot;&gt;chipset&lt;/code&gt; enum (it crashed at compile time). Use explicit timing parameters (&lt;code dir=&quot;auto&quot;&gt;bit0_high&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;bit0_low&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;bit1_high&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;bit1_low&lt;/code&gt;) instead. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15537&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15537&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CallbackManager&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;std::function&lt;/code&gt; replaced with lightweight &lt;code dir=&quot;auto&quot;&gt;Callback&lt;/code&gt; type. Existing code continues to work but external components should migrate callback registration methods from &lt;code dir=&quot;auto&quot;&gt;std::function&lt;/code&gt; parameters to templates for optimal performance (non-template methods fall back to a heap-allocation path). &lt;a href=&quot;https://github.com/esphome/esphome/pull/14853&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14853&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PollingComponent&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;set_update_interval()&lt;/code&gt; is now non-virtual. Subclasses overriding this method should use alternative patterns. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14938&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14938&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART FlushResult&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;FlushResult&lt;/code&gt; renamed to &lt;code dir=&quot;auto&quot;&gt;UARTFlushResult&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;UART_FLUSH_RESULT_&lt;/code&gt; prefix for enum values. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15101&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15101&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensor raw_state&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;.raw_state&lt;/code&gt; is deprecated. &lt;code dir=&quot;auto&quot;&gt;raw_callback_&lt;/code&gt; is now gated behind &lt;code dir=&quot;auto&quot;&gt;USE_SENSOR_FILTER&lt;/code&gt;, saving RAM on every sensor instance when no filters are configured. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15094&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15094&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trigger trampolines eliminated&lt;/strong&gt;: Trigger objects for common entity automations (button, sensor, binary_sensor, switch, text_sensor, number, event) are no longer instantiated. &lt;code dir=&quot;auto&quot;&gt;build_automation()&lt;/code&gt; and Trigger subclasses remain available. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15174&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15174&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TemplatableFn&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;TEMPLATABLE_VALUE&lt;/code&gt; macro now uses 4-byte &lt;code dir=&quot;auto&quot;&gt;TemplatableFn&lt;/code&gt; for trivially copyable types. External components calling macro-generated setters with raw C++ constants instead of going through &lt;code dir=&quot;auto&quot;&gt;cg.templatable()&lt;/code&gt; will fail to compile. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15545&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15545&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Climate/Fan custom modes&lt;/strong&gt;: Custom mode/preset vectors are now stored on the entity instead of heap-allocated. Constructors for climate and fan traits have changed. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15206&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15206&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15209&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15209&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trigger migrations to callback automation&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;alarm_control_panel&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;lock&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;media_player&lt;/code&gt; triggers now use callback automation pattern. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15198&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15198&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15199&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15199&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/15200&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15200&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BLE event dispatch&lt;/strong&gt;: BLE event handler dispatch is devirtualized. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15310&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15310&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;wake_loop&lt;/strong&gt;: Moved from socket component into core. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15446&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15446&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preferences devirtualized&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;ESPPreferenceBackend&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ESPPreferences&lt;/code&gt; are now type aliases to concrete platform-specific classes (no virtual base). &lt;a href=&quot;https://github.com/esphome/esphome/pull/14825&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14825&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component shrunk from 12 to 8 bytes&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;set_component_source(const LogString *)&lt;/code&gt; removed and replaced with &lt;code dir=&quot;auto&quot;&gt;set_component_source_(uint8_t)&lt;/code&gt; (protected). &lt;a href=&quot;https://github.com/esphome/esphome/pull/15103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15103&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AS5600&lt;/strong&gt;: Dead &lt;code dir=&quot;auto&quot;&gt;angle&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;raw_angle&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;position&lt;/code&gt; sensor code removed. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15254&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15254&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus helpers&lt;/strong&gt;: Shared helper functions refactored across modbus components. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15291&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#15291&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14172&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14172&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the &lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-4-1---april-20&quot;&gt;Release 2026.4.1 - April 20&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[core] Fix app_state_ status bits clobbered for non-looping components &lt;a href=&quot;https://github.com/esphome/esphome/pull/15658&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15658&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Inline feed_wdt hot path with out-of-line slow path &lt;a href=&quot;https://github.com/esphome/esphome/pull/15656&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15656&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[st7789v] Fix swapped offset_width/offset_height in model presets &lt;a href=&quot;https://github.com/esphome/esphome/pull/15755&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15755&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sx126x][sx127x] Fix frequency precision loss from float32 codegen &lt;a href=&quot;https://github.com/esphome/esphome/pull/15753&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15753&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump aioesphomeapi from 44.15.0 to 44.16.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/15757&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15757&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Clean the build if lv_conf.h changes &lt;a href=&quot;https://github.com/esphome/esphome/pull/15777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15777&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mitsubishi_cn105] use HEAT_COOL mode to enable temperature slider &lt;a href=&quot;https://github.com/esphome/esphome/pull/15748&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15748&lt;/a&gt; by &lt;a href=&quot;https://github.com/crnjan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@crnjan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Diagnose missing cg.templatable in codegen for TEMPLATABLE_VALUE fields &lt;a href=&quot;https://github.com/esphome/esphome/pull/15758&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15758&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[time] Fix RTC is_valid() rejecting valid times after day_of_year cleanup &lt;a href=&quot;https://github.com/esphome/esphome/pull/15763&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15763&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[qmc5883l] Move per-update log line from DEBUG to VERBOSE &lt;a href=&quot;https://github.com/esphome/esphome/pull/15781&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15781&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bundle] Force-resolve nested IncludeFile during file discovery &lt;a href=&quot;https://github.com/esphome/esphome/pull/15762&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15762&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ili9xxx] Guard against null buffer in display_() when allocation fails &lt;a href=&quot;https://github.com/esphome/esphome/pull/15786&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15786&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Accept unquoted minimum_chip_revision values &lt;a href=&quot;https://github.com/esphome/esphome/pull/15785&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15785&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Guard lv_image_set_src wrapper with LV_USE_IMAGE &lt;a href=&quot;https://github.com/esphome/esphome/pull/15789&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15789&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] Drawing fixes for native display &lt;a href=&quot;https://github.com/esphome/esphome/pull/15802&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15802&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[image] Fix byte order handling &lt;a href=&quot;https://github.com/esphome/esphome/pull/15800&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15800&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] coerce set_interval(0) / update_interval: 0ms to 1ms &lt;a href=&quot;https://github.com/esphome/esphome/pull/15799&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15799&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ethernet] Fix SPI3_HOST default breaking compile on variants without SPI3 &lt;a href=&quot;https://github.com/esphome/esphome/pull/15809&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15809&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix DelayAction compile error with non-const reference args &lt;a href=&quot;https://github.com/esphome/esphome/pull/15814&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15814&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Downgrade unneeded &lt;code dir=&quot;auto&quot;&gt;ignore_pin_validation_error&lt;/code&gt; to a warning &lt;a href=&quot;https://github.com/esphome/esphome/pull/15811&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15811&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[runtime_image] Fix RGB order &lt;a href=&quot;https://github.com/esphome/esphome/pull/15813&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15813&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix crash with snow on rotated display &lt;a href=&quot;https://github.com/esphome/esphome/pull/15822&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15822&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Feed WDT unconditionally in main loop to fix empty-config panic &lt;a href=&quot;https://github.com/esphome/esphome/pull/15830&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15830&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump aioesphomeapi from 44.16.0 to 44.16.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/15836&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15836&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Default PollingComponent() to 1ms when codegen is bypassed &lt;a href=&quot;https://github.com/esphome/esphome/pull/15831&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15831&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[substitutions] Fix &lt;code dir=&quot;auto&quot;&gt;substitutions: !include file.yaml&lt;/code&gt; regression &lt;a href=&quot;https://github.com/esphome/esphome/pull/15850&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15850&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[packages] Improve error messages with include stack and fix missing path propagation &lt;a href=&quot;https://github.com/esphome/esphome/pull/15844&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15844&lt;/a&gt; by &lt;a href=&quot;https://github.com/jpeletier&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jpeletier&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-4-2---april-23&quot;&gt;Release 2026.4.2 - April 23&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[lvgl] Fix format of hello world page &lt;a href=&quot;https://github.com/esphome/esphome/pull/15868&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15868&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix overloads for setting images on styles &lt;a href=&quot;https://github.com/esphome/esphome/pull/15864&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15864&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix update of textarea attached to keyboard &lt;a href=&quot;https://github.com/esphome/esphome/pull/15866&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15866&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[image] Fix rodata bloat for multi-frame RGB565+alpha animations &lt;a href=&quot;https://github.com/esphome/esphome/pull/15873&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15873&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix Pvariable placement new losing subclass identity &lt;a href=&quot;https://github.com/esphome/esphome/pull/15881&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15881&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2412] Fix null deref in set_basic_config when entities unconfigured &lt;a href=&quot;https://github.com/esphome/esphome/pull/15893&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15893&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Add Secure Boot V1 ECDSA signing scheme for pre-rev-3.0 ESP32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/15882&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15882&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; (new-feature)&lt;/li&gt;
&lt;li&gt;[io_expanders] Self-heal interrupt-driven expanders when INT stays asserted across the read &lt;a href=&quot;https://github.com/esphome/esphome/pull/15923&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15923&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[usb_uart] Derive TX output chunk count from &lt;code dir=&quot;auto&quot;&gt;buffer_size&lt;/code&gt; config &lt;a href=&quot;https://github.com/esphome/esphome/pull/15909&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15909&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-4-3---april-28&quot;&gt;Release 2026.4.3 - April 28&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[lvgl] Triggers on tabview tabs fix &lt;a href=&quot;https://github.com/esphome/esphome/pull/15935&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15935&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[time] Handle Windows EINVAL when validating POSIX TZ strings &lt;a href=&quot;https://github.com/esphome/esphome/pull/15934&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15934&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[deep_sleep] Fix sleep_duration codegen type to uint32_t &lt;a href=&quot;https://github.com/esphome/esphome/pull/15965&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15965&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix stale wifi.connected after state transition &lt;a href=&quot;https://github.com/esphome/esphome/pull/15966&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15966&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rotary_encoder][at581x] Fix templatable int field types &lt;a href=&quot;https://github.com/esphome/esphome/pull/16015&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16015&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32][wifi] Fix bootloop and WiFi connection issue if nvs partition is missing or has non-default label &lt;a href=&quot;https://github.com/esphome/esphome/pull/16025&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16025&lt;/a&gt; by &lt;a href=&quot;https://github.com/Mat931&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Mat931&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[nextion] Unify TFT upload ack timeout to 5000ms &lt;a href=&quot;https://github.com/esphome/esphome/pull/15960&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15960&lt;/a&gt; by &lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_touch] Feed wdt &lt;a href=&quot;https://github.com/esphome/esphome/pull/16066&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16066&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[image] Fix RGB565+alpha rendering for multi-frame animations &lt;a href=&quot;https://github.com/esphome/esphome/pull/16017&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16017&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-4-4---may-5&quot;&gt;Release 2026.4.4 - May 5&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[automation] Fix codegen type for component.resume update_interval &lt;a href=&quot;https://github.com/esphome/esphome/pull/16069&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16069&lt;/a&gt; by &lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mcp23xxx_base] Reject unsupported interrupt_pin options (inverted, allow_other_uses) &lt;a href=&quot;https://github.com/esphome/esphome/pull/16149&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16149&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Strip \?\ prefix from sys.executable for PlatformIO subprocess &lt;a href=&quot;https://github.com/esphome/esphome/pull/16158&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16158&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Replace 512B stack buffer in printf wraps with picolibc cookie FILE &lt;a href=&quot;https://github.com/esphome/esphome/pull/16170&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16170&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Clamp values for meter line indicators &lt;a href=&quot;https://github.com/esphome/esphome/pull/16180&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16180&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Drop printf wrap on IDF 6.0+ (picolibc no longer needs it) &lt;a href=&quot;https://github.com/esphome/esphome/pull/16189&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16189&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fall back to owning types for service array args used after a delay &lt;a href=&quot;https://github.com/esphome/esphome/pull/16140&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16140&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Use safe_print for log output and fix safe_print bytes-repr fallback &lt;a href=&quot;https://github.com/esphome/esphome/pull/16160&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16160&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-4-5---may-7&quot;&gt;Release 2026.4.5 - May 7&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[ha-addon] Add opt-in toggle for the new ESPHome Device Builder &lt;a href=&quot;https://github.com/esphome/esphome/pull/16247&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16247&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bundle] Include secrets.yaml when &lt;code dir=&quot;auto&quot;&gt;!secret&lt;/code&gt; keys are quoted &lt;a href=&quot;https://github.com/esphome/esphome/pull/16271&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16271&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[substitutions] Fix sibling references inside dict-valued substitutions &lt;a href=&quot;https://github.com/esphome/esphome/pull/16273&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16273&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix WiFi connection in safe mode &lt;a href=&quot;https://github.com/esphome/esphome/pull/16269&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16269&lt;/a&gt; by &lt;a href=&quot;https://github.com/Mat931&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Mat931&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[nextion] Fix text sensor state not updated on string response &lt;a href=&quot;https://github.com/esphome/esphome/pull/16280&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#16280&lt;/a&gt; by &lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.4.0/&quot;&gt;full 2026.4.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2026.3.0: Performance overhaul and first-class RP2040</title><link>https://esphome.io/blog/2026/03/18/esphome-2026-3/</link><guid isPermaLink="true">https://esphome.io/blog/2026/03/18/esphome-2026-3/</guid><description>ESPHome 2026.3.0 delivers deep performance work across the main loop, lights and API, first-class RP2040/RP2350 support, and a new media player architecture.</description><pubDate>Wed, 18 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/serial_proxy/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/uart.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Serial ​Proxy&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/media_source/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/folder-open.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Media ​Source ​Core&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/media_source/audio_file/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/file-document-box.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Audio ​File ​Media ​Source&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/audio_file/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/file-document-box.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Audio ​File&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hdc302x/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/hdc302x.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;HDC3​0​2​x&lt;/div&gt;&lt;div&gt;Temperature ​&amp;#x26;​ ​Humidity&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/sen6x/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/sen6x.webp&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;SEN6​x&lt;/div&gt;&lt;div&gt;Particulate ​&amp;#x26;​ ​Temperature ​&amp;#x26;​ ​Humidity ​&amp;#x26;​ ​VOC ​&amp;#x26;​ ​NOx ​&amp;#x26;​ ​CO2​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/rp2040_ble/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bluetooth.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;RP2​0​4​0​ ​BLE&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/dew_point/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/water-drop.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Dew ​Point&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.3.0 is a performance-focused release with deep optimizations across the entire stack. The main loop is up to 99x faster on socket polling, light gamma correction is 8-10x faster, API protobuf encoding is 6-12x faster, and &lt;code dir=&quot;auto&quot;&gt;millis()&lt;/code&gt; is 2.5x faster, all reducing CPU overhead and improving responsiveness, especially on single-core chips and Bluetooth proxy devices. Flash savings of 11-20KB+ are achieved through printf wrapping, scanf removal, timezone refactoring, and aggressive devirtualization.&lt;/p&gt;
&lt;p&gt;Alongside the performance work, a redesigned media player architecture with pluggable sources, playlists, and Ogg Opus support ships together with RP2040/RP2350 reaching first-class platform support — pico-sdk 2.0, 143+ board definitions, BLE foundations, crash diagnostics, and captive portal. A long-standing LWIP use-after-free bug that caused heap corruption crashes on ESP8266 (and RP2040) has been fixed — both platforms now pass stress testing. An 86-fix codebase correctness sweep from &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; addresses buffer overflows, millis() overflow bugs, uninitialized variables, and logic errors across 100+ components. ESP32 gains an automatic crash handler that captures backtraces across reboots and reports them over the API — no serial cable needed. ESP32-P4 and ESP32-C5 gain expanded hardware support, nRF52 gets BLE OTA, and new components include SEN6x, HDC302x, dew point, and serial proxy.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;opentherm&lt;/code&gt; with the &lt;code dir=&quot;auto&quot;&gt;opentherm_version&lt;/code&gt; config key, rename it to &lt;code dir=&quot;auto&quot;&gt;opentherm_version_controller&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;speaker&lt;/code&gt; media player and stream audio via hardcoded URLs (not through Home Assistant), set &lt;code dir=&quot;auto&quot;&gt;codec_support_enabled: all&lt;/code&gt; to keep all codecs available&lt;/li&gt;
&lt;li&gt;If you have an ESP32-P4 engineering sample (pre-rev3), add &lt;code dir=&quot;auto&quot;&gt;engineering_sample: true&lt;/code&gt; to your &lt;code dir=&quot;auto&quot;&gt;esp32:&lt;/code&gt; config&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;sgp30&lt;/code&gt; sensors, plan for up to 12 hours of recalibration after update as stored baselines will be invalidated by a serial number fix&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;nextion&lt;/code&gt; TFT uploads over slow networks, set &lt;code dir=&quot;auto&quot;&gt;tft_upload_http_timeout&lt;/code&gt; to a higher value (default changed from 15s to 4.5s)&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;time&lt;/code&gt; component and have lambdas calling &lt;code dir=&quot;auto&quot;&gt;::mktime()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;::strftime()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;setenv(&quot;TZ&quot;, ...)&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;tzset()&lt;/code&gt; directly, update them to use ESPHome’s &lt;a href=&quot;https://esphome.io/components/time/&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;ESPTime&lt;/code&gt; API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;on_multi_click&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_click&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_double_click&lt;/code&gt;, or count edges in &lt;code dir=&quot;auto&quot;&gt;on_press&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;on_release&lt;/code&gt; on a physical button wired to the &lt;code dir=&quot;auto&quot;&gt;gpio&lt;/code&gt; binary_sensor &lt;em&gt;without a debounce filter&lt;/em&gt;, add a &lt;code dir=&quot;auto&quot;&gt;delayed_on_off: 20ms&lt;/code&gt; filter (or &lt;code dir=&quot;auto&quot;&gt;delayed_on&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;delayed_off&lt;/code&gt;) to that sensor’s &lt;code dir=&quot;auto&quot;&gt;filters:&lt;/code&gt; list. Most users already follow the documented guidance; this only affects configs that skipped it. The instant-ISR-wake change (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14383&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14383&lt;/a&gt;) means mechanical switch bounce now reaches downstream automations instead of being swallowed by the slow loop poll cadence. See &lt;a href=&quot;https://esphome.io/components/binary_sensor/gpio#debouncing-values&quot;&gt;debouncing values&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;div&gt;&lt;h2 id=&quot;main-loop-performance-overhaul&quot;&gt;Main Loop Performance Overhaul&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release delivers a major performance overhaul to the core event loop, reducing CPU overhead and improving responsiveness across all platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Socket Polling: Up to 99x Faster on ESP32&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;lwip_select()&lt;/code&gt; system call has been replaced with direct LwIP socket reads and FreeRTOS task notifications on ESP32 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14249&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14249&lt;/a&gt;). The old &lt;code dir=&quot;auto&quot;&gt;select()&lt;/code&gt; call cost ~133 us per loop iteration due to internal locking overhead. The new pre-sleep scan costs just ~1.3 us (99x faster), the active poll path costs ~7.5 us (17x faster), and the wake mechanism dropped from ~130 us to ~1.8 us (72x faster), freeing ~1.55% of total CPU time. On single-core chips (ESP32-C3, C6, H2), this directly improves BLE scan responsiveness by eliminating mutex contention with the WiFi/BLE stacks. The optimization was also extended to all LibreTiny platforms (bk72xx, rtl87xx, ln882x) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14254&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14254&lt;/a&gt;), where real-world testing showed WiFi connection times dropping from up to 60s to under 30s.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Instant ISR Wake&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GPIO binary sensors and touch sensors now wake the main loop immediately from interrupts instead of waiting up to ~16ms for the select timeout (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14383&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14383&lt;/a&gt;). UART wake-on-RX was also redesigned — replacing a FreeRTOS task + event queue (~3.9KB heap per UART) with a direct ISR callback at essentially zero cost (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14382&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14382&lt;/a&gt;). With the new near-zero-cost mechanism, wake-on-RX is now enabled by default on all ESP32 UARTs (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14391&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14391&lt;/a&gt;), and ESP8266 gained ISR wake support for GPIO binary sensors (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14392&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14392&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Native 64-bit Time and Faster millis()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A new &lt;code dir=&quot;auto&quot;&gt;millis_64()&lt;/code&gt; HAL function provides 64-bit uptime across all platforms, replacing the Scheduler’s rollover tracking (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14339&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14339&lt;/a&gt;). On ESP32, this reads &lt;code dir=&quot;auto&quot;&gt;esp_timer_get_time()&lt;/code&gt; directly (26 bytes, lock-free) instead of the 193-byte rollover reconstruction path. RP2040 uses &lt;code dir=&quot;auto&quot;&gt;time_us_64()&lt;/code&gt; from the hardware timer (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14356&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14356&lt;/a&gt;), and Host uses &lt;code dir=&quot;auto&quot;&gt;clock_gettime(CLOCK_MONOTONIC)&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14340&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14340&lt;/a&gt;). ESP8266 and LibreTiny use a lightweight software rollover tracker. Components like &lt;code dir=&quot;auto&quot;&gt;uptime&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt; now call &lt;code dir=&quot;auto&quot;&gt;millis_64()&lt;/code&gt; directly from &lt;code dir=&quot;auto&quot;&gt;hal.h&lt;/code&gt; instead of going through &lt;code dir=&quot;auto&quot;&gt;App.scheduler&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;millis()&lt;/code&gt; function itself — called once per component per loop iteration — was also optimized with a &lt;a href=&quot;https://en.wikipedia.org/wiki/Euclidean_division&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Euclidean decomposition&lt;/a&gt; that eliminates the &lt;code dir=&quot;auto&quot;&gt;__udivdi3&lt;/code&gt; software 64-bit division routine, achieving 2-2.5x speedup on every call (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14409&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14409&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Loop Call Overhead&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The main loop now calls &lt;code dir=&quot;auto&quot;&gt;component-&gt;loop()&lt;/code&gt; directly instead of going through &lt;code dir=&quot;auto&quot;&gt;call()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;call_loop_()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt;, eliminating 2 unnecessary function frames per component per iteration (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14451&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14451&lt;/a&gt;). On a device with 120 looping components, that’s 240 function frames removed per loop cycle. Trivial component state accessors (&lt;code dir=&quot;auto&quot;&gt;get_component_state()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;is_failed()&lt;/code&gt;, etc.) were moved to inline header definitions, eliminating function call overhead for what amounts to single-byte loads (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14425&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14425&lt;/a&gt;). The &lt;code dir=&quot;auto&quot;&gt;is_high_frequency()&lt;/code&gt; check, called every loop iteration, was also inlined (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14423&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14423&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cached Connection Checks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;WiFi &lt;code dir=&quot;auto&quot;&gt;is_connected()&lt;/code&gt; now caches connection state as a simple bool field, eliminating expensive SDK calls on every invocation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14463&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14463&lt;/a&gt;). The &lt;code dir=&quot;auto&quot;&gt;network::is_connected()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;EthernetComponent::is_connected()&lt;/code&gt; functions were moved to headers as inline (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14464&lt;/a&gt;). OpenThread connection state is now updated via callback instead of polling with a mutex lock on every loop (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14484&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14484&lt;/a&gt;). The API server’s &lt;code dir=&quot;auto&quot;&gt;is_connected()&lt;/code&gt; was split into an inline fast path for the common no-arg case and an out-of-line path for state subscription checks, important for the BLE proxy hot path (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14574&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14574&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;rp2040rp2350-first-class-platform-support&quot;&gt;RP2040/RP2350: First-Class Platform Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The RP2040/RP2350 platform takes a major step toward first-class support in this release. The &lt;strong&gt;arduino-pico framework jumps from 3.9.4 to 5.5.0&lt;/strong&gt;, bringing pico-sdk 2.0 and the GCC 14 toolchain (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14328&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14328&lt;/a&gt;). RP2350 (Pico 2 W) is now verified on real hardware with WiFi, debug sensors, and OTA all working, and the platform gains the same reliability, tooling, and developer experience that ESP32 users expect.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What the framework update brings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RP2350 hardware verified&lt;/strong&gt; - Pico 2 W tested with WiFi, debug sensors, and OTA all working (429KB free heap)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;143+ board definitions&lt;/strong&gt; (up from 3) auto-generated from the arduino-pico repository, including all RP2350 variants (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14528&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14528&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WiFi reliability fixes&lt;/strong&gt; - Proper CYW43 link status detection, non-blocking WiFi join, and correct disconnect cleanup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New Capabilities:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BLE foundation&lt;/strong&gt; - New &lt;a href=&quot;https://esphome.io/components/rp2040_ble&quot;&gt;rp2040_ble&lt;/a&gt; component initializes BTstack on Pico W/Pico 2 W boards, laying the groundwork for BLE scanning and Bluetooth proxy support with only ~17KB overhead (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14603&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14603&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BOOTSEL upload via picotool&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;esphome upload&lt;/code&gt; now detects RP2040 devices in BOOTSEL mode, uploads with real-time progress, and automatically starts log output after reboot (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14483&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HardFault crash handler&lt;/strong&gt; - See the &lt;a href=&quot;#crash-handlers-without-a-serial-cable&quot;&gt;Crash Handlers&lt;/a&gt; section below for details (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14685&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14685&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14716&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14716&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware UART with single pin&lt;/strong&gt; - RP2040 now supports configuring a hardware UART with only TX or only RX, useful for one-way serial protocols (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14725&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14725&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ADC fix for RP2350&lt;/strong&gt; - Fixed a &lt;code dir=&quot;auto&quot;&gt;PICO_VSYS_PIN&lt;/code&gt; compile error on RP2350 boards when using the ADC component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14724&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14724&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Socket wake support&lt;/strong&gt; - The fast select optimization was ported to RP2040, enabling efficient socket polling without &lt;code dir=&quot;auto&quot;&gt;lwip_select()&lt;/code&gt; overhead (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14498&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14498&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WiFi AP and captive portal&lt;/strong&gt; - WiFi AP mode and AP+STA fallback now work reliably on RP2040/RP2350, with 7 WiFi fixes in arduino-pico 5.5.1 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14500&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14500&lt;/a&gt;). The captive portal component was also enabled for the platform (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14505&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14505&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Reliability:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LWIP PCB use-after-free fixed&lt;/strong&gt; - A long-standing bug where &lt;code dir=&quot;auto&quot;&gt;tcp_close()&lt;/code&gt; left the PCB alive during the TCP close handshake, allowing LWIP &lt;code dir=&quot;auto&quot;&gt;recv&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;err&lt;/code&gt; callbacks to fire with dangling pointers after the socket object was destroyed, has been fixed (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14706&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14706&lt;/a&gt;). This caused &lt;code dir=&quot;auto&quot;&gt;umm_malloc_core&lt;/code&gt; heap corruption crashes that have plagued ESP8266 reliability for years, and also affected RP2040. Both platforms now pass the 500-iteration rapid connect/disconnect stress test with 4 concurrent clients.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TCP race condition fixed&lt;/strong&gt; - A critical race between lwip IRQ callbacks and the main loop on Pico W was identified and fixed, preventing heap corruption under concurrent API connections (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14679&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14679&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accept-in-IRQ heap corruption fixed&lt;/strong&gt; - Socket accept callbacks on RP2040 no longer allocate memory in IRQ context, eliminating crashes under rapid connect/disconnect stress testing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14687&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14687&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OTA timeout fixed&lt;/strong&gt; - OTA updates on ESP8266 and RP2040 no longer time out under load; switched from polling to &lt;code dir=&quot;auto&quot;&gt;SO_RCVTIMEO&lt;/code&gt; for reliable socket reads (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14675&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14675&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mDNS restart after WiFi reconnect&lt;/strong&gt; - mDNS on RP2040 now correctly restarts after WiFi reconnects, fixing service discovery failures (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14737&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14737&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I2C bus selection&lt;/strong&gt; - Fixed RP2040 I2C bus selection to correctly choose the hardware I2C peripheral based on pin assignment (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14745&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14745&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Debug reset reason&lt;/strong&gt; - The debug component now correctly reports the reset reason on RP2040/RP2350 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14740&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14740&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Flash and Performance:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;9.2KB flash savings&lt;/strong&gt; from printf stub optimization (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14622&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14622&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native &lt;code dir=&quot;auto&quot;&gt;millis_64()&lt;/code&gt;&lt;/strong&gt; using the hardware timer, eliminating software rollover tracking (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14356&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14356&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faster &lt;code dir=&quot;auto&quot;&gt;millis()&lt;/code&gt;&lt;/strong&gt; via optimized 64-bit division, 2-2.5x faster on every call (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14409&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14409&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: The framework update is a breaking change for external components using old pico-sdk APIs (e.g., &lt;code dir=&quot;auto&quot;&gt;padsbank0_hw&lt;/code&gt; renamed to &lt;code dir=&quot;auto&quot;&gt;pads_bank0_hw&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SerialPIO::NOPIN&lt;/code&gt; is now just &lt;code dir=&quot;auto&quot;&gt;NOPIN&lt;/code&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;libretiny-platform-improvements&quot;&gt;LibreTiny Platform Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The LibreTiny platforms (BK72xx, RTL87xx, LN882x) received a significant reliability and performance overhaul this release.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;lwIP Memory Tuning (~26KB freed on BK72xx):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The SDK-default lwIP buffer sizes were tuned for WiFi Alliance throughput certification, not IoT devices. &lt;code dir=&quot;auto&quot;&gt;TCP_SND_BUF&lt;/code&gt; at 10xMSS (14.6KB per chunk) caused OOM on BK7231N when ESPAsyncWebServer allocated response buffers. Switching to system heap allocation (&lt;code dir=&quot;auto&quot;&gt;MEM_LIBC_MALLOC=1&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;MEMP_MEM_MALLOC=1&lt;/code&gt;) and right-sizing buffers freed ~26.5KB on BK7231N and ~20.2KB on RTL87xx (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14186&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14186&lt;/a&gt;). This also fixes OTA slowness on BK72xx caused by dedicated heap fragmentation during MSS-sized pbuf allocations. Socket counts are now auto-calculated from component registrations instead of hardcoded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BK72xx Loop Stalls Fixed:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The BK72xx main task ran at FreeRTOS priority 3, below all WiFi (4-5) and LwIP (4) tasks, causing ~100ms loop stalls whenever WiFi background processing ran. Raising the priority to 6 (matching RTL87xx’s effective priority) dropped loop times from ~110ms to ~14ms (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14420&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14420&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BK72xx -Os optimization&lt;/strong&gt; - ESPHome source code now compiles with &lt;code dir=&quot;auto&quot;&gt;-Os&lt;/code&gt; on BK72xx while the SDK stays at &lt;code dir=&quot;auto&quot;&gt;-O1&lt;/code&gt;, improving flash usage without triggering SDK bugs (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14322&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14322&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fast select optimization&lt;/strong&gt; - The ESP32 socket polling optimization was ported to all LibreTiny platforms, with real-world WiFi connection times dropping from up to 60s to under 30s (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14254&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14254&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Direct SDK SSID retrieval&lt;/strong&gt; - WiFi SSID queries now call vendor SDK functions directly instead of going through Arduino’s &lt;code dir=&quot;auto&quot;&gt;String&lt;/code&gt;-allocating &lt;code dir=&quot;auto&quot;&gt;WiFi.SSID()&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14349&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14349&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;nrf52-platform-improvements&quot;&gt;nRF52 Platform Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The nRF52 platform gains critical OTA and debugging capabilities, thanks to &lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BLE and Serial OTA:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The new &lt;a href=&quot;https://esphome.io/components/ota/zephyr_mcumgr&quot;&gt;zephyr_mcumgr&lt;/a&gt; component enables over-the-air updates via BLE or serial using the MCUmgr protocol (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11932&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11932&lt;/a&gt;). This is a major step forward for nRF52 devices which previously lacked wireless update support.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Crash Debugging:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Early boot debug messages are now available on nRF52, including boot reason logging and last crash PC/LR values stored in a no-init buffer (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11685&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11685&lt;/a&gt;). The logger waits up to 10 seconds for the CDC port to open, ensuring no early logs are lost.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;BLE NUS UART:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;ble_nus&lt;/code&gt; component now supports bidirectional UART communication over Bluetooth, compatible with tools like &lt;a href=&quot;https://pypi.org/project/ble-serial/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ble-serial&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14320&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14320&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;scheduler-performance&quot;&gt;Scheduler Performance&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The scheduler drives all timers, intervals, and deferred callbacks on every device. This release includes 7 targeted optimizations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Defer queue lock halving&lt;/strong&gt; - Lock acquisitions reduced from 2N+1 to N+1 for N deferred items, with the lock skipped entirely when the queue is empty (the common case) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14107&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14107&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Relaxed memory ordering&lt;/strong&gt; - Atomic reads under the scheduler lock now use relaxed ordering since the lock already provides the necessary memory barrier (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14140&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14140&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Atomic bool fix&lt;/strong&gt; - GCC on Xtensa generated indirect function calls for &lt;code dir=&quot;auto&quot;&gt;std::atomic&amp;#x3C;bool&gt;::load()&lt;/code&gt; instead of inlining it. Switching to &lt;code dir=&quot;auto&quot;&gt;std::atomic&amp;#x3C;uint8_t&gt;&lt;/code&gt; eliminated 5 indirect calls on the hot path, saving 30 bytes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14626&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14626&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raw pointer lifecycle management&lt;/strong&gt; - Replaced &lt;code dir=&quot;auto&quot;&gt;unique_ptr&amp;#x3C;SchedulerItem&gt;&lt;/code&gt; with explicit lifecycle management, eliminating 608 bytes of STL template instantiations (&lt;code dir=&quot;auto&quot;&gt;__adjust_heap&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;_M_realloc_append&lt;/code&gt;, etc.) and adding debug leak detection (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14620&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14620&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;De-templated helpers&lt;/strong&gt; - Consolidated scheduler helper functions to reduce code duplication (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14164&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14164&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rvalue std::function&lt;/strong&gt; - Scheduler callbacks are now passed by rvalue reference, avoiding unnecessary copies (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14260&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14260&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;millis_64 extracted&lt;/strong&gt; - The 32-bit rollover tracking code was moved out of the Scheduler into its own module, removing the dependency on &lt;code dir=&quot;auto&quot;&gt;App.scheduler&lt;/code&gt; being initialized and allowing &lt;code dir=&quot;auto&quot;&gt;defer()&lt;/code&gt; items to skip the &lt;code dir=&quot;auto&quot;&gt;millis_64()&lt;/code&gt; call entirely (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14360&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14360&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;api-and-protobuf-performance&quot;&gt;API and Protobuf Performance&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The native API communication layer received over 20 targeted optimizations this release, particularly benefiting Bluetooth proxy devices where protobuf encoding is the dominant CPU cost.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Encoding Pipeline:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Direct buffer writes&lt;/strong&gt; - Protobuf encoding now writes through raw pointers to pre-sized buffers instead of &lt;code dir=&quot;auto&quot;&gt;push_back()&lt;/code&gt;, achieving 6-12x faster encoding in benchmarks (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14018&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14018&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protobuf devirtualization&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;encode()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;calculate_size()&lt;/code&gt; are resolved at compile time instead of through virtual dispatch, achieving 2x faster &lt;code dir=&quot;auto&quot;&gt;calculate_size()&lt;/code&gt; on sensor state messages and 2.5x less CPU time in the API component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14449&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14449&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single-pass BLE advertisement encoding&lt;/strong&gt; - Eliminates 24 redundant &lt;code dir=&quot;auto&quot;&gt;calculate_size()&lt;/code&gt; calls per BLE proxy flush, reducing encode time by 28% (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14575&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14575&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-fill elimination&lt;/strong&gt; - A custom &lt;code dir=&quot;auto&quot;&gt;APIBuffer&lt;/code&gt; replaces &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x3C;uint8_t&gt;&lt;/code&gt; for protobuf buffers, skipping unnecessary zero-initialization before every message encode, reducing API component CPU time by 43% on BLE proxy devices (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14593&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14593&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Force proto fields&lt;/strong&gt; - BLE advertisement fields known to be non-default skip zero checks, saving 13% on &lt;code dir=&quot;auto&quot;&gt;calculate_size()&lt;/code&gt; for BLE batches (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14610&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14610&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Parsing and Dispatch:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Varint 32/64-bit split&lt;/strong&gt; - Varint parsing uses fast 32-bit arithmetic for the common case (1-4 byte values), with 64-bit only when BLE fields require it, 25-50% faster on common paths (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14039&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14039&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Varint fast paths inlined&lt;/strong&gt; - Protobuf varint parsing and encoding hot paths were inlined for zero function-call overhead in tight loops (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14607&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14607&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14638&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14638&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frame helper devirtualization&lt;/strong&gt; - When only one API protocol is configured (plaintext-only or noise-only), virtual dispatch is eliminated for all frame operations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14468&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14468&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Noise data path optimized&lt;/strong&gt; - Redundant state machine checks eliminated from every packet read/write in the noise protocol path (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14629&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14629&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keepalive ping outlined&lt;/strong&gt; - The keepalive/disconnect cold path was extracted from &lt;code dir=&quot;auto&quot;&gt;APIConnection::loop()&lt;/code&gt;, reducing the hot loop body by 30% (374 to 263 bytes on Xtensa) since this code only fires once per minute (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14374&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14374&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Encryption:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ChaCha20-Poly1305 optimized for embedded&lt;/strong&gt; - ESPHome-maintained patches to libsodium replace unaligned byte loads with aligned 32-bit loads in the poly1305 and chacha20 implementations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14632&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14632&lt;/a&gt;). On Xtensa, each unaligned &lt;code dir=&quot;auto&quot;&gt;LOAD32_LE&lt;/code&gt; decomposed into 4 byte-load instructions plus shifts; the patched path uses direct aligned loads. Every encrypted API packet benefits: 8-32% faster across all platforms (32% on ESP32, 24% on ESP32-S3, 21% on ESP32-C3, 12% on RTL87xx, 10% on ESP8266/BK72xx, 8% on RP2040, measured with 1KB packets).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Network Layer:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Socket layer overhaul&lt;/strong&gt; - The entire socket abstraction was devirtualized, converting the virtual base class to concrete per-platform types (&lt;code dir=&quot;auto&quot;&gt;BSDSocketImpl&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;LwIPSocketImpl&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;LWIPRawImpl&lt;/code&gt;) with zero virtual methods (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14398&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14398&lt;/a&gt;). The compiler now fully inlines hot-path socket methods (&lt;code dir=&quot;auto&quot;&gt;read&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;write&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;writev&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ready&lt;/code&gt;) directly into API frame helpers and OTA chunk handlers, eliminating vtable loads on every packet. Saves ~3KB flash on ESP32. Socket pointer caching (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14408&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14408&lt;/a&gt;) further inlined the entire &lt;code dir=&quot;auto&quot;&gt;ready()&lt;/code&gt; chain to ~30 bytes with zero function calls.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handshake timeout&lt;/strong&gt; - 15-second timeout for completing API handshakes prevents connection slot exhaustion from stale half-open connections (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14050&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14050&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inlined send buffer fast path&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;try_to_clear_buffer()&lt;/code&gt; check on every &lt;code dir=&quot;auto&quot;&gt;send_buffer()&lt;/code&gt; call is now inlined, avoiding a function call when the TX buffer is already clear (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14630&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14630&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TCP_NODELAY fast path&lt;/strong&gt; - Setting &lt;code dir=&quot;auto&quot;&gt;TCP_NODELAY&lt;/code&gt; now bypasses the expensive &lt;code dir=&quot;auto&quot;&gt;lwip_setsockopt&lt;/code&gt; overhead by writing directly to the PCB flags (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14693&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14693&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;BLE Event Processing:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BLE event hot path optimized&lt;/strong&gt; - Eliminated redundant operations in the ESP32 BLE event processing loop, including short-circuiting dropped-count checks (4 instructions instead of ~25 in the common case) and removing redundant event release calls (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14627&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14627&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;light-optimizations&quot;&gt;Light Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Runtime &lt;code dir=&quot;auto&quot;&gt;powf()&lt;/code&gt; calls in light gamma correction have been replaced with pre-computed PROGMEM lookup tables generated at compile time (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14123&lt;/a&gt;). A 5-channel RGBWW light transition frame dropped from 349 us to 36 us on ESP32 (8-10x faster) and from 456 us to 58 us on ESP8266. Addressable lights also save 512 bytes of heap per instance - the RAM gamma tables are eliminated entirely. The &lt;code dir=&quot;auto&quot;&gt;powf&lt;/code&gt; math library (~2.3KB flash) is no longer pulled into the binary for lights.&lt;/p&gt;
&lt;p&gt;Light color interpolation now uses a lightweight &lt;code dir=&quot;auto&quot;&gt;lerp_fast&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;std::lerp&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14238&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14238&lt;/a&gt;), and static effect names are resolved to integer indices at code generation time instead of runtime string matching, saving 632 bytes on ESP8266 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14265&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14265&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;powf&lt;/code&gt; elimination extends beyond lights - a new &lt;code dir=&quot;auto&quot;&gt;pow10_int()&lt;/code&gt; helper replaces &lt;code dir=&quot;auto&quot;&gt;powf(10, exp)&lt;/code&gt; in sensor filters and accuracy normalization, achieving up to 22x faster computation on ESP8266 and saving 3.1KB flash (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14114&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14114&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;logger-optimizations&quot;&gt;Logger Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The logger received 7 targeted optimizations recovering wasted RAM and reducing per-log-call overhead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UART heap waste eliminated&lt;/strong&gt; - Removed the unused FreeRTOS event queue and oversized RX buffer from &lt;code dir=&quot;auto&quot;&gt;uart_driver_install()&lt;/code&gt; on ESP32, recovering ~595 bytes of heap (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14168&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14168&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TX buffer compile-time sized&lt;/strong&gt; - The transmit buffer is now an inline array instead of a separate heap allocation, consolidating two allocations into one (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14205&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14205&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loop disable fix&lt;/strong&gt; - The logger’s no-op &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; was running ~114x/s on all ESP32-S2/S3/C3/C5/C6/H2/P4 variants due to a wrong preprocessor guard (&lt;code dir=&quot;auto&quot;&gt;USE_LOGGER_USB_CDC&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;USE_LOGGER_UART_SELECTION_USB_CDC&lt;/code&gt;) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14158&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14158&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LogListener devirtualized&lt;/strong&gt; - Replaced the &lt;code dir=&quot;auto&quot;&gt;LogListener&lt;/code&gt; abstract class with a lightweight &lt;code dir=&quot;auto&quot;&gt;LogCallback&lt;/code&gt; struct (function pointer + instance pointer), eliminating vtable overhead from every class that implemented it (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14084&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14084&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logger and trigger marked final&lt;/strong&gt; - Enables the compiler to devirtualize calls to &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;dump_config()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;get_setup_priority()&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14291&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14291&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faster line number formatting&lt;/strong&gt; - Replaced division-based formatting with subtraction loops, 1.8x faster on ESP8266 (no hardware divider) and 1.44x faster on ESP32-C3 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14219&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14219&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hot path optimized&lt;/strong&gt; - Eliminated null-check and call frame indirection from every log call, with early log detection in debug builds (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14538&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14538&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;memory-and-flash-optimizations&quot;&gt;Memory and Flash Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Several significant optimizations reduce firmware size and RAM usage across all platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Timezone Overhaul (~9.5KB flash on ESP32, ~2% RAM on ESP8266):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The entire libc timezone infrastructure has been replaced with a lightweight 32-byte struct parser (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13635&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13635&lt;/a&gt;). Previously, ESPHome pulled in libc’s &lt;code dir=&quot;auto&quot;&gt;scanf&lt;/code&gt; family (~9.8KB), environment variable infrastructure, and double-stored timezone data just to parse a string it already knew. The new implementation also provides consistent cross-platform timezone behavior with 126 unit tests, eliminating differences between newlib versions on different chips. Lambdas using &lt;code dir=&quot;auto&quot;&gt;::mktime()&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;setenv(&quot;TZ&quot;, ...)&lt;/code&gt; directly may need to be updated.&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Platform&lt;/th&gt;&lt;th&gt;Flash Savings&lt;/th&gt;&lt;th&gt;RAM Savings&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;ESP32-IDF&lt;/td&gt;&lt;td&gt;~9.5KB&lt;/td&gt;&lt;td&gt;136 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ESP8266&lt;/td&gt;&lt;td&gt;~4.1KB&lt;/td&gt;&lt;td&gt;~850 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LibreTiny&lt;/td&gt;&lt;td&gt;~4.7KB&lt;/td&gt;&lt;td&gt;148 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RP2040&lt;/td&gt;&lt;td&gt;~3.7KB&lt;/td&gt;&lt;td&gt;148 bytes&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;printf/scanf Wrapping:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32 printf wrapping saves ~11KB flash&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;printf()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;vprintf()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;fprintf()&lt;/code&gt; are wrapped with lightweight stubs that redirect through &lt;code dir=&quot;auto&quot;&gt;vsnprintf()&lt;/code&gt;, eliminating newlib’s &lt;code dir=&quot;auto&quot;&gt;_vfprintf_r&lt;/code&gt; dead code (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14362&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14362&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP8266 scanf removal saves ~8KB flash&lt;/strong&gt; - The forced &lt;code dir=&quot;auto&quot;&gt;-u _scanf_float&lt;/code&gt; linker flag has been removed, garbage-collecting the entire unused &lt;code dir=&quot;auto&quot;&gt;scanf&lt;/code&gt; family (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13678&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13678&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP8266 printf stubs save ~1.6KB flash&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14621&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14621&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RP2040 printf stubs save ~9.2KB flash&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14622&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14622&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;JSON Serialization Without Heap Allocation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JSON serialization for web_server, MQTT, and API responses now uses a stack-first &lt;code dir=&quot;auto&quot;&gt;SerializationBuffer&lt;/code&gt; that handles 99.9% of payloads (up to 640 bytes) without any heap allocation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13625&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13625&lt;/a&gt;). Previously, every JSON response built a &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; on the heap. The new buffer falls back to heap only for unusually large payloads (40+ select options, extreme climate presets). User service string arguments also switched from &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13974&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13974&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Preferences Heap Churn Eliminated:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Most preference saves (switches, fans, covers, numbers, rotary encoders) now use a small inline buffer instead of heap-allocating for every save operation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13259&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13259&lt;/a&gt;). A union-based &lt;code dir=&quot;auto&quot;&gt;SmallInlineBuffer&amp;#x3C;8&gt;&lt;/code&gt; stores data inline when 8 bytes or smaller, eliminating heap fragmentation from repeated preference writes on long-running devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Entity String Packing:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Entity string properties (&lt;code dir=&quot;auto&quot;&gt;device_class&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;unit_of_measurement&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;icon&lt;/code&gt;) were packed into PROGMEM-indexed &lt;code dir=&quot;auto&quot;&gt;uint8_t&lt;/code&gt; fields stored in struct padding bytes, replacing per-entity &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt; pointers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14171&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14171&lt;/a&gt;). This saves 8-12 bytes per entity with zero extra memory cost since the indices fit in alignment padding. Measured: +3,084 bytes free heap on ESP32-S3 (large config), +369 bytes on ESP8266. Application &lt;code dir=&quot;auto&quot;&gt;name&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;friendly_name&lt;/code&gt; were also converted from &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt;, saving 416-2,508 bytes flash and +308 bytes free heap on ESP8266 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14532&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14532&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESP8266 PROGMEM Optimizations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Icon strings moved to flash&lt;/strong&gt; - Saves ~27 bytes per unique icon (~1KB for a config with 40 icons) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14437&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Device class strings moved to flash&lt;/strong&gt; - Same treatment applied to device class strings, with deduplicated handling across MQTT and API (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14443&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14443&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static strings auto-wrapped in PROGMEM&lt;/strong&gt; via &lt;code dir=&quot;auto&quot;&gt;TemplatableValue&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13885&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13885&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entity setup calls consolidated&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;set_name&lt;/code&gt; + &lt;code dir=&quot;auto&quot;&gt;set_entity_strings&lt;/code&gt; merged into a single &lt;code dir=&quot;auto&quot;&gt;configure_entity_()&lt;/code&gt; call, saving 124 bytes flash on a ~30 entity config (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14444&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14444&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IRAM freed&lt;/strong&gt; - Removed unnecessary &lt;code dir=&quot;auto&quot;&gt;IRAM_ATTR&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;yield()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;delay()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;feed_wdt()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;arch_feed_wdt()&lt;/code&gt;, freeing ~22 bytes IRAM on ESP8266 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14063&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14063&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ESP-IDF 5.5.3:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ESP-IDF has been bumped to 5.5.3 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14122&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14122&lt;/a&gt;), fixing long-standing BLE bugs from 5.5.1 and 5.5.2 where Bluetooth would stop working on ESP32 devices. Users who experienced BLE connectivity drops or Bluetooth proxy failures should see these resolved. A follow-up bump to 5.5.3.1 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14147&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14147&lt;/a&gt;) fixed a Bluedroid compile error, allowing the workaround that unconditionally enabled GATTS to be reverted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Framework and Core Optimizations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Component devirtualization&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;call_loop()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;mark_failed()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;call_dump_config()&lt;/code&gt; are now non-virtual, saving ~800+ bytes of flash from vtable elimination (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14083&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14083&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14355&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14355&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compile-time loop detection&lt;/strong&gt; - Components that don’t override &lt;code dir=&quot;auto&quot;&gt;loop()&lt;/code&gt; are now detected at compile time and excluded from the loop list, eliminating runtime vtable probing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14405&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14405&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conditional filter compilation&lt;/strong&gt; - Sensor, text sensor, and binary sensor filter infrastructure is now compiled out entirely when no filters are configured, saving flash and RAM (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14213&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14213&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14214&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14214&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14215&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14215&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FLAC CRC validation disabled&lt;/strong&gt; - Skipping internal CRC checks during FLAC decoding improves throughput by 15-20% (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14108&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14108&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Codebase-wide constexpr migration&lt;/strong&gt; - Over 20 PRs converted &lt;code dir=&quot;auto&quot;&gt;static const&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;constexpr&lt;/code&gt; across core, API, BLE, NFC, MQTT, and display components, moving constants to flash and enabling compiler optimizations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14071&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14071&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14127&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14127&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14129&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14129&lt;/a&gt;, and others)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;esphome::optional&lt;/code&gt; replaced with &lt;code dir=&quot;auto&quot;&gt;std::optional&lt;/code&gt;&lt;/strong&gt; - Eliminates a custom implementation in favor of the C++17 standard (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14368&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14368&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;crash-handlers-without-a-serial-cable&quot;&gt;Crash Handlers Without a Serial Cable&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;ESP32:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A new crash handler for ESP32 devices using the ESP-IDF framework automatically captures backtraces when a crash occurs, stores them in &lt;code dir=&quot;auto&quot;&gt;.noinit&lt;/code&gt; memory (survives software reset), and logs the data on next boot (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14709&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14709&lt;/a&gt;). Crash data appears in &lt;code dir=&quot;auto&quot;&gt;esphome logs&lt;/code&gt; over the API — no serial cable needed — and in the Home Assistant log viewer when “Subscribe to logs” is enabled. The CLI automatically decodes addresses inline using &lt;code dir=&quot;auto&quot;&gt;addr2line&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The handler works on both &lt;strong&gt;Xtensa&lt;/strong&gt; (ESP32, S2, S3) and &lt;strong&gt;RISC-V&lt;/strong&gt; (C3, C6, H2, C2) architectures, capturing up to 16 backtrace frames with human-readable exception reasons. On RISC-V, stack-scanned entries are validated and labeled to distinguish from register-sourced frames. Memory cost is minimal: +92 bytes RAM, +1,092 bytes flash. No configuration needed — it’s automatically enabled for all ESP-IDF devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RP2040/RP2350:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A HardFault crash handler captures register state and stack backtrace when a crash occurs, stores it across reboot via watchdog scratch registers, and logs it on next boot (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14685&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14685&lt;/a&gt;). A follow-up fix (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14716&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14716&lt;/a&gt;) improved backtrace storage and logger integration. The CLI’s serial log viewer auto-decodes addresses using &lt;code dir=&quot;auto&quot;&gt;addr2line&lt;/code&gt;. Works on both RP2040 and RP2350.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp32-p4-and-esp32-c5-improvements&quot;&gt;ESP32-P4 and ESP32-C5 Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;ESP32-P4:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Touch pad support&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;esp32_touch&lt;/code&gt; component has been migrated to ESP-IDF v5.5’s unified touch sensor driver, adding ESP32-P4 as a supported variant with 14 touch channels (GPIO 2-15) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14033&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14033&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production silicon default&lt;/strong&gt; - The default board now targets rev3+ production chips instead of engineering samples. Users with pre-rev3 dev kits should set &lt;code dir=&quot;auto&quot;&gt;engineering_sample: true&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14139&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14139&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execute from PSRAM&lt;/strong&gt; - Code execution from PSRAM is now enabled for P4, expanding available instruction memory (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14329&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14329&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LDO channels 1 &amp;#x26; 2&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;esp_ldo&lt;/code&gt; component now supports internal LDO channels with an explicit &lt;code dir=&quot;auto&quot;&gt;allow_internal_channel&lt;/code&gt; guard, useful for boards like the Waveshare ESP32-P4 where these channels power external peripherals (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14177&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14177&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ESP32-C5:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dual-band WiFi configuration&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;band_mode&lt;/code&gt; option for selecting 2.4GHz, 5GHz, or auto band selection on the ESP32-C5’s dual-band radio, thanks to &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14148&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14148&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-sensor-components&quot;&gt;New Sensor Components&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release adds support for several new sensor families.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SEN6x Environmental Sensor Node:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/sensor/sen6x&quot;&gt;sen6x&lt;/a&gt; component supports Sensirion’s entire SEN6x product family (SEN62, SEN63C, SEN65, SEN66, SEN68, SEN69C) with up to 7 measurement channels: PM1.0/2.5/4.0/10, temperature, humidity, NOx, VOC, CO2, and formaldehyde (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12553&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12553&lt;/a&gt;). Each sensor variant automatically exposes only its available channels.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HDC302x Temperature &amp;#x26; Humidity:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/sensor/hdc302x&quot;&gt;hdc302x&lt;/a&gt; component adds support for Texas Instruments’ high-precision HDC3020/3021/3022 sensors, including the IP67-rated HDC3022 with permanent PTFE dust and water protection (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10160&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#10160&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dew Point Calculator:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/sensor/dew_point&quot;&gt;dew_point&lt;/a&gt; component calculates the dew point from any existing temperature and humidity sensors, without requiring additional hardware (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14441&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14441&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;serial-proxy-experimental&quot;&gt;Serial Proxy (Experimental)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/serial_proxy&quot;&gt;serial_proxy&lt;/a&gt; component proxies UART communication to Home Assistant API clients over the network (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13944&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13944&lt;/a&gt;). This experimental component enables remote access to serial devices connected to ESPHome nodes, similar to how &lt;code dir=&quot;auto&quot;&gt;zwave_proxy&lt;/code&gt; bridges Z-Wave modems. Configure a UART bus and expose it as a named serial port with a specified type (TTL, RS232, RS485).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;display-support-expansion&quot;&gt;Display Support Expansion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Several new display models are now supported out of the box:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Waveshare DSI touch panels&lt;/strong&gt; - 5 new MIPI DSI models from 3.4” to 10.1” with touch support (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14023&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14023&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Waveshare 7.5” 4-color e-Paper (H)&lt;/strong&gt; - 800x480 display with black/white/yellow/red colors (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13991&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13991&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WeAct 3-color e-paper&lt;/strong&gt; - 2.13”, 2.9”, and 4.2” SSD1683-based displays with red/black/white (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13894&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13894&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Waveshare 1.83” v2&lt;/strong&gt; - MIPI SPI panel with updated init sequence for the Rev2 PCB (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13680&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13680&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Camera sensors without JPEG&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;esp32_camera&lt;/code&gt; component now supports sensors like the GC0308 (m5stack AtomS3R-CAM) that output RGB565 instead of JPEG, with automatic software JPEG conversion (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9496&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#9496&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;8-bit BMP support&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;runtime_image&lt;/code&gt; component now supports decoding 8-bit BMP images in addition to existing formats (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10733&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#10733&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;codebase-correctness-sweep&quot;&gt;Codebase Correctness Sweep&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; contributed 86 bugfix PRs this release in a systematic audit of the codebase, fixing issues that had silently accumulated across 100+ components. The fixes span several categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Buffer overflows and bounds checks&lt;/strong&gt; (16 PRs) - Fixed out-of-bounds reads and writes in components including ld2410, ld2420, remote_receiver, fingerprint_grow, pn532, NFC, shelly_dimmer, and multiple display drivers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14297&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14297&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14458&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14458&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14459&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14459&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14493&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14493&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14511&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14511&lt;/a&gt;, and others)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;millis() overflow bugs&lt;/strong&gt; (11 PRs) - Fixed timeout and duration checks that would break after ~49 days of uptime in bl0942, shelly_dimmer, lcd_base, light transitions, BLE presence, pn532, mcp2515, nextion, and others (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14285&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14285&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14292&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14292&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14474&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14474&lt;/a&gt;, and others)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Uninitialized variables&lt;/strong&gt; (5 PRs) - Added default initializers to member variables across deep_sleep, remote_transmitter, sim800l, sen5x, and many other components (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14556&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14556&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14636&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14636&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14659&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14659&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logic and copy-paste bugs&lt;/strong&gt; (9 PRs) - Fixed wrong operators, masks, and duplicated code in dfplayer, ads1115, alpha3, mpu6886, sht4x, and others (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14491&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14491&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14492&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14492&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14644&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14644&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unsigned integer underflows&lt;/strong&gt; (multiple PRs) - Fixed wrap-around bugs in esp32_improv, rf_bridge, display, pipsolar, and addressable light effects (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14466&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14466&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14546&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14546&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Division by zero guards&lt;/strong&gt; - Added checks in tsl2561, bl0942, graph, combination sensor, and others (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14634&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14634&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Malformed external input hardening&lt;/strong&gt; - Added bounds checks for BLE advertisements, Nextion responses, Modbus frames, and UART-based sensors to prevent crashes from unexpected data (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14643&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14643&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14651&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14651&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-media-player-architecture-speaker_source&quot;&gt;New Media Player Architecture (speaker_source)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The media player has been redesigned around a modular &lt;strong&gt;source-based architecture&lt;/strong&gt; to support the upcoming &lt;a href=&quot;https://www.sendspin-audio.com/spec/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Sendspin&lt;/a&gt; multi-room audio protocol, thanks to &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;. The new &lt;a href=&quot;https://esphome.io/components/media_player/speaker_source&quot;&gt;speaker_source&lt;/a&gt; media player replaces the monolithic speaker media player with a flexible orchestrator that routes audio from pluggable &lt;a href=&quot;https://esphome.io/components/media_source&quot;&gt;media_source&lt;/a&gt; components.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pluggable media sources&lt;/strong&gt; - Audio sources are separate components that plug into the media player. This release includes the &lt;a href=&quot;https://esphome.io/components/media_source/audio_file&quot;&gt;audio_file&lt;/a&gt; media source for embedded firmware files, with HTTP streams and Sendspin sources planned for future releases&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dual pipeline support&lt;/strong&gt; - Separate media and announcement pipelines with independent speakers, formats, and sources, allowing announcements to play alongside music&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full playlist management&lt;/strong&gt; - Enqueue, next/previous track navigation, repeat (off/one/all), and shuffle with Fisher-Yates algorithm&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volume persistence&lt;/strong&gt; - Volume and mute state are saved across reboots with configurable min/max/increment&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expanded media player commands&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;next&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;previous&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;repeat_all&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;shuffle&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;unshuffle&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;group_join&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;clear_playlist&lt;/code&gt; actions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12258&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12258&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&quot;https://esphome.io/components/audio_file&quot;&gt;audio_file&lt;/a&gt; component lets you embed audio files (local or from URLs) directly into firmware for instant playback without network access. Files are decoded directly from flash, saving two buffer copies compared to the previous approach.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;audio-playback-improvements&quot;&gt;Audio Playback Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ogg Opus codec support&lt;/strong&gt; - The new microOpus library enables decoding Ogg Opus files, completing the codec lineup alongside FLAC and MP3 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13967&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13967&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smarter codec builds&lt;/strong&gt; - Only the codecs your configuration actually requires are built. The &lt;code dir=&quot;auto&quot;&gt;speaker_source&lt;/code&gt; media player does this automatically, while the &lt;code dir=&quot;auto&quot;&gt;speaker&lt;/code&gt; media player’s &lt;code dir=&quot;auto&quot;&gt;codec_support_enabled&lt;/code&gt; option now defaults to &lt;code dir=&quot;auto&quot;&gt;needed&lt;/code&gt; (users streaming arbitrary URLs should set &lt;code dir=&quot;auto&quot;&gt;codec_support_enabled: all&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speaker media player on/off&lt;/strong&gt; - The speaker media player now supports explicit on/off power control (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9295&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#9295&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;other-notable-features&quot;&gt;Other Notable Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;!extend&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;!remove&lt;/code&gt; on all list components&lt;/strong&gt; - A long-awaited feature: &lt;code dir=&quot;auto&quot;&gt;!extend&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;!remove&lt;/code&gt; now work on any list-based config entry (like &lt;code dir=&quot;auto&quot;&gt;external_components&lt;/code&gt;) even when the component schema doesn’t declare an &lt;code dir=&quot;auto&quot;&gt;id&lt;/code&gt; field, thanks to &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14682&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14682&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BLE connection parameters API&lt;/strong&gt; - Bluetooth proxies can now adjust connection intervals on connected BLE devices, allowing integrations like yalexs-ble to switch from fast intervals (~7.5ms) to slow ones (~1000ms) after connection, significantly reducing battery drain on “Always Connected” devices like Yale/August locks (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14577&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14577&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safe mode explicit boot success&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;safe_mode.mark_boot_ok&lt;/code&gt; action lets you explicitly notify safe mode that a boot is successful, solving the issue for deep sleep devices that boot and sleep within the safe mode timeout window (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14306&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14306&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CC1101 runtime configuration&lt;/strong&gt; - New actions to change frequency, modulation type, symbol rate, filter bandwidth, and other CC1101 radio settings on the fly (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14141&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14141&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 BLE authentication&lt;/strong&gt; - Configurable &lt;code dir=&quot;auto&quot;&gt;min_key_size&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;max_key_size&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;auth_req_mode&lt;/code&gt; for BLE security (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7138&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#7138&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration sensor set action&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;set&lt;/code&gt; method to publish and save a specific value to an integration sensor (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13316&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13316&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LPS22DF pressure sensor&lt;/strong&gt; - Support for the DF variant of the LPS22 pressure sensor family (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14397&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14397&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenThread TX power&lt;/strong&gt; - Configurable transmit power for OpenThread radios (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14200&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14200&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP request TLS buffer&lt;/strong&gt; - Configurable TLS buffer size on ESP8266, required for modern web servers that send 16KB TLS records (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14009&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14009&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART debug prefix&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;debug_prefix&lt;/code&gt; option to distinguish multiple UARTs in log output (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14525&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14525&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART flush result&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;flush()&lt;/code&gt; method now returns a result indicating success/timeout, with configurable timeout via YAML (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14608&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14608&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Version text sensor &lt;code dir=&quot;auto&quot;&gt;hide_hash&lt;/code&gt;&lt;/strong&gt; - Option to restore the pre-2026.1 version string format without the git hash (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14251&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14251&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GT911 interrupt via IO expander&lt;/strong&gt; - Touch interrupt line can now be routed through an IO expander (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14358&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14358&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 hosted SDIO clock&lt;/strong&gt; - Configurable SDIO clock frequency for &lt;code dir=&quot;auto&quot;&gt;esp32_hosted&lt;/code&gt; WiFi (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14319&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14319&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nextion configurable HTTP parameters&lt;/strong&gt; - New options for TFT upload timeout, follow redirects, and useragent (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14234&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14234&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART mock integration tests&lt;/strong&gt; - New integration test infrastructure enables automated testing of serial protocol components. The LD24xx family (LD2410, LD2412, LD2420, LD2450) and Modbus received comprehensive tests along with bug fixes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14377&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14377&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14448&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14448&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14471&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14471&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14611&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14611&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14395&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14395&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;thank-you-contributors&quot;&gt;Thank You, Contributors&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release includes 480 pull requests from over 50 contributors. A huge thank you to everyone who made 2026.3.0 possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt; - 101 PRs including an 86-fix correctness sweep across 100+ components, ESP32-C5 dual-band WiFi, and the &lt;code dir=&quot;auto&quot;&gt;!extend&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;!remove&lt;/code&gt; config enhancement&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt; - 20 PRs building the new media player architecture, Ogg Opus codec support, audio file component, and speaker pipeline infrastructure&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt; - 11 PRs bringing the nRF52 platform forward with BLE OTA (zephyr_mcumgr), crash debugging, and USB CDC support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/schdro&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@schdro&lt;/a&gt; - 8 PRs improving the OpenThread stack with TX power configuration, connection caching, and build optimizations&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt; - 8 PRs including the new serial proxy component, mixer speaker debounce, and UART flush improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ximex&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ximex&lt;/a&gt; - 7 PRs with code quality improvements across rtttl, ESP32 pin validation, and time handling&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; - 6 PRs including the ESP32-P4 PSRAM execution, const cleanup, and USB UART fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt; - 4 PRs improving OpenThread with connection state caching and code quality&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt; - 3 PRs adding UART debug prefix, ESP LDO channel support, and USB UART chip detection&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/diorcety&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@diorcety&lt;/a&gt; - 3 PRs with cross-compiler compatibility and ESP-IDF build fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/exciton&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@exciton&lt;/a&gt; - 2 PRs creating the Modbus integration test infrastructure and fixing timing bugs&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pgolawsk&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@pgolawsk&lt;/a&gt; - 2 PRs adding WeAct 3-color e-paper support and safe_mode improvements&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt; - 2 PRs improving Nextion TFT upload error handling and configurable HTTP parameters&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/AndreKR&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@AndreKR&lt;/a&gt; - 2 PRs improving ESP8266 TLS logging and configurable buffer sizes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mikelawrence&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mikelawrence&lt;/a&gt; - 2 PRs refactoring Sensirion sensor library shared code&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/CFlix&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@CFlix&lt;/a&gt; - 2 PRs including the new dew point sensor component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Rapsssito&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Rapsssito&lt;/a&gt; - 2 PRs for MQTT precision and BLE server testing&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mebner86&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mebner86&lt;/a&gt; - the new SEN6x sensor component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/joshuasing&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@joshuasing&lt;/a&gt; - the new HDC302x sensor component&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mcassaniti&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mcassaniti&lt;/a&gt; - explicit boot success marking for safe mode&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rwagoner&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwagoner&lt;/a&gt; - climate preset, fan mode, and humidity support for web server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also thank you to &lt;a href=&quot;https://github.com/ademuri&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ademuri&lt;/a&gt;, &lt;a href=&quot;https://github.com/anunayk&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@anunayk&lt;/a&gt;, &lt;a href=&quot;https://github.com/bharvey88&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bharvey88&lt;/a&gt;, &lt;a href=&quot;https://github.com/ccutrer&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ccutrer&lt;/a&gt;, &lt;a href=&quot;https://github.com/corneliusludmann&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@corneliusludmann&lt;/a&gt;, &lt;a href=&quot;https://github.com/deirdreobyrne&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@deirdreobyrne&lt;/a&gt;, &lt;a href=&quot;https://github.com/edenhaus&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edenhaus&lt;/a&gt;, &lt;a href=&quot;https://github.com/Gnuspice&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Gnuspice&lt;/a&gt;, &lt;a href=&quot;https://github.com/gtjoseph&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@gtjoseph&lt;/a&gt;, &lt;a href=&quot;https://github.com/jamesmyatt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jamesmyatt&lt;/a&gt;, &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;, &lt;a href=&quot;https://github.com/JiriPrchal&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@JiriPrchal&lt;/a&gt;, &lt;a href=&quot;https://github.com/jpeletier&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jpeletier&lt;/a&gt;, &lt;a href=&quot;https://github.com/LinoSchmidt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@LinoSchmidt&lt;/a&gt;, &lt;a href=&quot;https://github.com/lwratten&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@lwratten&lt;/a&gt;, &lt;a href=&quot;https://github.com/lyubomirtraykov&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@lyubomirtraykov&lt;/a&gt;, &lt;a href=&quot;https://github.com/mahumpula&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mahumpula&lt;/a&gt;, &lt;a href=&quot;https://github.com/mback2k&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mback2k&lt;/a&gt;, &lt;a href=&quot;https://github.com/melak&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@melak&lt;/a&gt;, &lt;a href=&quot;https://github.com/nagyrobi&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@nagyrobi&lt;/a&gt;, &lt;a href=&quot;https://github.com/netixx&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@netixx&lt;/a&gt;, &lt;a href=&quot;https://github.com/oarcher&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@oarcher&lt;/a&gt;, &lt;a href=&quot;https://github.com/PedanticAvenger&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@PedanticAvenger&lt;/a&gt;, &lt;a href=&quot;https://github.com/puddly&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@puddly&lt;/a&gt;, &lt;a href=&quot;https://github.com/RAR&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@RAR&lt;/a&gt;, &lt;a href=&quot;https://github.com/rsre&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rsre&lt;/a&gt;, &lt;a href=&quot;https://github.com/sredman&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@sredman&lt;/a&gt;, &lt;a href=&quot;https://github.com/sxtfov&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@sxtfov&lt;/a&gt;, &lt;a href=&quot;https://github.com/Szpadel&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Szpadel&lt;/a&gt;, &lt;a href=&quot;https://github.com/tuct&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tuct&lt;/a&gt;, &lt;a href=&quot;https://github.com/tvogel&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tvogel&lt;/a&gt;, and &lt;a href=&quot;https://github.com/whitty&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@whitty&lt;/a&gt; for their contributions, and to everyone who reported issues, tested pre-releases, and helped in the community.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Most users can update without any configuration changes. The items below are grouped by whether you need to take action.&lt;/p&gt;

&lt;div&gt;&lt;h3 id=&quot;action-required-if-you-use-these-components&quot;&gt;Action required (if you use these components)&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpenTherm&lt;/strong&gt;: The deprecated &lt;code dir=&quot;auto&quot;&gt;opentherm_version&lt;/code&gt; config option has been removed. Use &lt;code dir=&quot;auto&quot;&gt;opentherm_version_controller&lt;/code&gt; instead &lt;a href=&quot;https://github.com/esphome/esphome/pull/14103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14103&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32-P4&lt;/strong&gt;: The default board now targets production rev3+ silicon instead of engineering samples. If you have a pre-rev3 ESP32-P4 dev kit, add &lt;code dir=&quot;auto&quot;&gt;engineering_sample: true&lt;/code&gt; to your &lt;code dir=&quot;auto&quot;&gt;esp32:&lt;/code&gt; config &lt;a href=&quot;https://github.com/esphome/esphome/pull/14139&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14139&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speaker Media Player&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;codec_support_enabled&lt;/code&gt; option now defaults to &lt;code dir=&quot;auto&quot;&gt;needed&lt;/code&gt; instead of building all codecs. If you stream audio via hardcoded URLs (not through Home Assistant), set &lt;code dir=&quot;auto&quot;&gt;codec_support_enabled: all&lt;/code&gt; to restore the previous behavior &lt;a href=&quot;https://github.com/esphome/esphome/pull/13967&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13967&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SGP30&lt;/strong&gt;: Fixed serial number truncation from 48-bit to 24-bit. This changes the preference hash, so existing stored baselines will no longer be found. Plan for up to 12 hours of recalibration &lt;a href=&quot;https://github.com/esphome/esphome/pull/14478&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14478&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;/strong&gt;: If you have lambdas calling &lt;code dir=&quot;auto&quot;&gt;::mktime()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;::strftime()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;setenv(&quot;TZ&quot;, ...)&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;tzset()&lt;/code&gt; directly, update them to use ESPHome’s &lt;a href=&quot;https://esphome.io/components/time/&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;ESPTime&lt;/code&gt; API&lt;/a&gt;. Most users are unaffected, and &lt;code dir=&quot;auto&quot;&gt;::localtime()&lt;/code&gt; continues to work &lt;a href=&quot;https://github.com/esphome/esphome/pull/13635&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13635&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPIO Binary Sensor implicit debounce gone&lt;/strong&gt;: The main loop now wakes immediately from inside the GPIO ISR (&lt;a href=&quot;https://github.com/esphome/esphome/pull/14383&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14383&lt;/a&gt;) instead of waiting out the &lt;code dir=&quot;auto&quot;&gt;select()&lt;/code&gt; timeout. Configs that already follow the &lt;a href=&quot;https://esphome.io/components/binary_sensor/gpio#debouncing-values&quot;&gt;debouncing values&lt;/a&gt; guidance and have a filter on their physical button are unaffected. Configs that skipped it were getting accidental debouncing from the slow loop poll cadence; mechanical switch bounce now reaches downstream automations, so timing-based triggers (&lt;code dir=&quot;auto&quot;&gt;on_multi_click&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_click&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;on_double_click&lt;/code&gt;, edge counters in &lt;code dir=&quot;auto&quot;&gt;on_press&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;on_release&lt;/code&gt;) on raw physical buttons may need an explicit &lt;code dir=&quot;auto&quot;&gt;delayed_on_off: 20ms&lt;/code&gt; filter (or &lt;code dir=&quot;auto&quot;&gt;delayed_on&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;delayed_off&lt;/code&gt;) added to the &lt;code dir=&quot;auto&quot;&gt;gpio&lt;/code&gt; binary_sensor’s &lt;code dir=&quot;auto&quot;&gt;filters:&lt;/code&gt; list. The matcher logic itself is unchanged. &lt;a href=&quot;https://github.com/esphome/esphome/issues/15323&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15323&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;most-users-unaffected&quot;&gt;Most users unaffected&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RP2040&lt;/strong&gt;: The arduino-pico framework has been updated from 3.9.4 to 5.5.0 (pico-sdk 2.0, GCC 14). Most user configs are unaffected, but external components targeting RP2040 may need updates &lt;a href=&quot;https://github.com/esphome/esphome/pull/14328&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14328&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP8266/RP2040&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;printf&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;vprintf&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;fprintf&lt;/code&gt; are now wrapped with lightweight stubs to save flash. External components that need full FILE*-based printf can set &lt;code dir=&quot;auto&quot;&gt;enable_full_printf: true&lt;/code&gt; under their platform config &lt;a href=&quot;https://github.com/esphome/esphome/pull/14621&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14621&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14622&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14622&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nextion&lt;/strong&gt;: The TFT upload HTTP timeout default changed from 15s to 4.5s to prevent watchdog resets. Users with slow connections can increase it via the new &lt;code dir=&quot;auto&quot;&gt;tft_upload_http_timeout&lt;/code&gt; option &lt;a href=&quot;https://github.com/esphome/esphome/pull/14234&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14234&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenThread&lt;/strong&gt;: The log level is now statically set based on the &lt;code dir=&quot;auto&quot;&gt;esp32.framework.log_level&lt;/code&gt; setting instead of being dynamic &lt;a href=&quot;https://github.com/esphome/esphome/pull/14456&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14456&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Micronova&lt;/strong&gt;: A command queue has been added for read and write requests. Write requests are now prioritized, and read requests are deduplicated. This fixes silently ignored write requests and incomplete sensor updates &lt;a href=&quot;https://github.com/esphome/esphome/pull/12268&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12268&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;/strong&gt;: The libc timezone infrastructure has been replaced with a lightweight custom parser, saving ~9.5KB flash on ESP32 and ~2% RAM on ESP8266. The &lt;code dir=&quot;auto&quot;&gt;dump_config()&lt;/code&gt; output now shows human-readable timezone info (e.g., &lt;code dir=&quot;auto&quot;&gt;UTC-6:00 (DST UTC-5:00)&lt;/code&gt;) instead of raw POSIX strings &lt;a href=&quot;https://github.com/esphome/esphome/pull/13635&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13635&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Icons (ESP8266)&lt;/strong&gt;: Icon strings are now stored in PROGMEM (flash), with a maximum length of 63 characters. All standard &lt;code dir=&quot;auto&quot;&gt;mdi:*&lt;/code&gt; icons are well under this limit &lt;a href=&quot;https://github.com/esphome/esphome/pull/14437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14437&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Device Classes (ESP8266)&lt;/strong&gt;: Device class strings are similarly moved to PROGMEM &lt;a href=&quot;https://github.com/esphome/esphome/pull/14443&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14443&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Light&lt;/strong&gt;: Lambdas calling &lt;code dir=&quot;auto&quot;&gt;set_effect(0)&lt;/code&gt; to disable effects by integer index will get an ambiguous overload error. Use &lt;code dir=&quot;auto&quot;&gt;set_effect(uint32_t{0})&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;set_effect(&quot;None&quot;)&lt;/code&gt; instead &lt;a href=&quot;https://github.com/esphome/esphome/pull/14732&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14732&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;undocumented-api-changes&quot;&gt;Undocumented API Changes&lt;/h3&gt;&lt;/div&gt;

&lt;p&gt;These are changes to &lt;strong&gt;unstable, undocumented&lt;/strong&gt; C++ APIs that may affect users who write lambdas or maintain external components. These APIs are not documented on &lt;a href=&quot;https://esphome.io&quot;&gt;esphome.io&lt;/a&gt; and are &lt;strong&gt;not part of the public API&lt;/strong&gt; — they may change at any time without notice. Only APIs documented on &lt;a href=&quot;https://esphome.io&quot;&gt;esphome.io&lt;/a&gt; are considered stable. If you depend on these internals, you do so at your own risk. We list them here as a courtesy.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;EntityBase&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;set_name()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_icon()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_device_class()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_unit_of_measurement()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_internal()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_disabled_by_default()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;set_entity_category()&lt;/code&gt; have been removed and packed into the existing &lt;code dir=&quot;auto&quot;&gt;configure_entity_()&lt;/code&gt; call. &lt;code dir=&quot;auto&quot;&gt;set_device()&lt;/code&gt; is renamed to &lt;code dir=&quot;auto&quot;&gt;set_device_()&lt;/code&gt; and made protected. These were codegen-only setters — calling them at runtime was unsafe and could silently corrupt state or crash the device (&lt;a href=&quot;https://en.wikipedia.org/wiki/Undefined_behavior&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;undefined behavior&lt;/a&gt;). &lt;a href=&quot;https://github.com/esphome/esphome/pull/14564&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14564&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14171&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14171&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14437&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14443&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14443&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;/strong&gt;: The libc functions &lt;code dir=&quot;auto&quot;&gt;localtime()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;localtime_r()&lt;/code&gt; are overridden on embedded platforms to use ESPHome’s custom timezone implementation. The &lt;code dir=&quot;auto&quot;&gt;setenv(&quot;TZ&quot;, ...)&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;tzset()&lt;/code&gt; path is no longer used internally. See the breaking changes section above for lambda migration guidance. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13635&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13635&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API ProtoMessage&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;encode()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;calculate_size()&lt;/code&gt; are no longer virtual. &lt;code dir=&quot;auto&quot;&gt;ProtoSize&lt;/code&gt; class converted from accumulator-object API to pure static methods. Lambdas calling &lt;code dir=&quot;auto&quot;&gt;calculate_size()&lt;/code&gt; should now call it directly on the message (returns &lt;code dir=&quot;auto&quot;&gt;uint32_t&lt;/code&gt; instead of populating a &lt;code dir=&quot;auto&quot;&gt;ProtoSize&lt;/code&gt; object). &lt;a href=&quot;https://github.com/esphome/esphome/pull/14449&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14449&lt;/a&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Before&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ProtoSize s;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;calculate_size&lt;/span&gt;&lt;span&gt;(s);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; size &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get_size&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// After&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;uint32_t&lt;/span&gt;&lt;span&gt; size &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;calculate_size&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIServer&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;is_connected(bool state_subscription_only)&lt;/code&gt; overload removed. Use &lt;code dir=&quot;auto&quot;&gt;is_connected()&lt;/code&gt; (no args, inlined) for the common path, or &lt;code dir=&quot;auto&quot;&gt;is_connected_with_state_subscription()&lt;/code&gt; for the rare state-subscription-only check. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14574&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14574&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OTA&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;OTABackend&lt;/code&gt; abstract base class has been removed. Use &lt;code dir=&quot;auto&quot;&gt;auto&lt;/code&gt; for local variables from &lt;code dir=&quot;auto&quot;&gt;make_ota_backend()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;ota::OTABackendPtr&lt;/code&gt; for member variables. Include &lt;code dir=&quot;auto&quot;&gt;ota_backend_factory.h&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;ota_backend.h&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14473&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14473&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenThread&lt;/strong&gt;: The OT console (&lt;code dir=&quot;auto&quot;&gt;CONFIG_OPENTHREAD_CONSOLE_ENABLE&lt;/code&gt;) and OT diagnostics (&lt;code dir=&quot;auto&quot;&gt;CONFIG_OPENTHREAD_DIAG&lt;/code&gt;) are now disabled by default, saving up to ~22KB flash. Custom lambdas using the OT console or diagnostics C API will need to re-enable these via sdkconfig. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14390&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14390&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14399&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14399&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ByteBuffer&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;put_uint24(value, offset)&lt;/code&gt; was writing 4 bytes instead of 3, corrupting the adjacent byte. Lambdas relying on the old (buggy) behavior may see different results. &lt;a href=&quot;https://github.com/esphome/esphome/pull/14555&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14555&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;div&gt;&lt;h4 id=&quot;devirtualization&quot;&gt;Devirtualization&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Several core virtual interfaces have been replaced with compile-time dispatch for performance. External components that override or depend on the virtual dispatch may need updates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Component&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;call_loop()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;mark_failed()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;call_dump_config()&lt;/code&gt; devirtualized &lt;a href=&quot;https://github.com/esphome/esphome/pull/14083&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14083&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14355&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14355&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logger&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;LogListener&lt;/code&gt; virtual interface replaced with &lt;code dir=&quot;auto&quot;&gt;LogCallback&lt;/code&gt; struct &lt;a href=&quot;https://github.com/esphome/esphome/pull/14084&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14084&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Socket&lt;/strong&gt;: Socket abstraction layer devirtualized &lt;a href=&quot;https://github.com/esphome/esphome/pull/14398&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14398&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OTA backend&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;OTABackend&lt;/code&gt; abstract base class removed. Use &lt;code dir=&quot;auto&quot;&gt;ota::OTABackendPtr&lt;/code&gt; type alias and &lt;code dir=&quot;auto&quot;&gt;auto&lt;/code&gt; for &lt;code dir=&quot;auto&quot;&gt;make_ota_backend()&lt;/code&gt; return &lt;a href=&quot;https://github.com/esphome/esphome/pull/14473&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14473&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protobuf API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;encode()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;calculate_size()&lt;/code&gt; are now non-virtual on &lt;code dir=&quot;auto&quot;&gt;ProtoMessage&lt;/code&gt;. &lt;code dir=&quot;auto&quot;&gt;ProtoSize&lt;/code&gt; converted to static methods. &lt;code dir=&quot;auto&quot;&gt;send_message()&lt;/code&gt; is now templated and deduces &lt;code dir=&quot;auto&quot;&gt;MESSAGE_TYPE&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/14449&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14449&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;entity-api-changes&quot;&gt;Entity API changes&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Entity icon/device class API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_icon_ref()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_icon()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_device_class_ref()&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;get_device_class()&lt;/code&gt; deprecated on non-ESP8266, &lt;code dir=&quot;auto&quot;&gt;static_assert&lt;/code&gt; error on ESP8266. Use &lt;code dir=&quot;auto&quot;&gt;get_icon_to(std::span&amp;#x3C;char, MAX_ICON_LENGTH&gt;)&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;get_device_class_to(std::span&amp;#x3C;char, MAX_DEVICE_CLASS_LENGTH&gt;)&lt;/code&gt; instead &lt;a href=&quot;https://github.com/esphome/esphome/pull/14437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14437&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14443&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14443&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EntityBase setters&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;set_name()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_icon()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_device_class()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_unit_of_measurement()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_internal()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_disabled_by_default()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_entity_category()&lt;/code&gt; removed (now packed into &lt;code dir=&quot;auto&quot;&gt;configure_entity_()&lt;/code&gt;). &lt;code dir=&quot;auto&quot;&gt;set_device()&lt;/code&gt; renamed to &lt;code dir=&quot;auto&quot;&gt;set_device_()&lt;/code&gt; and made protected &lt;a href=&quot;https://github.com/esphome/esphome/pull/14564&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14564&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14171&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14171&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14437&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14443&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14443&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entity string properties&lt;/strong&gt;: Packed into PROGMEM-indexed &lt;code dir=&quot;auto&quot;&gt;uint8_t&lt;/code&gt; fields &lt;a href=&quot;https://github.com/esphome/esphome/pull/14171&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14171&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;type-and-container-changes&quot;&gt;Type and container changes&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;esphome::optional&lt;/strong&gt;: Replaced with &lt;code dir=&quot;auto&quot;&gt;std::optional&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/14368&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14368&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application name/friendly_name&lt;/strong&gt;: Changed from &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/14532&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14532&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;http_request headers&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;std::map&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;std::list&lt;/code&gt; replaced with &lt;code dir=&quot;auto&quot;&gt;std::vector&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/14024&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14024&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/14027&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14027&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SerializationBuffer&lt;/strong&gt;: New stack-first JSON serialization buffer &lt;a href=&quot;https://github.com/esphome/esphome/pull/13625&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13625&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;removed-deprecated-apis&quot;&gt;Removed deprecated APIs&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;i2c&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;stop&lt;/code&gt; parameter overloads and &lt;code dir=&quot;auto&quot;&gt;readv&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;writev&lt;/code&gt; methods removed &lt;a href=&quot;https://github.com/esphome/esphome/pull/14106&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14106&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 IDF components&lt;/strong&gt;: Deprecated &lt;code dir=&quot;auto&quot;&gt;add_idf_component()&lt;/code&gt; parameters removed &lt;a href=&quot;https://github.com/esphome/esphome/pull/14105&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14105&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;platform-and-component-changes&quot;&gt;Platform and component changes&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RP2040 framework&lt;/strong&gt;: arduino-pico 3.9.4 → 5.5.0 with pico-sdk 2.0. Key API renames: &lt;code dir=&quot;auto&quot;&gt;padsbank0_hw&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;pads_bank0_hw&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;SerialPIO::NOPIN&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;NOPIN&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/14328&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14328&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART flush()&lt;/strong&gt;: Return type changed from &lt;code dir=&quot;auto&quot;&gt;void&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;FlushResult&lt;/code&gt;. External components overriding &lt;code dir=&quot;auto&quot;&gt;flush()&lt;/code&gt; must update their signature &lt;a href=&quot;https://github.com/esphome/esphome/pull/14608&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14608&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;runtime_image&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;ImageFormat&lt;/code&gt; enum moved from &lt;code dir=&quot;auto&quot;&gt;esphome::online_image&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;esphome::runtime_image&lt;/code&gt;. &lt;code dir=&quot;auto&quot;&gt;OnlineImage&lt;/code&gt; constructor signature changed &lt;a href=&quot;https://github.com/esphome/esphome/pull/10212&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#10212&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;rx_full_threshold&lt;/code&gt; sentinel added to &lt;code dir=&quot;auto&quot;&gt;UARTComponent&lt;/code&gt;; timeout calculation changed for non-hardware UARTs. External modbus components may need update &lt;a href=&quot;https://github.com/esphome/esphome/pull/14614&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14614&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h4 id=&quot;registration-and-build-changes&quot;&gt;Registration and build changes&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;register_component&lt;/strong&gt;: Now protected, runtime checks removed &lt;a href=&quot;https://github.com/esphome/esphome/pull/14371&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14371&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;register_action&lt;/strong&gt;: Now requires explicit &lt;code dir=&quot;auto&quot;&gt;synchronous=&lt;/code&gt; parameter &lt;a href=&quot;https://github.com/esphome/esphome/pull/14606&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14606&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;build_info_data.h&lt;/strong&gt;: Moved out of &lt;code dir=&quot;auto&quot;&gt;application.h&lt;/code&gt; to fix incremental rebuilds &lt;a href=&quot;https://github.com/esphome/esphome/pull/14230&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14230&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;get_loop_priority&lt;/strong&gt;: Conditionally compiled with &lt;code dir=&quot;auto&quot;&gt;USE_LOOP_PRIORITY&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/14210&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#14210&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the &lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-3-1---march-23&quot;&gt;Release 2026.3.1 - March 23&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Bump aioesphomeapi from 44.5.2 to 44.6.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/14927&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14927&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Prevent double update task launch &lt;a href=&quot;https://github.com/esphome/esphome/pull/14910&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14910&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ble_client] Fix RSSI sensor reporting same value for all clients &lt;a href=&quot;https://github.com/esphome/esphome/pull/14939&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14939&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[openthread] Guard InstanceLock against uninitialized semaphore &lt;a href=&quot;https://github.com/esphome/esphome/pull/14940&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14940&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump aioesphomeapi from 44.6.0 to 44.6.1 &lt;a href=&quot;https://github.com/esphome/esphome/pull/14954&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14954&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[time] Fix lookup of top-level IANA timezone keys like UTC and GMT &lt;a href=&quot;https://github.com/esphome/esphome/pull/14952&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14952&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[logger] Fix ESP8266 crash with VERY_VERBOSE log level &lt;a href=&quot;https://github.com/esphome/esphome/pull/14980&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14980&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sdl] Fix get_width()/height() when rotation used &lt;a href=&quot;https://github.com/esphome/esphome/pull/14950&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14950&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Fix UART0 default pin IOMUX loopback on ESP32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/14978&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14978&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2450] Fix zone target counts including untracked ghost targets &lt;a href=&quot;https://github.com/esphome/esphome/pull/15026&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15026&lt;/a&gt; by &lt;a href=&quot;https://github.com/kroehre&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kroehre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bump aioesphomeapi from 44.6.1 to 44.6.2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/15027&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15027&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/dependabot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dependabot[bot]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Increase noise handshake timeout to 60s for slow WiFi environments &lt;a href=&quot;https://github.com/esphome/esphome/pull/15022&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15022&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix ESP8266 power_save_mode mapping (LIGHT/HIGH were swapped) &lt;a href=&quot;https://github.com/esphome/esphome/pull/15029&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15029&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; (breaking-change)&lt;/li&gt;
&lt;li&gt;[esp32_touch] Fix initial state never published when sensor untouched &lt;a href=&quot;https://github.com/esphome/esphome/pull/15032&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15032&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[web_server] Increase httpd task stack size to prevent stack overflow &lt;a href=&quot;https://github.com/esphome/esphome/pull/14997&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14997&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Add copy() method to StringRef for std::string compatibility &lt;a href=&quot;https://github.com/esphome/esphome/pull/15028&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15028&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[time] Fix timezone_offset() and recalc_timestamp_local() always returning UTC &lt;a href=&quot;https://github.com/esphome/esphome/pull/14996&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14996&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[analog_threshhold] add missing header &lt;a href=&quot;https://github.com/esphome/esphome/pull/15058&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15058&lt;/a&gt; by &lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mqtt] Rate-limit component resends to prevent task WDT on reconnect &lt;a href=&quot;https://github.com/esphome/esphome/pull/15061&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15061&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[light] Fix constant_brightness broken by gamma LUT refactor &lt;a href=&quot;https://github.com/esphome/esphome/pull/15048&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15048&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sht4x] Fix heater causing measurement jitter &lt;a href=&quot;https://github.com/esphome/esphome/pull/15030&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15030&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Fix RTL87xx compilation failure due to SUCCESS macro collision &lt;a href=&quot;https://github.com/esphome/esphome/pull/15054&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15054&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[light] Fix gamma LUT quantizing small brightness to zero &lt;a href=&quot;https://github.com/esphome/esphome/pull/15060&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15060&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ultrasonic] Fix ISR edge detection with debounce and trigger filtering &lt;a href=&quot;https://github.com/esphome/esphome/pull/15014&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15014&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[logger] Fix race condition in task log buffer initialization &lt;a href=&quot;https://github.com/esphome/esphome/pull/15071&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15071&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[pmsx003] Keep active-mode reads aligned &lt;a href=&quot;https://github.com/esphome/esphome/pull/14832&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14832&lt;/a&gt; by &lt;a href=&quot;https://github.com/jkoelker&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jkoelker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-3-2---april-1&quot;&gt;Release 2026.3.2 - April 1&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[time] Point to valid IANA timezone list on validation failure &lt;a href=&quot;https://github.com/esphome/esphome/pull/15110&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15110&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix roaming attempt counter reset on disconnect during scan &lt;a href=&quot;https://github.com/esphome/esphome/pull/15099&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15099&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Reduce ESP8266 roaming scan dwell time to match ESP32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/15127&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15127&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sx127x] Fix FIFO read corruption &lt;a href=&quot;https://github.com/esphome/esphome/pull/15114&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15114&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[datetime] Fix state_as_esptime() returning invalid timestamp &lt;a href=&quot;https://github.com/esphome/esphome/pull/15128&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15128&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix roaming counter reset from delayed disconnect and successful retry &lt;a href=&quot;https://github.com/esphome/esphome/pull/15126&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15126&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Filter fast_connect by band_mode and use background scan for roaming &lt;a href=&quot;https://github.com/esphome/esphome/pull/15152&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15152&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Fix debug callback missing peeked byte and reading past end &lt;a href=&quot;https://github.com/esphome/esphome/pull/15169&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15169&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sgp4x] Fix NOx index_offset default (should be 1, not 100) &lt;a href=&quot;https://github.com/esphome/esphome/pull/15212&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15212&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_server] Fix set_value action with static data lists &lt;a href=&quot;https://github.com/esphome/esphome/pull/15285&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15285&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp8266] Add enable_scanf_float option &lt;a href=&quot;https://github.com/esphome/esphome/pull/15284&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15284&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; (new-feature)&lt;/li&gt;
&lt;li&gt;[thermostat] Fix stale &lt;code dir=&quot;auto&quot;&gt;max_runtime_exceeded&lt;/code&gt; causing spurious supplemental heating/cooling &lt;a href=&quot;https://github.com/esphome/esphome/pull/15274&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15274&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[haier] Fix hOn half-degree temperature setting &lt;a href=&quot;https://github.com/esphome/esphome/pull/15312&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15312&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[tormatic] Fix UART stream desync on ESP32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/15337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15337&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] fix baud rate not applied on &lt;code dir=&quot;auto&quot;&gt;load_settings()&lt;/code&gt; for ESP32 (IDF) &lt;a href=&quot;https://github.com/esphome/esphome/pull/15341&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15341&lt;/a&gt; by &lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mixer] Fix memory leak in mixer task on stop/start cycles &lt;a href=&quot;https://github.com/esphome/esphome/pull/15185&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15185&lt;/a&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_tracker] Restart BLE scan after OTA failure &lt;a href=&quot;https://github.com/esphome/esphome/pull/15308&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15308&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-3-3---april-7&quot;&gt;Release 2026.3.3 - April 7&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[nextion] Fix queue age check using inconsistent time sources &lt;a href=&quot;https://github.com/esphome/esphome/pull/15317&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15317&lt;/a&gt; by &lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[online_image] Clear LVGL dsc when image size changes. &lt;a href=&quot;https://github.com/esphome/esphome/pull/15360&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15360&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Clean build when sdkconfig options change &lt;a href=&quot;https://github.com/esphome/esphome/pull/15439&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#15439&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.3.0/&quot;&gt;full 2026.3.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2026.2.0: Faster builds, leaner runtime</title><link>https://esphome.io/blog/2026/02/18/esphome-2026-2/</link><guid isPermaLink="true">https://esphome.io/blog/2026/02/18/esphome-2026-2/</guid><description>ESPHome 2026.2.0 is a performance and stability release: faster ESP32 builds, smaller firmware, lower CPU usage, three new components, and security hardening.</description><pubDate>Wed, 18 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/bmp581/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bmp581.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;BMP5​8​1​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/sy6970/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/sy6970.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;SY6​9​7​0​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/ch423/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ch423.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;CH4​2​3​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/dlms_meter/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/dlms_meter.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;DLMS ​Meter&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.2.0 is a performance and stability release. The focus is on making your devices compile faster, run leaner, and stay reliable over months of uptime.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Faster builds, smaller firmware.&lt;/strong&gt; ESP32 Arduino builds compile 36% faster and produce 44% less flash and 50% less static RAM. ESP-IDF compiles are ~22% faster. A streamlined certificate bundle saves another 51KB of flash.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;More stable, more responsive devices.&lt;/strong&gt; CPU usage is down across the board: the BLE tracker loop uses ~85% less CPU, MQTT consolidation saves ~6.5% total device CPU, and the scheduler is 25% smaller. Unnecessary memory allocations have been eliminated from dozens of components, and ESP8266 devices recover significant RAM by moving strings to flash.&lt;/p&gt;
&lt;p&gt;This release also introduces 3 new components (DLMS smart meter, CH423 I/O expander, SY6970 battery management), adds 7 new display models including ESP32-P4 Waveshare panels, expands the Zigbee platform, and hardens security with constant-time authentication and cryptographic random generation.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;bmp581&lt;/code&gt;, update your configuration to use &lt;code dir=&quot;auto&quot;&gt;bmp581_i2c&lt;/code&gt; as the platform&lt;/li&gt;
&lt;li&gt;If you use &lt;code dir=&quot;auto&quot;&gt;on_open&lt;/code&gt; in cover automations, rename it to &lt;code dir=&quot;auto&quot;&gt;on_opened&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you have DSMR &lt;code dir=&quot;auto&quot;&gt;fw_core_version&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;fw_module_version&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;sensor:&lt;/code&gt;, move them to &lt;code dir=&quot;auto&quot;&gt;text_sensor:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you call Arduino library APIs directly in lambdas (e.g., &lt;code dir=&quot;auto&quot;&gt;Preferences&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;WiFi&lt;/code&gt;), add them to &lt;code dir=&quot;auto&quot;&gt;esphome: libraries:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you connect to HTTPS servers using uncommon CAs, add &lt;code dir=&quot;auto&quot;&gt;use_full_certificate_bundle: true&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;esp32: framework: advanced:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you use BL0942 sensors, expect readings to change after recalibration to match corrected reference values&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;esp32-build-size-and-compile-time-optimizations&quot;&gt;ESP32 Build Size and Compile Time Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESP32 builds are faster and produce smaller firmware in this release, meaning shorter compile times and more room on your devices.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Improvement&lt;/th&gt;&lt;th&gt;Savings&lt;/th&gt;&lt;th&gt;Details&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Arduino selective compilation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13623&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;36% faster builds, 44% less flash, 50% less static RAM&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Unused Arduino libraries are no longer compiled or linked&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ESP-IDF component exclusion (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13610&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13610&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/13664&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13664&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;~22% faster ESP-IDF compiles&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Unused ESP-IDF components are excluded at build time instead of compiled and discarded by the linker&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Streamlined certificate bundle (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13574&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13574&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;~51KB flash saved&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Default switched to Common CAs (~99% of websites); full bundle available via config&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Skip precompiled Arduino libs (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13775&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13775&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;~40% faster first build, ~2GB disk saved&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Stub replaces the ~270MB precompiled library download that isn’t needed when building from source&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;sdkconfig defaults (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13611&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13611&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;Additional flash savings&lt;/td&gt;&lt;td&gt;Unused ESP-IDF features (debug stubs, PKCS#7, FAT) disabled by default&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Arduino numbers measured on an ESP32 Arduino build comparing before and after this release. ESP-IDF compile time measured across multiple optimization PRs. Actual savings depend on your configuration.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; ESPHome now only compiles the parts of Arduino and ESP-IDF that your configuration actually uses. Built-in components automatically re-enable the libraries they need, so most users get these savings with zero configuration changes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Who benefits most?&lt;/strong&gt; Everyone on ESP32. If your firmware was close to flash limits, this may free enough space to add more components. If you were waiting on long compiles, expect noticeably faster builds. Users on ESP-IDF see the ~22% compile time improvement automatically. Arduino users see all three improvements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;External components that call &lt;code dir=&quot;auto&quot;&gt;cg.add_library()&lt;/code&gt; in their code generation work automatically. If you use external components or lambdas that rely on Arduino libraries without declaring them, you can add them to &lt;code dir=&quot;auto&quot;&gt;esphome: libraries:&lt;/code&gt;. See &lt;a href=&quot;#breaking-changes&quot;&gt;Breaking Changes&lt;/a&gt; for details.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;runtime-memory-and-performance&quot;&gt;Runtime Memory and Performance&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Your devices should be more responsive and more stable after this update. Across all platforms, we’ve reduced CPU usage, freed up RAM, and eliminated sources of memory fragmentation that can cause crashes after weeks or months of uptime.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;esp8266-ram-recovery&quot;&gt;ESP8266 RAM Recovery&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;ESP8266 devices have only 80KB of RAM, so every byte matters. This release moves constant strings and lookup tables from RAM to flash across &lt;strong&gt;19+ components&lt;/strong&gt;, freeing up heap for actual device operation. Components updated include &lt;a href=&quot;https://esphome.io/components/web_server&quot;&gt;web_server&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13315&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13315&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/light&quot;&gt;light&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13314&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13314&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/mqtt&quot;&gt;mqtt&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13546&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13546&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/wifi&quot;&gt;wifi&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13349&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13349&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/debug&quot;&gt;debug&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13352&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13352&lt;/a&gt;), and &lt;strong&gt;13 more&lt;/strong&gt; via a new flash-based string table pattern (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13659&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13659&lt;/a&gt;) applied to &lt;a href=&quot;https://esphome.io/components/uart&quot;&gt;uart&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13805&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13805&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/sprinkler&quot;&gt;sprinkler&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13806&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13806&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/display/ssd1306&quot;&gt;ssd1306&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13814&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13814&lt;/a&gt;), and others.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;long-term-stability&quot;&gt;Long-Term Stability&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Devices that run for months can crash when repeated memory allocations fragment the heap. This release eliminates unnecessary runtime memory allocations across the codebase, including &lt;a href=&quot;https://esphome.io/components/api&quot;&gt;api&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13399&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13399&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/mqtt&quot;&gt;mqtt&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13434&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13434&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/climate/thermostat&quot;&gt;thermostat&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13692&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13692&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/sprinkler&quot;&gt;sprinkler&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13705&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13705&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/voice_assistant&quot;&gt;voice_assistant&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13689&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13689&lt;/a&gt;), and many others. On ESP8266, format strings are also moved to flash as part of these changes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13258&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13258&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;uart-batch-reads&quot;&gt;UART Batch Reads&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;16 UART-based components&lt;/strong&gt; now read all available serial data at once instead of one byte per loop, reducing CPU overhead. Updated components include &lt;a href=&quot;https://esphome.io/components/modbus&quot;&gt;modbus&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13822&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13822&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/display/nextion&quot;&gt;nextion&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13823&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13823&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/tuya&quot;&gt;tuya&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13827&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13827&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/sensor/ld2410&quot;&gt;ld2410&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13820&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13820&lt;/a&gt;), &lt;a href=&quot;https://esphome.io/components/sensor/dsmr&quot;&gt;dsmr&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13826&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13826&lt;/a&gt;), and &lt;a href=&quot;https://esphome.io/components/sensor/ld2450&quot;&gt;ld2450&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13818&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13818&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;cpu-and-loop-optimizations&quot;&gt;CPU and Loop Optimizations&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://esphome.io/components/esp32_ble_tracker&quot;&gt;esp32_ble_tracker&lt;/a&gt; loop uses &lt;strong&gt;~85% less CPU&lt;/strong&gt; thanks to state change tracking (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13337&lt;/a&gt;). Components like &lt;a href=&quot;https://esphome.io/components/binary_sensor/status&quot;&gt;status&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13342&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13342&lt;/a&gt;) and &lt;a href=&quot;https://esphome.io/components/globals&quot;&gt;globals&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13345&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13345&lt;/a&gt;) no longer run every loop iteration. The &lt;a href=&quot;https://esphome.io/components/api&quot;&gt;api&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13901&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13901&lt;/a&gt;) and core loop (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13900&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13900&lt;/a&gt;) were also tightened up, and &lt;a href=&quot;https://esphome.io/components/mdns&quot;&gt;mDNS&lt;/a&gt; polling was throttled on ESP8266 and RP2040 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13917&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13917&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;scheduler-improvements&quot;&gt;Scheduler Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The scheduler runs on every device and drives all timers and intervals. This release makes it smaller and more efficient: the core timer code is &lt;strong&gt;25% smaller&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13899&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13899&lt;/a&gt;), memory allocations were removed from cleanup operations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13837&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13837&lt;/a&gt;), and flash usage was reduced (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13214&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13214&lt;/a&gt;). Timer IDs are now type-safe to prevent collisions between components (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13882&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13882&lt;/a&gt;), and the &lt;code dir=&quot;auto&quot;&gt;set_retry&lt;/code&gt; API was deprecated in favor of &lt;code dir=&quot;auto&quot;&gt;set_interval&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;set_timeout&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13845&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13845&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;mqtt-optimizations&quot;&gt;MQTT Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;If you use MQTT, your devices will use noticeably less CPU and memory. Previously, every MQTT entity ran its own loop and rebuilt topic strings every iteration, causing thousands of unnecessary memory allocations per minute. This has been consolidated so entities are processed centrally (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13356&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13356&lt;/a&gt;), saving roughly &lt;strong&gt;6.5% total device CPU&lt;/strong&gt; with savings scaling with entity count.&lt;/p&gt;
&lt;p&gt;Memory allocations were also removed from discovery messages (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13216&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13216&lt;/a&gt;), publish paths (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13372&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13372&lt;/a&gt;), topic building (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13434&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13434&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/13812&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13812&lt;/a&gt;), and log forwarding (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13809&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13809&lt;/a&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Who benefits most?&lt;/strong&gt; Users running MQTT instead of the native API, especially devices with many entities. The more entities you expose over MQTT, the bigger the improvement. If you’ve noticed high CPU usage or instability on MQTT devices, this update should help.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;h2 id=&quot;security-hardening&quot;&gt;Security Hardening&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Our first internal security audit in &lt;a href=&quot;https://esphome.io/blog/2025/10/15/esphome-2025-10/#security-enhancements&quot;&gt;2025.10.0&lt;/a&gt; led to several deprecations, most of which were completed in &lt;a href=&quot;https://esphome.io/blog/2026/01/21/esphome-2026-1/&quot;&gt;2026.1.0&lt;/a&gt;. This release started a new review cycle. No issues requiring deprecation were found, but we identified several additional hardening opportunities.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Constant-time authentication&lt;/strong&gt; - The dashboard (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13865&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13865&lt;/a&gt;) and web server (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13868&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13868&lt;/a&gt;) now use constant-time string comparisons for Basic Auth credential checks, preventing timing-based side-channel attacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cryptographic random generation&lt;/strong&gt; - The OTA component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13863&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13863&lt;/a&gt;) and setup wizard (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13864&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13864&lt;/a&gt;) now use Python’s &lt;code dir=&quot;auto&quot;&gt;secrets&lt;/code&gt; module for generating authentication nonces and fallback AP passwords, replacing less secure random sources&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protobuf parsing hardening&lt;/strong&gt; - The API protobuf parser now guards against overlong varint encodings (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13870&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13870&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Download path validation&lt;/strong&gt; - The dashboard binary download handler now uses &lt;code dir=&quot;auto&quot;&gt;Path.resolve()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;relative_to()&lt;/code&gt; for path validation instead of string replacement (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13867&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13867&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auth header validation&lt;/strong&gt; - The dashboard gracefully handles malformed Basic Auth headers instead of raising exceptions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13866&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13866&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-components&quot;&gt;New Components&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;dlmscosem-smart-meter&quot;&gt;DLMS/COSEM Smart Meter&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/sensor/dlms_meter&quot;&gt;dlms_meter&lt;/a&gt; component adds support for smart meters using the DLMS/COSEM protocol, commonly used by European energy providers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/8009&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#8009&lt;/a&gt;). The component connects via UART to an M-Bus adapter and supports encrypted communication with configurable decryption keys. Available sensors include voltage, current, and active power per phase, as well as energy totals and timestamps. Multiple provider-specific configurations are supported, including Netz NOE and EVN.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;ch423-io-expander&quot;&gt;CH423 I/O Expander&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/ch423&quot;&gt;ch423&lt;/a&gt; component provides support for the CH423 I/O expander with 24 GPIO pins: 8 bidirectional I/O pins and 16 output-only pins (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13079&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13079&lt;/a&gt;). Based on the CH422G driver architecture, it communicates over I2C and can be used with standard GPIO binary sensors, switches, and outputs.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;sy6970-battery-management-ic&quot;&gt;SY6970 Battery Management IC&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/sensor/sy6970&quot;&gt;sy6970&lt;/a&gt; component supports the SY6970 battery management IC, commonly found in devices like the LilyGo T-Display S3 Pro (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13311&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13311&lt;/a&gt;). It provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Voltage sensors&lt;/strong&gt; - VBUS, battery, and system voltage monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Current sensors&lt;/strong&gt; - Charge and precharge current measurement&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Binary sensors&lt;/strong&gt; - Charging status, VBUS connection, and charge completion&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Text sensors&lt;/strong&gt; - Bus status, charge status, and NTC temperature status&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configurable charging&lt;/strong&gt; - Set charge voltage, current limits, and enable/disable charging&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;expanded-display-support&quot;&gt;Expanded Display Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release adds support for &lt;strong&gt;7 new display models&lt;/strong&gt; across multiple display platforms, with a particular focus on ESP32-P4 displays.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MIPI DSI displays:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Waveshare ESP32-P4-WIFI6-TOUCH-LCD-7B&lt;/strong&gt; - 7” touchscreen for the ESP32-P4 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13608&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13608&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Waveshare ESP32-P4-WIFI6-TOUCH-LCD-3.4C&lt;/strong&gt; - 800x800 circular display (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13840&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13840&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Waveshare ESP32-P4-WIFI6-TOUCH-LCD-4C&lt;/strong&gt; - 720x720 circular display (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13840&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13840&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guition JC8012P4A1&lt;/strong&gt; - An affordable display panel (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13241&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13241&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;M5Stack Tab5 V2&lt;/strong&gt; - Updated revision using the ST7123 integrated display-touch driver (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12074&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12074&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;MIPI SPI displays:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32-2432S028 variants&lt;/strong&gt; - Added support for ILI9342, ILI9342A, and ST7789V driver chip variants of the popular Sunton board (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13340&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13340&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;HUB75 LED matrix:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Huidu HD-WF1&lt;/strong&gt; - Added pin configuration for the WF1 version of the Huidu board (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13341&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13341&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;E-Paper:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Waveshare 1.54-G&lt;/strong&gt; - 4-color e-paper display based on the JD79660 controller (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13758&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13758&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;zigbee-and-nrf52-platform-enhancements&quot;&gt;Zigbee and nRF52 Platform Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The Zigbee integration on nRF52 receives several important improvements in this release.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time synchronization&lt;/strong&gt; - Zigbee end devices can now synchronize their clocks from the Zigbee coordinator, enabling time-based automations on battery-powered devices (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12236&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12236&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Number component support&lt;/strong&gt; - ESPHome number entities can now be exposed over Zigbee, expanding the set of entity types available for Zigbee-connected devices (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13581&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13581&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom vendor OUI&lt;/strong&gt; - Configure the IEEE 802.15.4 Vendor Organizationally Unique Identifier to replace Nordic Semiconductor’s default company ID with your own, or use a random address during development (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13580&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13580&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thread-safe task log buffer&lt;/strong&gt; - A new &lt;code dir=&quot;auto&quot;&gt;TaskLogBuffer&lt;/code&gt; implementation for nRF52/Zephyr using Zephyr’s native &lt;code dir=&quot;auto&quot;&gt;mpsc_pbuf&lt;/code&gt; enables reliable multi-threaded logging, matching the capabilities already available on ESP32, Host, and LibreTiny (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13862&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13862&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;libretiny-platform-update&quot;&gt;LibreTiny Platform Update&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;LibreTiny has been updated from v1.10.x to v1.12.1 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13512&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13512&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/13851&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13851&lt;/a&gt;), bringing new board support (WBR3, generic RTL8720CM, CR3L), a refactored Serial library with dynamic RX/TX pin changes, static IP support for Realtek AMB WiFi, improved OTA for Realtek AMBZ2, Beken BDK 3.0.78 support, and several WiFi stability fixes including watchdog resets during connection attempts on BK72xx.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;cover-component-operation-based-triggers-and-conditions&quot;&gt;Cover Component: Operation-Based Triggers and Conditions&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The cover component gains new triggers that fire based on movement state, making cover automations much more natural to write (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13471&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13471&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New triggers:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;on_opening&lt;/code&gt;&lt;/strong&gt; - Fires when the cover starts opening&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;on_closing&lt;/code&gt;&lt;/strong&gt; - Fires when the cover starts closing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;on_idle&lt;/code&gt;&lt;/strong&gt; - Fires when the cover stops moving&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New conditions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;cover.is_open&lt;/code&gt;&lt;/strong&gt; - Check if a cover is fully open&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;cover.is_closed&lt;/code&gt;&lt;/strong&gt; - Check if a cover is fully closed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The existing &lt;code dir=&quot;auto&quot;&gt;on_open&lt;/code&gt; trigger has been renamed to &lt;code dir=&quot;auto&quot;&gt;on_opened&lt;/code&gt; (the old name is deprecated until 2026.8.0). Additionally, &lt;code dir=&quot;auto&quot;&gt;on_opened&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;on_closed&lt;/code&gt; now only fire on &lt;em&gt;transitions&lt;/em&gt; to the fully open/closed state, fixing unintended repeated trigger firing that occurred on every state update.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-sensor-features-and-hardware-support&quot;&gt;New Sensor Features and Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;New hardware support:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Plantower PMS1003, PMS3003, PMS9003M&lt;/strong&gt; - Three additional particle sensor models are now supported by the &lt;a href=&quot;https://esphome.io/components/sensor/pmsx003&quot;&gt;pmsx003&lt;/a&gt; component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13640&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13640&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resol DeltaSol BS/2&lt;/strong&gt; - The &lt;a href=&quot;https://esphome.io/components/vbus&quot;&gt;vbus&lt;/a&gt; component now supports this solar controller with temperature, pump speed, heat quantity, and error sensors (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13762&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13762&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BMP581 I2C/SPI split&lt;/strong&gt; - The BMP581 pressure sensor has been split into &lt;code dir=&quot;auto&quot;&gt;bmp581_base&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;bmp581_i2c&lt;/code&gt; components, preparing the way for future SPI support. Existing users will need to update their platform from &lt;code dir=&quot;auto&quot;&gt;bmp581&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;bmp581_i2c&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12485&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12485&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Sensor filter improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;max_delta&lt;/code&gt; filter&lt;/strong&gt; - A new filter that rejects measurement differences exceeding a configurable threshold, effectively removing outliers from sensor readings (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12605&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12605&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Debug component:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;min_free&lt;/code&gt; heap sensor&lt;/strong&gt; - Reports the minimum free heap size since boot for ESP32 and LibreTiny platforms, useful for detecting memory high-water-mark usage (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13231&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13231&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;fragmentation&lt;/code&gt; sensor&lt;/strong&gt; - Now available on ESP32 in addition to ESP8266 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13231&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13231&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;additional-component-enhancements&quot;&gt;Additional Component Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTTP request custom CA certificates&lt;/strong&gt; - ESP32 devices can now use &lt;code dir=&quot;auto&quot;&gt;ca_certificate_path&lt;/code&gt; to specify a PEM file for SSL verification, enabling HTTPS connections to servers with self-signed or custom CA certificates (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13552&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13552&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BTHome encrypted beacons&lt;/strong&gt; - The bthome_mithermometer component now supports decrypting encrypted BTHome beacons from PVVX firmware using a bindkey, preventing spoofing with fake data over the air (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13428&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13428&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ethernet &lt;code dir=&quot;auto&quot;&gt;on_connect&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;on_disconnect&lt;/code&gt; triggers&lt;/strong&gt; - The &lt;a href=&quot;https://esphome.io/components/ethernet&quot;&gt;ethernet&lt;/a&gt; component now supports connection triggers, matching the functionality already available for WiFi (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13677&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13677&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HeatpumpIR ESP-IDF support&lt;/strong&gt; - The heatpumpir component now works with the ESP-IDF framework, not just Arduino (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13042&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13042&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Select condition&lt;/strong&gt; - A new &lt;code dir=&quot;auto&quot;&gt;select.is&lt;/code&gt; condition allows checking the value of a select entity in automations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13267&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13267&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MQTT cover JSON state payload&lt;/strong&gt; - Covers can now publish position, tilt, and state as a single JSON payload on one topic, reducing MQTT message volume (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12639&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12639&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key collector text sensor&lt;/strong&gt; - The &lt;a href=&quot;https://esphome.io/components/key_collector&quot;&gt;key_collector&lt;/a&gt; component now supports a text sensor platform and accepts multiple key input sources (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13617&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13617&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Template water heater improvements&lt;/strong&gt; - Added &lt;code dir=&quot;auto&quot;&gt;target_temperature&lt;/code&gt; lambda (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13661&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13661&lt;/a&gt;) and On/Off and Away mode support (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13839&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13839&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nextion configurable timeouts&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;startup_override_ms&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;max_queue_age&lt;/code&gt; constants are now configurable via YAML, allowing users to tune timing for their specific displays (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11098&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#11098&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Voice assistant timer optimization&lt;/strong&gt; - Timer storage switched from &lt;code dir=&quot;auto&quot;&gt;unordered_map&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;vector&lt;/code&gt;, eliminating per-tick heap allocation and string copies for the hot path that runs every second (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13857&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13857&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release continues the work that began in &lt;a href=&quot;https://esphome.io/blog/2025/10/15/esphome-2025-10/&quot;&gt;2025.10.0&lt;/a&gt; and accelerated in &lt;a href=&quot;https://esphome.io/blog/2026/01/21/esphome-2026-1/&quot;&gt;2026.1.0&lt;/a&gt;: making ESPHome leaner and more reliable on every platform. Fewer heap allocations, smaller firmware, and lower CPU usage all contribute to devices that stay stable for months and years. That focus on memory discipline and long-term stability will continue in future releases as we extend these improvements to more components and platforms.&lt;/p&gt;
&lt;p&gt;On the documentation side, &lt;a href=&quot;https://esphome.io&quot;&gt;esphome.io&lt;/a&gt; has migrated from Hugo to &lt;a href=&quot;https://starlight.astro.build/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Starlight&lt;/a&gt;, bringing faster page loads, improved search, and a modern documentation framework that will make it easier to maintain and contribute to the docs going forward.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Most users can update without any configuration changes. The items below are grouped by whether you need to take action.&lt;/p&gt;

&lt;div&gt;&lt;h3 id=&quot;action-required-if-you-use-these-components&quot;&gt;Action required (if you use these components)&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;BMP581&lt;/strong&gt;: Update your platform from &lt;code dir=&quot;auto&quot;&gt;bmp581&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;bmp581_i2c&lt;/code&gt;. The component has been split to prepare for future SPI support. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12485&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12485&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cover triggers&lt;/strong&gt;: Rename &lt;code dir=&quot;auto&quot;&gt;on_open&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;on_opened&lt;/code&gt; in your cover automations (the old name is deprecated until 2026.8.0). Additionally, &lt;code dir=&quot;auto&quot;&gt;on_opened&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;on_closed&lt;/code&gt; now only fire on &lt;em&gt;transitions&lt;/em&gt; to the fully open/closed state, not on every state update. Automations that relied on repeated firing will need to be adjusted. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13471&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13471&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DSMR&lt;/strong&gt;: Move &lt;code dir=&quot;auto&quot;&gt;fw_core_version&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;fw_module_version&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;sensor:&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;text_sensor:&lt;/code&gt;. The meter returns version strings (e.g., &lt;code dir=&quot;auto&quot;&gt;(ER11)&lt;/code&gt;), not numbers. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13780&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13780&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Arduino library APIs in lambdas&lt;/strong&gt;: If you directly call Arduino library APIs in lambdas (e.g., &lt;code dir=&quot;auto&quot;&gt;Preferences&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;WiFi&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Wire&lt;/code&gt;), add them to your config. ESPHome’s built-in components handle this automatically, so this only affects custom lambda code. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13623&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;libraries&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;Preferences&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Add any Arduino libraries you use directly&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Voice Assistant timers&lt;/strong&gt;: If you use lambdas that iterate timers with map pair semantics (&lt;code dir=&quot;auto&quot;&gt;.second&lt;/code&gt;), update them to access &lt;code dir=&quot;auto&quot;&gt;Timer&lt;/code&gt; fields directly. See the PR description for before/after examples. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13857&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13857&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;most-users-unaffected&quot;&gt;Most users unaffected&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;These changes improve correctness or save resources. They only require action if you depend on the previous behavior.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP32 certificate bundle&lt;/strong&gt;: The default TLS bundle now includes only Common CAs (~99% of websites), saving ~51KB of flash. If you connect to HTTPS services using uncommon CAs, add &lt;code dir=&quot;auto&quot;&gt;use_full_certificate_bundle: true&lt;/code&gt; under &lt;code dir=&quot;auto&quot;&gt;esp32: framework: advanced:&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13574&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13574&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;BL0942&lt;/strong&gt;: Calibration reference values have been corrected to match datasheet formulas. Sensor readings will change. Users with custom calibration may need to re-calibrate. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12867&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#12867&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sensor clamp filter&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;clamp&lt;/code&gt; filter now handles infinity and NaN instead of passing them through. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13457&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13457&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Water Heater&lt;/strong&gt;: On/Off and Away state control now requires both Home Assistant 2026.3.0 and ESPHome 2026.2.0. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13892&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13892&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32 Arduino selective compilation&lt;/strong&gt;: Arduino libraries are now disabled by default. External components that use Arduino libraries must call &lt;code dir=&quot;auto&quot;&gt;cg.add_library(&quot;LibraryName&quot;, None)&lt;/code&gt; in their &lt;code dir=&quot;auto&quot;&gt;to_code()&lt;/code&gt; to enable them. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13623&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Voice Assistant &lt;code dir=&quot;auto&quot;&gt;get_timers()&lt;/code&gt; return type&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_timers()&lt;/code&gt; now returns &lt;code dir=&quot;auto&quot;&gt;const std::vector&amp;#x3C;Timer&gt; &amp;#x26;&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const std::unordered_map&amp;#x3C;std::string, Timer&gt; &amp;#x26;&lt;/code&gt;. Code using map pair semantics (&lt;code dir=&quot;auto&quot;&gt;.second&lt;/code&gt;) must be updated to iterate &lt;code dir=&quot;auto&quot;&gt;Timer&lt;/code&gt; directly. The &lt;code dir=&quot;auto&quot;&gt;on_timer_tick&lt;/code&gt; automation arg type is now &lt;code dir=&quot;auto&quot;&gt;const std::vector&amp;#x3C;Timer&gt; &amp;#x26;&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13857&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13857&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cover &lt;code dir=&quot;auto&quot;&gt;on_open&lt;/code&gt; renamed to &lt;code dir=&quot;auto&quot;&gt;on_opened&lt;/code&gt;&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;CoverOpenTrigger&lt;/code&gt; now tracks transitions instead of firing on every state update. The old &lt;code dir=&quot;auto&quot;&gt;on_open&lt;/code&gt; name is deprecated until 2026.8.0. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13471&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13471&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Water Heater API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;WATER_HEATER_COMMAND_HAS_STATE&lt;/code&gt; is deprecated in favor of &lt;code dir=&quot;auto&quot;&gt;WATER_HEATER_COMMAND_HAS_ON_STATE&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;WATER_HEATER_COMMAND_HAS_AWAY_STATE&lt;/code&gt; for granular on/off and away control. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13892&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;#13892&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the &lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-2-1---february-20&quot;&gt;Release 2026.2.1 - February 20&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[esp32_ble_server] fix infinitely large characteristic value &lt;a href=&quot;https://github.com/esphome/esphome/pull/14011&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14011&lt;/a&gt; by &lt;a href=&quot;https://github.com/Rapsssito&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Rapsssito&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[udp] Register socket consumption for CONFIG_LWIP_MAX_SOCKETS &lt;a href=&quot;https://github.com/esphome/esphome/pull/14068&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14068&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[web_server] Double socket allocation to prevent connection exhaustion &lt;a href=&quot;https://github.com/esphome/esphome/pull/14067&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14067&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[pulse_counter] Fix compilation on ESP32-C6/C5/H2/P4 &lt;a href=&quot;https://github.com/esphome/esphome/pull/14070&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14070&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[web_server] Fix water_heater JSON key names and move traits to DETAIL_ALL &lt;a href=&quot;https://github.com/esphome/esphome/pull/14064&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14064&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2420] Use constexpr for compile-time constants &lt;a href=&quot;https://github.com/esphome/esphome/pull/14079&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14079&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[e131] Fix E1.31 on ESP8266 and RP2040 by restoring WiFiUDP support &lt;a href=&quot;https://github.com/esphome/esphome/pull/14086&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14086&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[socket] Fix IPv6 compilation error on host platform &lt;a href=&quot;https://github.com/esphome/esphome/pull/14101&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14101&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ethernet] Improve clk_mode deprecation warning with actionable YAML &lt;a href=&quot;https://github.com/esphome/esphome/pull/14104&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14104&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[pulse_counter] Fix build failure when use_pcnt is false &lt;a href=&quot;https://github.com/esphome/esphome/pull/14111&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14111&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble] Enable CONFIG_BT_RELEASE_IRAM on ESP32-C2 &lt;a href=&quot;https://github.com/esphome/esphome/pull/14109&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14109&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[safe_mode] Log brownout as reset reason on OTA rollback &lt;a href=&quot;https://github.com/esphome/esphome/pull/14113&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14113&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Sync output_power with PHY max TX power to prevent brownout &lt;a href=&quot;https://github.com/esphome/esphome/pull/14118&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14118&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Always call pin setup for UART0 default pins on ESP-IDF &lt;a href=&quot;https://github.com/esphome/esphome/pull/14130&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14130&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[pulse_counter] Fix PCNT glitch filter calculation off by 1000x &lt;a href=&quot;https://github.com/esphome/esphome/pull/14132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14132&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2450] Add frame header synchronization to readline_() &lt;a href=&quot;https://github.com/esphome/esphome/pull/14135&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14135&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2410] Add frame header synchronization to readline_() &lt;a href=&quot;https://github.com/esphome/esphome/pull/14136&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14136&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2420] Increase MAX_LINE_LENGTH to allow footer-based resync &lt;a href=&quot;https://github.com/esphome/esphome/pull/14137&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14137&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2410/ld2450] Replace header sync with buffer size increase for frame resync &lt;a href=&quot;https://github.com/esphome/esphome/pull/14138&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14138&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-2-2---february-26&quot;&gt;Release 2026.2.2 - February 26&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[max7219digit] Fix typo in action names &lt;a href=&quot;https://github.com/esphome/esphome/pull/14162&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14162&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_dsi] Disallow swap_xy &lt;a href=&quot;https://github.com/esphome/esphome/pull/14124&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14124&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[dsmr] Add deprecated std::string overload for set_decryption_key &lt;a href=&quot;https://github.com/esphome/esphome/pull/14180&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14180&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fix build error when lambda returns StringRef in homeassistant.event data &lt;a href=&quot;https://github.com/esphome/esphome/pull/14187&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14187&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[haier] Fix uninitialized HonSettings causing API connection failures &lt;a href=&quot;https://github.com/esphome/esphome/pull/14188&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14188&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bme68x_bsec2] Fix compilation on ESP32 Arduino &lt;a href=&quot;https://github.com/esphome/esphome/pull/14194&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14194&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[network] Improve IPAddress::str() deprecation warning with usage example &lt;a href=&quot;https://github.com/esphome/esphome/pull/14195&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14195&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[water_heater] Fix device_id missing from state responses &lt;a href=&quot;https://github.com/esphome/esphome/pull/14212&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14212&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_dsi] Allow transform disable; fix warnings &lt;a href=&quot;https://github.com/esphome/esphome/pull/14216&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14216&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; (new-feature)&lt;/li&gt;
&lt;li&gt;[http_request.ota] Percent-encode credentials in URL &lt;a href=&quot;https://github.com/esphome/esphome/pull/14257&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14257&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Don’t get stuck forever on a failed component can_proceed &lt;a href=&quot;https://github.com/esphome/esphome/pull/14267&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14267&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[pid] Fix deadband threshold conversion for Fahrenheit &lt;a href=&quot;https://github.com/esphome/esphome/pull/14268&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14268&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2420] Fix sizeof vs value bug in register memcpy &lt;a href=&quot;https://github.com/esphome/esphome/pull/14286&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14286&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rtttl] Fix speaker playback bugs &lt;a href=&quot;https://github.com/esphome/esphome/pull/14280&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14280&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[hmc5883l] Fix wrong gain for 88uT range &lt;a href=&quot;https://github.com/esphome/esphome/pull/14281&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14281&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sensor] Fix delta filter percentage mode regression &lt;a href=&quot;https://github.com/esphome/esphome/pull/14302&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14302&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-2-3---march-3&quot;&gt;Release 2026.2.3 - March 3&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[mqtt] Remove broken ESP8266 ssl_fingerprints option &lt;a href=&quot;https://github.com/esphome/esphome/pull/14182&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14182&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt; (breaking-change)&lt;/li&gt;
&lt;li&gt;[sprinkler] Fix millis overflow and underflow bugs &lt;a href=&quot;https://github.com/esphome/esphome/pull/14299&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14299&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[cc1101] Transition through IDLE in begin_tx/begin_rx for reliable state changes &lt;a href=&quot;https://github.com/esphome/esphome/pull/14321&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14321&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[zigbee] Fix codegen ordering for basic/identify attribute lists &lt;a href=&quot;https://github.com/esphome/esphome/pull/14343&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14343&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Revert UART0 default pin workarounds (fixed in ESP-IDF 5.5.2) &lt;a href=&quot;https://github.com/esphome/esphome/pull/14363&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14363&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_dsi] Fix Waveshare P4 7B board config &lt;a href=&quot;https://github.com/esphome/esphome/pull/14372&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14372&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Defer entity automation codegen to prevent sibling ID deadlocks &lt;a href=&quot;https://github.com/esphome/esphome/pull/14381&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14381&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[improv_serial] Add missing USE_IMPROV_SERIAL define to fix WiFi scan filtering &lt;a href=&quot;https://github.com/esphome/esphome/pull/14359&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14359&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Fix flow_control_pin inverted flag ignored on ESP-IDF &lt;a href=&quot;https://github.com/esphome/esphome/pull/14410&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14410&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-2-4---march-3&quot;&gt;Release 2026.2.4 - March 3&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[wifi] Revert cyw43_wifi_link_status change for RP2040 &lt;a href=&quot;https://github.com/esphome/esphome/pull/14424&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#14424&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.2.0/&quot;&gt;full 2026.2.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2026.1.0: Automatic WiFi roaming and ESP-IDF by default</title><link>https://esphome.io/blog/2026/01/21/esphome-2026-1/</link><guid isPermaLink="true">https://esphome.io/blog/2026/01/21/esphome-2026-1/</guid><description>ESPHome 2026.1.0 adds automatic WiFi roaming, makes ESP-IDF the default on ESP32, requires API encryption and SHA256 OTA, and lands broad performance work.</description><pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/aqi/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/aqi.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;AQI&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/water_heater/index/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/folder-open.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Water ​Heater ​Core&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/water_heater/template/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/description.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Template ​Water ​Heater&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/zigbee/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/zigbee.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Zigbee ​End ​Device&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/rd03d/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/rd03d.webp&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;RD-​0​3​D&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/infrared/index/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/folder-open.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Infrared ​Core&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/ir_rf_proxy/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/remote.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;IR/​RF ​Proxy&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2026.1.0 delivers one of the most requested features: automatic WiFi roaming. Devices now switch to better access points after connecting, solving the problem of devices getting stuck on distant APs after power outages or AP reboots.&lt;/p&gt;
&lt;p&gt;The web server now uses entity names directly in URLs with collision-free encoding, fixing issues that plagued non-ASCII configurations.&lt;/p&gt;
&lt;p&gt;This release completes major security transitions: API password authentication has been removed and API encryption is now required, while OTA updates require SHA256 authentication. ESP-IDF is now the default for ESP32, ESP32-C3, ESP32-S2, and ESP32-S3, delivering up to 40% smaller binaries and faster compile times.&lt;/p&gt;
&lt;p&gt;Months of performance optimization work culminates here: heap churn reduction plus allocator work enabled moving heap functions from IRAM to flash (saving ~6KB of IRAM on ESP32), removing object_id storage from RAM saves hundreds to thousands of bytes, zero-copy API support delivers ~42% more entities per packet, and ESP32 camera streaming improves by ~10% with lower latency. These optimizations translate directly into headroom for existing devices and reliability for years to come.&lt;/p&gt;
&lt;p&gt;LibreTiny platforms (BK72xx, RTL87xx, LN882x) receive thread-safe WiFi, atomics support, and deep sleep that bring them closer to first-class status. New hardware support includes the RD-03D mmWave radar and BTHome v2 parsing for Xiaomi sensors, while Zigbee on nRF52 expands with sensor, binary sensor, and switch support.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;upgrade-checklist&quot;&gt;Upgrade Checklist&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;If you used &lt;code dir=&quot;auto&quot;&gt;api: password:&lt;/code&gt;, replace it with &lt;code dir=&quot;auto&quot;&gt;api: encryption: key:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you rely on Arduino-only components, explicitly set ESP32 framework to &lt;code dir=&quot;auto&quot;&gt;type: arduino&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you used web server URLs directly, note the new name-based URLs and the &lt;code dir=&quot;auto&quot;&gt;/&lt;/code&gt; restriction in entity names&lt;/li&gt;
&lt;li&gt;If you have lambdas using Fan, Select, Climate, Event, or Light state methods, check the Lambda API Changes below&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;building-forward-without-leaving-users-behind&quot;&gt;Building forward without leaving users behind&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;At the end of 2024, ESPHome completed the transition from ESP-IDF 4.x to ESP-IDF 5.x for ESP32. By early 2025, as we began addressing the higher baseline memory costs on ESP32, something important became clear. Users were telling us that their devices were running out of RAM, firmware builds were failing because flash limits were exceeded, and devices that had worked reliably for years were suddenly unstable or impossible to update.&lt;/p&gt;
&lt;p&gt;ESPHome had grown powerful.
It had also grown heavy.&lt;/p&gt;
&lt;p&gt;That growth did not happen overnight. Since 2019, the ESPHome codebase has steadily expanded. New components, new platforms, and new capabilities were added year after year. The project kept moving forward because it had to. User demand, new hardware, and ecosystem changes did not wait.&lt;/p&gt;
&lt;p&gt;What we did not have for a long time was enough capacity to do more than one hard thing at once.&lt;/p&gt;
&lt;p&gt;As we started reducing memory usage on ESP32 in early 2025, the work exposed a broader pattern. ESP8266 does not use ESP-IDF, but the ESP32 transition helped us see something we had missed. As development increasingly focused on ESP32, ESP8266 became less sustainable by default. Not because users needed ESP32 features, but because that was where optimization, testing, and attention naturally concentrated. When configurations became tight or devices unstable, the path of least resistance was often to move to ESP32.&lt;/p&gt;
&lt;p&gt;Over time, that behavior became normalized.&lt;/p&gt;
&lt;p&gt;The ESP-IDF upgrade forced us to step back and examine why so many users had already migrated. The answer was uncomfortable but clear. ESP8266 was not failing because it could not meet user needs. It was failing because we were no longer treating it as a first class platform. By the time runtime heap on ESP8266 routinely dropped below 10k, the outcome was predictable. Even modest real world configurations became fragile, and we eventually had to advise users not to use ESP8266 at all.&lt;/p&gt;
&lt;p&gt;That realization marked a real inflection point.&lt;/p&gt;
&lt;p&gt;Not because the ESP32 transition was wrong, but because it revealed a dependency we had allowed to form. Progress had quietly become tied to hardware replacement. People were being left behind, not by design, but by momentum. With millions of ESP8266 devices already deployed and likely to remain in homes for years, that was not an acceptable outcome.&lt;/p&gt;
&lt;p&gt;What changed was not direction.
What changed was scale.&lt;/p&gt;
&lt;p&gt;Increased support for the Open Home Foundation changed the equation. With more Home Assistant users supporting the ecosystem through hardware purchases and Home Assistant Cloud subscriptions, ESPHome now has two full time developers and a broader base of part time contributors. That made it possible to keep moving forward while also tackling long standing performance, memory, and sustainability work.&lt;/p&gt;
&lt;p&gt;In the middle of 2025, pressure increased again when ESPHome upgraded from Arduino 2 to Arduino 3 for ESP32. The new Arduino core brought important long term improvements, but it also increased baseline RAM and flash usage. On top of the ESP-IDF 5 transition, the impact compounded. Rather than accepting that cost, we made a structural change and moved Arduino to run as an ESP-IDF component.&lt;/p&gt;
&lt;p&gt;This gave us tighter control over integration, build behavior, and memory ownership, and allowed us to systematically reduce the overhead introduced by the transition.&lt;/p&gt;
&lt;p&gt;Over the following months, work continued in parallel. New components kept landing. New platforms were supported. At the same time, we removed duplication between layers, tightened boundaries, and eliminated unused paths that had quietly accumulated over time. The goal was not just compatibility, but sustainability.&lt;/p&gt;
&lt;p&gt;This work was guided by the principles of the Open Home Foundation. Privacy, choice, and sustainability are not abstract ideals. They show up in practical ways, in how long devices remain usable, how often hardware needs to be replaced, and whether users are forced to discard perfectly good devices just to keep their software up to date. We chose sustainability through efficiency.&lt;/p&gt;
&lt;p&gt;By the start of 2026, these efforts converged. The ESP-IDF 5 transition, the Arduino 3 integration, and the memory reduction work across ESPHome all fell into place, producing a step change in performance, RAM availability, and flash usage across supported platforms.&lt;/p&gt;
&lt;p&gt;The results were tangible.&lt;/p&gt;
&lt;p&gt;On ESP8266, available heap increased from under 10k to over 30k in realistic configurations. On a platform that often only has about 45k of heap available when nearly nothing is configured, that shift fundamentally changes what is possible. Devices that were unstable became reliable, and devices that could not be updated regained headroom.&lt;/p&gt;
&lt;p&gt;In parallel, we addressed long standing performance and latency issues on ESP32-C3. Bluetooth proxies on this platform were unreliable and frustrating, but through scheduler tuning, memory optimizations, and transport improvements, they are now viable. ESP32-S3 remains the better choice for heavy Bluetooth workloads, but C3 is no longer a dead end.&lt;/p&gt;
&lt;p&gt;ESP8266 is no longer a platform we warn users away from. It can continue serving existing deployments well into the future, even as new projects naturally gravitate toward ESP32.&lt;/p&gt;
&lt;p&gt;What changed in 2026 is not just memory numbers or latency graphs.&lt;/p&gt;
&lt;p&gt;What changed is intent.&lt;/p&gt;
&lt;p&gt;ESPHome continues to move forward with new hardware support, new components, and new features, while treating sustainability as a first class requirement rather than an afterthought.&lt;/p&gt;
&lt;p&gt;In 2026, ESPHome is faster, leaner, and more durable. It respects the hardware it runs on and the users who already invested in it.&lt;/p&gt;
&lt;p&gt;We learned how to move forward without leaving users behind.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;wifi-roaming-support&quot;&gt;WiFi Roaming Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;One of the most requested features for years: ESPHome devices now automatically switch to better access points after connecting (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12809&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12809&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This addresses three scenarios where devices get stuck on suboptimal APs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AP reboot&lt;/strong&gt; - Device connects to a distant AP while the nearby one restarts, never switches back&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power outage&lt;/strong&gt; - Devices connect to whichever AP recovers first, often the worst option&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improv provisioning&lt;/strong&gt; - Bluetooth or serial setup may pick a suboptimal AP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For Bluetooth proxies or Z-Wave adapters, a poor WiFi connection cascades into widespread failures. Until now, the only fix was manually restarting each device.&lt;/p&gt;
&lt;p&gt;Post-connect roaming is designed for stationary devices and is intentionally conservative. If you already configured 802.11k or 802.11v roaming, post-connect roaming disables itself automatically. Devices scan up to 3 times after connecting (every 5 minutes), skip scanning when signal is already excellent, and only roam when finding a meaningfully better signal. Users shouldn’t need to understand RSSI thresholds to get reliable WiFi behavior.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Enabled by default, but can be disabled:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;wifi&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ssid&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!secret&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wifi_ssid&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!secret&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wifi_password&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;post_connect_roaming&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# To disable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;web-server-improvements&quot;&gt;Web Server Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The web server now uses entity names directly in URLs instead of sanitized &lt;code dir=&quot;auto&quot;&gt;object_id&lt;/code&gt; values (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12627&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12627&lt;/a&gt;), fixing long-standing issues with URL collisions. This change is part of the broader effort to &lt;a href=&quot;https://github.com/esphome/backlog/issues/85&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;eliminate &lt;code dir=&quot;auto&quot;&gt;object_id&lt;/code&gt; collisions with non-ASCII characters&lt;/a&gt; - a key step toward proper UTF-8 support so users can use non-ASCII entity names in Home Assistant without collisions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problems Solved:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UTF-8 name collisions&lt;/strong&gt; - Different UTF-8 names like &lt;code dir=&quot;auto&quot;&gt;&quot;温度传感器&quot;&lt;/code&gt; (temperature) and &lt;code dir=&quot;auto&quot;&gt;&quot;湿度传感器&quot;&lt;/code&gt; (humidity) previously both became &lt;code dir=&quot;auto&quot;&gt;&quot;___&quot;&lt;/code&gt;, making them indistinguishable&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sub-device collisions&lt;/strong&gt; - Multiple devices with entities named “Temperature” now have unique URLs like &lt;code dir=&quot;auto&quot;&gt;/sensor/Garage/Temperature&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New URL Format:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Main device entity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/sensor/Temperature&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Sub-device entity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/sensor/Garage/Temperature&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# UTF-8 names work correctly&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/sensor/温度&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Old URLs using &lt;code dir=&quot;auto&quot;&gt;object_id&lt;/code&gt; format (e.g., &lt;code dir=&quot;auto&quot;&gt;/sensor/temperature_sensor&lt;/code&gt;) continue to work during a deprecation period until 2026.7.0.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SSE Entity IDs:&lt;/strong&gt; A deprecation path was added for SSE event entity IDs. The payload now includes a temporary &lt;code dir=&quot;auto&quot;&gt;name_id&lt;/code&gt; field (new format like &lt;code dir=&quot;auto&quot;&gt;sensor/Temperature&lt;/code&gt;) alongside &lt;code dir=&quot;auto&quot;&gt;id&lt;/code&gt; (legacy format like &lt;code dir=&quot;auto&quot;&gt;sensor-temperature&lt;/code&gt;). &lt;strong&gt;Timeline:&lt;/strong&gt; In 2026.8.0, &lt;code dir=&quot;auto&quot;&gt;name_id&lt;/code&gt; will be removed and &lt;code dir=&quot;auto&quot;&gt;id&lt;/code&gt; will switch to the new format. Third-party integrations should prefer &lt;code dir=&quot;auto&quot;&gt;name_id&lt;/code&gt; now, falling back to &lt;code dir=&quot;auto&quot;&gt;id&lt;/code&gt; for compatibility with older firmware. Integrations requiring the legacy format after 2026.8.0 must implement their own conversion logic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important restrictions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Names may not include &lt;code dir=&quot;auto&quot;&gt;/&lt;/code&gt; because it is reserved as a URL path separator&lt;/li&gt;
&lt;li&gt;Names used in URLs are limited to 120 characters&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;brotli-compression-for-web-assets&quot;&gt;Brotli Compression for Web Assets&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Web server and captive portal assets now use Brotli compression by default, saving significant flash space (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12959&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12959&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;captive_portal&lt;/strong&gt;: 348 bytes saved (24%)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;web_server v2&lt;/strong&gt;: 1,210 bytes saved (10%)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;web_server v3&lt;/strong&gt;: 9,420 bytes saved (12%)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;security-enhancements&quot;&gt;Security Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release includes significant security improvements that complete long-standing deprecations:&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;api-password-authentication-removed&quot;&gt;API Password Authentication Removed&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Password authentication has been &lt;strong&gt;removed&lt;/strong&gt; from the API component after being deprecated since May 2022 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12819&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12819&lt;/a&gt;). Password authentication only verified identity while all data was still transmitted in plaintext. Noise-based encryption provides both authentication and a fully encrypted data stream.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If your configuration still has &lt;code dir=&quot;auto&quot;&gt;password:&lt;/code&gt;, it will fail to compile.&lt;/strong&gt; Users must migrate to encryption:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;api&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;encryption&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!secret&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;api_encryption_key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Generate a key with: openssl rand -base64 32&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;ota-authentication-upgraded&quot;&gt;OTA Authentication Upgraded&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;MD5 authentication support has been &lt;strong&gt;removed&lt;/strong&gt; from OTA updates (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12707&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12707&lt;/a&gt;). SHA256 is now mandatory, preventing protocol downgrade attacks.&lt;/p&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESPHome versions before 2025.10.0 that use password authentication cannot OTA to devices running 2026.1.0 or later.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you use multiple systems to install and/or update your ESPHome devices, be sure they’re all up-to-date! If you need to downgrade to a version before 2025.10.0, downgrade to 2025.12.x first, then OTA to an earlier version.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;hmac-sha256-support&quot;&gt;HMAC-SHA256 Support&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;A new &lt;code dir=&quot;auto&quot;&gt;hmac_sha256&lt;/code&gt; component provides HMAC support using the more secure SHA256 algorithm (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12437&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp-idf-default-framework&quot;&gt;ESP-IDF Default Framework&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release completes the transition announced in ESPHome 2025.8.0: &lt;strong&gt;ESP-IDF is now the default framework&lt;/strong&gt; for ESP32, ESP32-C3, ESP32-S2, and ESP32-S3 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12746&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12746&lt;/a&gt;). Users have been warned about this change for months.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Up to 40% smaller firmware binaries&lt;/strong&gt; - More room for features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Up to 2-3x faster compile times&lt;/strong&gt; - Quicker development cycles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better performance&lt;/strong&gt; - Improved runtime characteristics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access to newer features&lt;/strong&gt; - Full ESP-IDF capabilities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This release also bumps to ESP-IDF 5.5.2 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12681&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12681&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;To continue using Arduino for components that require it (such as &lt;code dir=&quot;auto&quot;&gt;heatpumpir&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;midea&lt;/code&gt;), explicitly set &lt;code dir=&quot;auto&quot;&gt;type: arduino&lt;/code&gt; in your configuration. See the &lt;a href=&quot;https://esphome.io/guides/esp32_arduino_to_idf/&quot;&gt;Arduino to ESP-IDF Migration Guide&lt;/a&gt; for details.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esp32&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;board&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp32dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;framework&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;arduino&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Explicitly use Arduino if needed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;performance--memory-optimizations&quot;&gt;Performance &amp;#x26; Memory Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release represents the culmination of months of work to reduce heap churn and memory usage throughout ESPHome, resulting in significant improvements across all platforms.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;heap-churn-reduction&quot;&gt;Heap Churn Reduction&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Systematic elimination of unnecessary dynamic allocations means heap functions (malloc, free, realloc) are now primarily called during setup, not during normal operation. This enabled moving heap functions from IRAM to flash on ESP32, &lt;strong&gt;saving ~6KB of IRAM&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12862&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12862&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Key optimizations include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;StaticVector&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;FixedVector&lt;/code&gt; replacing &lt;code dir=&quot;auto&quot;&gt;std::vector&lt;/code&gt; where sizes are known&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt; for static strings instead of &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pre-allocated buffers instead of dynamic allocation in hot paths&lt;/li&gt;
&lt;li&gt;Stack allocation where possible&lt;/li&gt;
&lt;li&gt;Audio/video components using pre-allocated ring buffers&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;object-id-ram-removal&quot;&gt;Object ID RAM Removal&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;object_id&lt;/code&gt; field is no longer stored in RAM, saving significant memory especially on ESP8266 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12631&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12631&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP8266&lt;/strong&gt; (37 entities): ~886 bytes saved (~24 bytes/entity)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32&lt;/strong&gt; (102 entities): ~497 bytes saved (~5 bytes/entity)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Large setups&lt;/strong&gt; (800 entities): ~3,600 bytes saved&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;esp8266-memory-optimizations&quot;&gt;ESP8266 Memory Optimizations&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;ESP8266 receives additional memory optimizations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unused waveform code excluded&lt;/strong&gt; - Saves 596 bytes RAM when &lt;code dir=&quot;auto&quot;&gt;esp8266_pwm&lt;/code&gt; is not used (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12690&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12690&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unused Serial objects excluded&lt;/strong&gt; - Saves 32-64 bytes RAM (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12736&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12736&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;esp-idf-5-5-2-compiler-improvements&quot;&gt;ESP-IDF 5.5.2 Compiler Improvements&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The bump to ESP-IDF 5.5.2 includes compiler improvements that reduce flash usage by ~35KB (~4%) on typical ESP32 configurations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12681&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12681&lt;/a&gt;). The libc component alone shrank by ~15KB.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;logging-optimizations&quot;&gt;Logging Optimizations&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Over 100 components received logging optimizations that combine consecutive log statements into single calls (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12838&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12838&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12860&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12860&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12856&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12856&lt;/a&gt;, and many more). Each &lt;code dir=&quot;auto&quot;&gt;ESP_LOG*&lt;/code&gt; call involves formatting, memory allocation, serial output, and network packet transmission. Combining them significantly reduces event loop blocking and the number of network packets sent to connected clients.&lt;/p&gt;
&lt;p&gt;Additional logging improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thread-safe logging on host platform&lt;/strong&gt; - Consistent behavior across platforms (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13010&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13010&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAII guards for recursion protection&lt;/strong&gt; - Optimized hot path performance (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13194&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13194&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;StaticVector for log listeners&lt;/strong&gt; - Compile-time sizing eliminates heap allocation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13196&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13196&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;zero-copy-api-protocol&quot;&gt;Zero-Copy API Protocol&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Zero-copy message handling is now complete and enabled by default for all protobuf messages (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12816&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12816&lt;/a&gt;), eliminating unnecessary memory copies during API communication. Combined with removing &lt;code dir=&quot;auto&quot;&gt;object_id&lt;/code&gt; from the wire protocol (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12818&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12818&lt;/a&gt;) and 33% smaller batch items (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13199&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13199&lt;/a&gt;), this provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;~42% more entities per packet&lt;/strong&gt; (24 → 34)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faster Home Assistant reconnects&lt;/strong&gt; - especially noticeable for large setups&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced protocol overhead&lt;/strong&gt; - no longer sending the name twice&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lower CPU usage&lt;/strong&gt; - zero-copy eliminates buffer allocations during message processing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;33% less RAM per queued message&lt;/strong&gt; - batch items reduced from 12 to 8 bytes&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;esp32-network-latency-reduction&quot;&gt;ESP32 Network Latency Reduction&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Socket operations on ESP32 now call &lt;code dir=&quot;auto&quot;&gt;lwip_read()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;lwip_write()&lt;/code&gt; directly instead of going through ESP-IDF’s VFS layer (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13179&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13179&lt;/a&gt;). This reduces latency for API connections, async TCP, and voice assistant components by eliminating unnecessary function pointer dispatches.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;psram-workaround-optimization&quot;&gt;PSRAM Workaround Optimization&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;ESP32 r3.0+ users with PSRAM can now save ~10KB of IRAM by setting &lt;code dir=&quot;auto&quot;&gt;minimum_chip_revision: &quot;3.0&quot;&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13074&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13074&lt;/a&gt;). This disables workarounds for silicon bugs that were fixed in newer chip revisions.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;libretiny-platform-improvements&quot;&gt;LibreTiny Platform Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;LibreTiny platforms (BK72xx, RTL87xx, LN882x) receive significant improvements that bring them closer to first-class platform status:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thread-safe logging&lt;/strong&gt; - Prevents buffer corruption and connection failures when non-main tasks log messages (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13062&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13062&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cortex-M4 atomics support&lt;/strong&gt; - Enables proper atomic operations on RTL87xx and LN882x platforms (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13191&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13191&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thread-safe WiFi&lt;/strong&gt; - Improved WiFi reliability in multi-threaded scenarios (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13191&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13191&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Board regeneration&lt;/strong&gt; - Updated board definitions with consolidated platform code (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13191&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13191&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deep sleep support&lt;/strong&gt; - BK7231n and BK7231t chips now support deep sleep with configurable timer and GPIO wake-up (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12267&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12267&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BLE stack disabled on BK7231N&lt;/strong&gt; - Saves ~21KB RAM and ~225KB flash since ESPHome has no BLE support on LibreTiny (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13131&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13131&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LibreTiny 1.9.2&lt;/strong&gt; - Fixes GPIO interrupt issues on LN882H that caused HLW8012/BL0937 power sensors to report zero (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13077&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13077&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-hardware-support&quot;&gt;New Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;rd-03d-mmwave-radar&quot;&gt;RD-03D mmWave Radar&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;rd03d&lt;/code&gt; component adds support for the Ai-Thinker RD-03D 24GHz millimeter-wave radar module with multi-target trajectory tracking (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12764&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12764&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-target tracking&lt;/strong&gt; - Tracks up to 3 simultaneous targets&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rich sensor data&lt;/strong&gt; - X, Y coordinates, speed, distance, and angle for each target&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;bthome-mithermometer&quot;&gt;BTHome MiThermometer&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;bthome_mithermometer&lt;/code&gt; platform enables receiving data from Xiaomi Mijia BLE sensors running PVVX firmware with BTHome v2 format (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12635&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12635&lt;/a&gt;). Starting with PVVX firmware version 6, BTHome v2 is the only supported format.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;air-quality-index-sensor&quot;&gt;Air Quality Index Sensor&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;A new standalone &lt;code dir=&quot;auto&quot;&gt;aqi&lt;/code&gt; sensor computes Air Quality Index from particulate matter readings (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12203&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12203&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12958&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12958&lt;/a&gt;). It supports both EPA AQI (US) and CAQI (European) calculation methods.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sensor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;pmsx003&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pm_2_5&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;pm25&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pm_10_0&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;pm10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;aqi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Air Quality Index&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pm_2_5&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;pm25&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pm_10_0&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;pm10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;calculation_type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;AQI&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# or CAQI for European standard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;zigbee-support-for-nrf52&quot;&gt;Zigbee Support for nRF52&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome now supports Zigbee on nRF52 platforms, bringing a new connectivity option alongside WiFi, Bluetooth, and Thread:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Binary sensor support&lt;/strong&gt; - Expose GPIO states via Zigbee (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11535&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11535&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensor support&lt;/strong&gt; - Expose ESPHome sensors via Zigbee’s Analog Input cluster with automatic unit mapping (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12187&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12187&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Switch support&lt;/strong&gt; - Control ESPHome switches via Zigbee as binary output (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13083&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13083&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;wipe_on_boot: once&lt;/code&gt;&lt;/strong&gt; - Wipe network settings only on first boot, preserving connections after OTA updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Framework version support&lt;/strong&gt; - Configure nRF-SDK version with experimental support for SDK 2.9.2 and 3.2.0 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12489&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12489&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;ota-rollback-support&quot;&gt;OTA Rollback Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESP32 devices using ESP-IDF now support automatic OTA rollback (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12460&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12460&lt;/a&gt;). When enabled (the default), the bootloader automatically rolls back to the previous firmware if the device crashes or resets before the boot is marked as successful.&lt;/p&gt;
&lt;p&gt;This feature works with the &lt;code dir=&quot;auto&quot;&gt;safe_mode&lt;/code&gt; component - after a successful boot (determined by the safe_mode boot timer), the firmware is marked as valid. If the device crashes before that point, it automatically rolls back.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Your bootloader must be compiled with the appropriate sdkconfig. If upgrading from an older bootloader, a serial flash may be required.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;platform--component-improvements&quot;&gt;Platform &amp;#x26; Component Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;ac-dimmer-esp-idf-support&quot;&gt;AC Dimmer ESP-IDF Support&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;ac_dimmer&lt;/code&gt; component now supports ESP-IDF framework in addition to Arduino (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7072&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#7072&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;dsmr-esp-idf-support&quot;&gt;DSMR ESP-IDF Support&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;dsmr&lt;/code&gt; component now supports ESP-IDF framework and fixes multiple bugs with the DSMR parsing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11036&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11036&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;esp32-camera-performance&quot;&gt;ESP32 Camera Performance&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;esp32_camera&lt;/code&gt; component received significant performance improvements (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12601&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12601&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;~10% more frames delivered&lt;/strong&gt; during streaming (510-523 vs 467-474 per 60 seconds)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;~50% reduction in idle CPU usage&lt;/strong&gt; by skipping work when no frames are pending&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lower latency&lt;/strong&gt; through burst frame delivery and immediate wake signals instead of polling&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;water-heater-component&quot;&gt;Water Heater Component&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome now includes a dedicated &lt;a href=&quot;https://esphome.io/components/water_heater&quot;&gt;water_heater&lt;/a&gt; entity type for controlling water heaters, boilers, and similar hot water appliances (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12498&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12498&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12516&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12516&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12511&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12511&lt;/a&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Template platform&lt;/strong&gt; - Full control via automations and lambdas&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiple operating modes&lt;/strong&gt; - Support for eco, gas, and custom modes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web server support&lt;/strong&gt; - Control and monitor via the built-in web interface&lt;/li&gt;
&lt;/ul&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;Home Assistant integration for water heater entities is not yet available. See &lt;a href=&quot;https://github.com/home-assistant/core/pull/159201&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;home-assistant/core#159201&lt;/a&gt; for progress.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;water_heater&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Boiler&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;supported_modes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;eco&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;gas&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;visual&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;min_temperature&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;10.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;max_temperature&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;85.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;experimental-irrf-proxy-component&quot;&gt;Experimental: IR/RF Proxy Component&lt;/h2&gt;&lt;/div&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;WARNING&lt;/p&gt;
&lt;p&gt;This component is experimental and the API is likely to change in future releases.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/ir_rf_proxy&quot;&gt;ir_rf_proxy&lt;/a&gt; component provides an API-accessible interface for transmitting and receiving infrared and RF signals, bridging Home Assistant with ESPHome’s existing &lt;code dir=&quot;auto&quot;&gt;remote_receiver&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;remote_transmitter&lt;/code&gt; components (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12985&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12985&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Home Assistant integration&lt;/strong&gt; - IR/RF transmission and reception exposed through the native API&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible hardware support&lt;/strong&gt; - Works with both infrared and RF configurations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raw timing arrays&lt;/strong&gt; - Maximum flexibility with minimal on-device processing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bidirectional operation&lt;/strong&gt; - Define multiple proxy instances for transmit and receive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This component is part of a broader effort to make IR &amp;#x26; RF easier to use from within Home Assistant. A new experimental &lt;code dir=&quot;auto&quot;&gt;infrared&lt;/code&gt; entity platform (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13129&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13129&lt;/a&gt;) provides the underlying infrastructure.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;infrared&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ir_rf_proxy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;IR Proxy Transmitter&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;remote_transmitter_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ir_tx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ir_rf_proxy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;IR Proxy Receiver&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;remote_receiver_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ir_rx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;additional-features&quot;&gt;Additional Features&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UART event component&lt;/strong&gt; - Trigger ESPHome events when receiving specific UART sequences (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11765&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11765&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Templatable MQTT topics&lt;/strong&gt; - Dynamic state and command topics via lambdas (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12441&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12441&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update check action&lt;/strong&gt; - Trigger HTTP-based update checks from automations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12415&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12415&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SPI flexible data rates&lt;/strong&gt; - Any achievable data rate within 5% can now be specified (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12753&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12753&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hub75 improvements&lt;/strong&gt; - Rotation support, expanded bit depths (4-12), and brightness action (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12674&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12674&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12521&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12521&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 CAN listen-only mode&lt;/strong&gt; - Passive bus monitoring without sending ACK signals (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13084&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13084&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MMC5603 temperature compensation&lt;/strong&gt; - Eliminates thermal variation in magnetometer readings (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12556&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12556&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MHZ19 configurable detection range&lt;/strong&gt; - Set detection range at setup or dynamically via action (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12677&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12677&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 RMT LED strip inverted logic&lt;/strong&gt; - Support for simple transistor-based level shifters (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12825&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12825&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 Hosted HTTP updates&lt;/strong&gt; - Fetch coprocessor firmware from remote manifests (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13090&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13090&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thermostat boolean heat_cool_mode&lt;/strong&gt; - Simplified configuration without requiring automations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/13069&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13069&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;platform-changes&quot;&gt;Platform Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP32&lt;/strong&gt;: ESP-IDF is now the default framework for ESP32, ESP32-C3, ESP32-S2, and ESP32-S3. Users who relied on the implicit Arduino default must now explicitly specify &lt;code dir=&quot;auto&quot;&gt;type: arduino&lt;/code&gt; if they need Arduino-specific features or have components that don’t yet support ESP-IDF (such as &lt;code dir=&quot;auto&quot;&gt;heatpumpir&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;midea&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;light&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;wled&lt;/code&gt; effect). &lt;a href=&quot;https://github.com/esphome/esphome/pull/12746&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12746&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP8266&lt;/strong&gt;: Unused Arduino Serial objects are now excluded from builds. Users who directly use &lt;code dir=&quot;auto&quot;&gt;Serial&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;Serial1&lt;/code&gt; in lambdas must now explicitly enable them with &lt;code dir=&quot;auto&quot;&gt;enable_serial: true&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;enable_serial1: true&lt;/code&gt; under the &lt;code dir=&quot;auto&quot;&gt;esp8266:&lt;/code&gt; configuration. Most users are unaffected as Serial usage typically goes through the &lt;code dir=&quot;auto&quot;&gt;uart&lt;/code&gt; component. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12736&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12736&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP8266&lt;/strong&gt;: Unused waveform code is now excluded from builds when &lt;code dir=&quot;auto&quot;&gt;esp8266_pwm&lt;/code&gt; is not used, saving 596 bytes of RAM. Users who directly use Arduino waveform functions in lambdas must add an &lt;code dir=&quot;auto&quot;&gt;esp8266_pwm&lt;/code&gt; component to their configuration. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12690&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12690&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;security-changes&quot;&gt;Security Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;API&lt;/strong&gt;: Password authentication has been removed after being deprecated since May 2022. Configurations with &lt;code dir=&quot;auto&quot;&gt;password:&lt;/code&gt; will fail to build. Users must migrate to &lt;code dir=&quot;auto&quot;&gt;encryption:&lt;/code&gt; with a key generated via &lt;code dir=&quot;auto&quot;&gt;openssl rand -base64 32&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12819&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12819&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;api&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;encryption&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!secret&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;api_encryption_key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;OTA&lt;/strong&gt;: ESPHome versions before 2025.10.0 cannot perform OTA updates to devices running this version. MD5 authentication support has been removed; SHA256 is now mandatory. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12707&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12707&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sprinkler&lt;/strong&gt;: Internal latching valve support has been removed. The configuration variables &lt;code dir=&quot;auto&quot;&gt;pump_pulse_duration&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pump_off_switch_id&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pump_on_switch_id&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;valve_pulse_duration&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;valve_off_switch_id&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;valve_on_switch_id&lt;/code&gt; are no longer available. Users with latching valves must now use an &lt;a href=&quot;https://esphome.io/components/switch/hbridge&quot;&gt;H-Bridge switch&lt;/a&gt; with the standard &lt;code dir=&quot;auto&quot;&gt;valve_switch_id&lt;/code&gt; and/or &lt;code dir=&quot;auto&quot;&gt;pump_switch_id&lt;/code&gt; configuration. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12603&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12603&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Web Server&lt;/strong&gt;: URLs now use entity names instead of sanitized &lt;code dir=&quot;auto&quot;&gt;object_id&lt;/code&gt; values. Old URLs (e.g., &lt;code dir=&quot;auto&quot;&gt;/sensor/temperature_sensor&lt;/code&gt;) still work but are deprecated and will be removed in 2026.7.0. Additionally, the &lt;code dir=&quot;auto&quot;&gt;/&lt;/code&gt; character is no longer allowed in entity, device, or area names (reserved as URL path separator), and names are limited to 120 characters maximum. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12627&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12627&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP32 Hosted&lt;/strong&gt;: The update configuration now requires an explicit &lt;code dir=&quot;auto&quot;&gt;type:&lt;/code&gt; field. Existing embedded mode configurations must add &lt;code dir=&quot;auto&quot;&gt;type: embedded&lt;/code&gt;. A new &lt;code dir=&quot;auto&quot;&gt;type: http&lt;/code&gt; mode allows fetching firmware from remote manifests. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13090&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13090&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HM3301&lt;/strong&gt;: The AQI sensor configuration has been refactored into a shared &lt;code dir=&quot;auto&quot;&gt;aqi&lt;/code&gt; component. Existing &lt;code dir=&quot;auto&quot;&gt;aqi:&lt;/code&gt; configurations under &lt;code dir=&quot;auto&quot;&gt;hm3301&lt;/code&gt; continue to work but the implementation is now shared with &lt;code dir=&quot;auto&quot;&gt;pmsx003&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12203&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12203&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MMC5603&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;auto_set_reset&lt;/code&gt; option is now enabled by default to eliminate temperature-related drift. This reduces maximum read frequency from 150Hz to 75Hz. Users requiring high-frequency reads can set &lt;code dir=&quot;auto&quot;&gt;auto_set_reset: false&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12556&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12556&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ultrasonic&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;timeout&lt;/code&gt; option is deprecated and will be removed in 2026.8.0. A fixed 80ms measurement timeout is now used to fix reliability issues with some SR04 sensors that have a 12.3ms delay before sending pulses. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12897&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12897&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;behavior-changes&quot;&gt;Behavior Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;API&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;on_client_disconnected&lt;/code&gt; trigger now fires after the client is removed from the connection list, so &lt;code dir=&quot;auto&quot;&gt;api.connected&lt;/code&gt; correctly reflects the true connection state. Users who added &lt;code dir=&quot;auto&quot;&gt;delay: 1ms&lt;/code&gt; workarounds can remove them. Users who relied on the disconnecting client still being counted may need to adjust their logic. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13088&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13088&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Display Drivers&lt;/strong&gt;: Multiple display drivers now correctly honor clipping for &lt;code dir=&quot;auto&quot;&gt;fill()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;clear()&lt;/code&gt; operations. Code that relied on the previous (incorrect) behavior where fills ignored clipping regions may produce different results. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12808&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12808&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Build Info&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;compilation_time&lt;/code&gt; field in the native API now correctly updates on every compile (previously only updated when &lt;code dir=&quot;auto&quot;&gt;main.cpp&lt;/code&gt; was rebuilt). The version text sensor format has changed to include config hash. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12425&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12425&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;deprecations&quot;&gt;Deprecations&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;custom_components folder&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;custom_components&lt;/code&gt; folder is deprecated and will be removed in 2026.6.0. Users should migrate to &lt;code dir=&quot;auto&quot;&gt;external_components&lt;/code&gt; instead. A warning appears if the folder exists and contains files. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12552&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12552&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;lambda-api-changes&quot;&gt;Lambda API Changes&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Users with lambdas that access component state should note the following changes. These methods now return &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt;, which is safer but requires minor syntax changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fan&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_preset_mode()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt;. Use &lt;code dir=&quot;auto&quot;&gt;.empty()&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;!= nullptr&lt;/code&gt; checks, and &lt;code dir=&quot;auto&quot;&gt;==&lt;/code&gt; for string comparison instead of &lt;code dir=&quot;auto&quot;&gt;strcmp()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13092&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13092&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Select&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;current_option()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt;. Use &lt;code dir=&quot;auto&quot;&gt;.empty()&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;!= nullptr&lt;/code&gt; checks. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13095&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13095&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Climate&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_custom_fan_mode()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;get_custom_preset()&lt;/code&gt; return &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt;. Use &lt;code dir=&quot;auto&quot;&gt;has_custom_fan_mode()&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;.empty()&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;!= nullptr&lt;/code&gt; checks. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13103&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_last_event_type()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt;. Use &lt;code dir=&quot;auto&quot;&gt;has_event()&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;.empty()&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;!= nullptr&lt;/code&gt; checks. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13104&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13104&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Light&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_effect_name()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13105&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13105&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Application API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;get_compilation_time()&lt;/code&gt; deprecated (removal 2026.7.0), &lt;code dir=&quot;auto&quot;&gt;get_compilation_time_ref()&lt;/code&gt; removed. Use &lt;code dir=&quot;auto&quot;&gt;get_build_time()&lt;/code&gt; (Unix timestamp), &lt;code dir=&quot;auto&quot;&gt;get_config_hash()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_config_version_hash()&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;get_build_time_string(buffer)&lt;/code&gt; instead. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12425&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12425&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fan API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;Fan::get_preset_mode()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt;. Returns empty ref when no preset is set. Use &lt;code dir=&quot;auto&quot;&gt;has_preset_mode()&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;.empty()&lt;/code&gt; instead of nullptr checks. New &lt;code dir=&quot;auto&quot;&gt;apply_preset_mode_(call)&lt;/code&gt; helper for derived classes. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13092&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13092&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Select API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;Select::current_option()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt;. Returns empty ref when no state is set. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13095&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13095&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Climate API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;Climate::get_custom_fan_mode()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;Climate::get_custom_preset()&lt;/code&gt; return &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt;. New &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; overloads for &lt;code dir=&quot;auto&quot;&gt;set_custom_fan_mode_()&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;set_custom_preset_()&lt;/code&gt; protected setters. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13103&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13103&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;Event::get_last_event_type()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt;. New &lt;code dir=&quot;auto&quot;&gt;has_event()&lt;/code&gt; method added. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13104&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13104&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Light API&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;LightEffect::get_name()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt;. &lt;code dir=&quot;auto&quot;&gt;LightState::get_effect_name()&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;StringRef&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;. New &lt;code dir=&quot;auto&quot;&gt;str_equals_case_insensitive(StringRef, StringRef)&lt;/code&gt; helper in &lt;code dir=&quot;auto&quot;&gt;helpers.h&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/13105&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13105&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP8266 Serial&lt;/strong&gt;: External components using Arduino &lt;code dir=&quot;auto&quot;&gt;Serial&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;Serial1&lt;/code&gt; directly must call &lt;code dir=&quot;auto&quot;&gt;enable_serial()&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;enable_serial1()&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;esphome.components.esp8266.const&lt;/code&gt; in their &lt;code dir=&quot;auto&quot;&gt;to_code()&lt;/code&gt; function. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12736&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12736&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the &lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2026-1-1---january-22&quot;&gt;Release 2026.1.1 - January 22&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[wifi] Process scan results one at a time to avoid heap allocation &lt;a href=&quot;https://github.com/esphome/esphome/pull/13400&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13400&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Validate LVGL dropdown symbols require Unicode codepoint ≥ 0x100 &lt;a href=&quot;https://github.com/esphome/esphome/pull/13394&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13394&lt;/a&gt; by &lt;a href=&quot;https://github.com/apps/copilot-swe-agent&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Copilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Fix verify_ssl: false not working on ESP32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/13422&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13422&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Add warning for experimental 400MHz on ESP32-P4 &lt;a href=&quot;https://github.com/esphome/esphome/pull/13433&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13433&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix bk72xx manual_ip preventing API connection &lt;a href=&quot;https://github.com/esphome/esphome/pull/13426&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13426&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[spi] Fix display init failure by marking displays as write-only for half-duplex mode &lt;a href=&quot;https://github.com/esphome/esphome/pull/13431&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13431&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Fix OTA failures on ESP8266/Arduino by making read semantics consistent &lt;a href=&quot;https://github.com/esphome/esphome/pull/13435&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13435&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[dht] Increase delay for DHT22 and RHT03 &lt;a href=&quot;https://github.com/esphome/esphome/pull/13446&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13446&lt;/a&gt; by &lt;a href=&quot;https://github.com/rguca&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rguca&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Limit Nagle batching for log messages to reduce LWIP buffer pressure &lt;a href=&quot;https://github.com/esphome/esphome/pull/13439&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13439&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix stale error_from_callback_ causing immediate connection failures &lt;a href=&quot;https://github.com/esphome/esphome/pull/13450&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13450&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[fingerprint_grow] Use buffer-based dump_summary to fix deprecation warnings &lt;a href=&quot;https://github.com/esphome/esphome/pull/13447&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13447&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[aqi] Remove unit_of_measurement to fix Home Assistant warning &lt;a href=&quot;https://github.com/esphome/esphome/pull/13448&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13448&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[time] Always call time sync callbacks even when time unchanged &lt;a href=&quot;https://github.com/esphome/esphome/pull/13456&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13456&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-1-2---january-25&quot;&gt;Release 2026.1.2 - January 25&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[st7701s] Fix dump_summary deprecation warning &lt;a href=&quot;https://github.com/esphome/esphome/pull/13462&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13462&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_rgb] Fix dump_summary deprecation warning &lt;a href=&quot;https://github.com/esphome/esphome/pull/13463&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13463&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rpi_dpi_rgb] Fix dump_summary deprecation warning &lt;a href=&quot;https://github.com/esphome/esphome/pull/13461&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13461&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ir_rf_proxy] Remove unnecessary headers, add tests &lt;a href=&quot;https://github.com/esphome/esphome/pull/13464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13464&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_rgb] Add software reset command to st7701s init sequence &lt;a href=&quot;https://github.com/esphome/esphome/pull/13470&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13470&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[slow_pwm] Fix dump_summary deprecation warning &lt;a href=&quot;https://github.com/esphome/esphome/pull/13460&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13460&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sen5x] Fix store baseline functionality &lt;a href=&quot;https://github.com/esphome/esphome/pull/13469&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13469&lt;/a&gt; by &lt;a href=&quot;https://github.com/mikelawrence&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@mikelawrence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix setting empty text &lt;a href=&quot;https://github.com/esphome/esphome/pull/13494&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13494&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[light] Fix cwww state restore &lt;a href=&quot;https://github.com/esphome/esphome/pull/13493&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13493&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rd03d] Fix speed and resolution field order &lt;a href=&quot;https://github.com/esphome/esphome/pull/13495&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13495&lt;/a&gt; by &lt;a href=&quot;https://github.com/jasstrong&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jasstrong&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[modbus_controller] Fix YAML serialization error with custom_command &lt;a href=&quot;https://github.com/esphome/esphome/pull/13482&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13482&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[i2c] Increase ESP-IDF I2C transaction timeout from 20ms to 100ms &lt;a href=&quot;https://github.com/esphome/esphome/pull/13483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13483&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix watchdog timeout on P4 WiFi scan &lt;a href=&quot;https://github.com/esphome/esphome/pull/13520&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13520&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix scan flag race condition causing reconnect failure on ESP8266/LibreTiny &lt;a href=&quot;https://github.com/esphome/esphome/pull/13514&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13514&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-1-3---january-29&quot;&gt;Release 2026.1.3 - January 29&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Update webserver local assets to 20260122-204614 &lt;a href=&quot;https://github.com/esphome/esphome/pull/13455&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13455&lt;/a&gt; by &lt;a href=&quot;https://github.com/esphomebot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphomebot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mhz19] Fix Uninitialized var warning message &lt;a href=&quot;https://github.com/esphome/esphome/pull/13526&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13526&lt;/a&gt; by &lt;a href=&quot;https://github.com/sebcaps&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@sebcaps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ota] Improve error message when device closes connection without responding &lt;a href=&quot;https://github.com/esphome/esphome/pull/13562&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13562&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[socket] ESP8266: call delay(0) instead of esp_delay(0, cb) for zero timeout &lt;a href=&quot;https://github.com/esphome/esphome/pull/13530&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13530&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[web_server] Add name_id to SSE for entity ID format migration &lt;a href=&quot;https://github.com/esphome/esphome/pull/13535&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13535&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Update webserver local assets to 20260127-190637 &lt;a href=&quot;https://github.com/esphome/esphome/pull/13573&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13573&lt;/a&gt; by &lt;a href=&quot;https://github.com/esphomebot&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@esphomebot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2450] preserve precision of angle &lt;a href=&quot;https://github.com/esphome/esphome/pull/13600&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13600&lt;/a&gt; by &lt;a href=&quot;https://github.com/ccutrer&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ccutrer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix ESP8266 yield panic when WiFi scan fails &lt;a href=&quot;https://github.com/esphome/esphome/pull/13603&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13603&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Fix empty body for chunked transfer encoding responses &lt;a href=&quot;https://github.com/esphome/esphome/pull/13599&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13599&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-1-4---february-4&quot;&gt;Release 2026.1.4 - February 4&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[mipi_spi] Fix log_pin() FlashStringHelper compatibility &lt;a href=&quot;https://github.com/esphome/esphome/pull/13624&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13624&lt;/a&gt; by &lt;a href=&quot;https://github.com/J0k3r2k1&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@J0k3r2k1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[max7219] Allocate buffer in constructor &lt;a href=&quot;https://github.com/esphome/esphome/pull/13660&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13660&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mqtt] resolve warnings related to use of ip.str() &lt;a href=&quot;https://github.com/esphome/esphome/pull/13719&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13719&lt;/a&gt; by &lt;a href=&quot;https://github.com/rwrozelle&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@rwrozelle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Add missing uint32_t ID overloads for defer() and cancel_defer() &lt;a href=&quot;https://github.com/esphome/esphome/pull/13720&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13720&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Fix requests taking full timeout when response is already complete &lt;a href=&quot;https://github.com/esphome/esphome/pull/13649&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13649&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[cse7766] Fix power reading stuck when load switches off &lt;a href=&quot;https://github.com/esphome/esphome/pull/13734&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13734&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix wifi.connected condition returning false in connect state listener automations &lt;a href=&quot;https://github.com/esphome/esphome/pull/13733&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13733&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ultrasonic] adjust timeouts and bring the parameter back &lt;a href=&quot;https://github.com/esphome/esphome/pull/13738&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13738&lt;/a&gt; by &lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2026-1-5---february-11&quot;&gt;Release 2026.1.5 - February 11&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[rd03d] Revert incorrect field order swap &lt;a href=&quot;https://github.com/esphome/esphome/pull/13769&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13769&lt;/a&gt; by &lt;a href=&quot;https://github.com/jasstrong&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jasstrong&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Add capacity check to register_component_ &lt;a href=&quot;https://github.com/esphome/esphome/pull/13778&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13778&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ota] Fix CLI upload option shown when only http_request platform configured &lt;a href=&quot;https://github.com/esphome/esphome/pull/13784&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13784&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[dashboard] Close WebSocket after process exit to prevent zombie connections &lt;a href=&quot;https://github.com/esphome/esphome/pull/13834&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13834&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[nrf52,logger] fix printk &lt;a href=&quot;https://github.com/esphome/esphome/pull/13874&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13874&lt;/a&gt; by &lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix crash with unconfigured &lt;code dir=&quot;auto&quot;&gt;top_layer&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/13846&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13846&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Set UV_CACHE_DIR inside data dir so Clean All clears it &lt;a href=&quot;https://github.com/esphome/esphome/pull/13888&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13888&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[aqi] Fix AQI calculation for specific pm2.5 or pm10 readings &lt;a href=&quot;https://github.com/esphome/esphome/pull/13770&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13770&lt;/a&gt; by &lt;a href=&quot;https://github.com/xconverge&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@xconverge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2026.1.0/&quot;&gt;full 2026.1.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2025.12.0: API action responses and HUB75 matrix displays</title><link>https://esphome.io/blog/2025/12/17/esphome-2025-12/</link><guid isPermaLink="true">https://esphome.io/blog/2025/12/17/esphome-2025-12/</guid><description>ESPHome 2025.12.0 introduces API action responses, conditional package inclusion, and HUB75 LED matrix display support, along with memory optimizations and eight new components.</description><pubDate>Wed, 17 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/time/bm8563/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bm8563.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;BM8​5​6​3​ ​RTC&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/cc1101/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/cc1101.webp&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;CC1​1​0​1​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hc8/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/hc8.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;HC8​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hlw8032/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/hlw8032.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;HLW8​0​3​2​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/display/hub75/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/hub75.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;HUB7​5​ ​LED ​Matrix&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/stts22h/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/stts22h.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;STTS2​2​H&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/thermopro_ble/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/thermopro_tp357.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;ThermoPro ​BLE&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/usb_cdc_acm/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/usb.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;USB ​CDC-​ACM&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2025.12.0 introduces API action responses for bidirectional communication with Home Assistant, conditional package inclusion for dynamic configurations, and HUB75 LED matrix display support. This release delivers significant memory optimizations saving up to 10KB of IRAM on ESP32 devices, eliminates per-packet heap allocations in API connections and socket latency on ESP8266, and adds 8 new components including the CC1101 sub-GHz transceiver and USB CDC-ACM support. LVGL receives multiple usability improvements, and the WiFi component has been refactored for instant callback-based updates across all platforms.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;api-action-responses&quot;&gt;API Action Responses&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://esphome.io/components/api&quot;&gt;Native API&lt;/a&gt; now supports actions that send structured responses back to clients like Home Assistant, enabling true bidirectional communication where actions return success/error status and JSON data payloads (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12136&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12136&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status responses&lt;/strong&gt; - Report success or failure with optional error messages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data responses&lt;/strong&gt; - Return structured JSON data from actions using ArduinoJson&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-detection&lt;/strong&gt; - Response mode automatically detected based on &lt;code dir=&quot;auto&quot;&gt;api.respond&lt;/code&gt; usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Three modes&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;none&lt;/code&gt; (fire and forget), &lt;code dir=&quot;auto&quot;&gt;status&lt;/code&gt; (success/error only), or &lt;code dir=&quot;auto&quot;&gt;optional&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;only&lt;/code&gt; (with data)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This unlocks new use cases like query-type actions that return device configuration, sensor readings, or diagnostic information directly to Home Assistant.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;api&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;actions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;action&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;get_sensor_reading&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;variables&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;sensor_name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;api.respond&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!lambda&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;root[&quot;sensor&quot;] = sensor_name;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;root[&quot;value&quot;] = 42.5;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;root[&quot;unit&quot;] = &quot;°C&quot;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;conditional-package-inclusion&quot;&gt;Conditional Package Inclusion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://esphome.io/components/packages&quot;&gt;packages&lt;/a&gt; system now supports conditional inclusion, a long-awaited feature that enables dynamic configuration based on substitution variables (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11605&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11605&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Conditional imports&lt;/strong&gt; - Include packages based on boolean conditions using Jinja2 expressions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Package merging after substitutions&lt;/strong&gt; - Packages are now merged after substitution resolution, enabling generated components to merge correctly with manually defined ones&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LVGL extend support&lt;/strong&gt; - The &lt;code dir=&quot;auto&quot;&gt;!extend&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;!remove&lt;/code&gt; directives now work with LVGL-style configurations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11534&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11534&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;substitutions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;network_package&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;network.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;network_enabled&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;packages&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;${ network_enabled and network_package or {} }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This enables creating reusable configuration templates that adapt to different hardware variants or deployment scenarios.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;hub75-led-matrix-display-support&quot;&gt;HUB75 LED Matrix Display Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/display/hub75&quot;&gt;hub75&lt;/a&gt; component brings native support for HUB75 LED matrix panels, enabling large-format LED displays for information dashboards, signage, and creative projects (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11153&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11153&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiple ESP32 variants&lt;/strong&gt; - Supports ESP32 (I2S), ESP32-S3 (LCD CAM + GDMA), and ESP32-P4 (PARLIO)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible configuration&lt;/strong&gt; - Configurable panel dimensions, clock speed, and pin assignments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LVGL compatible&lt;/strong&gt; - Works seamlessly with LVGL for rich graphical interfaces&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Board presets&lt;/strong&gt; - Pre-configured settings for popular boards like Apollo Automation M1&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;cc1101-sub-1ghz-transceiver&quot;&gt;CC1101 Sub-1GHz Transceiver&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/cc1101&quot;&gt;cc1101&lt;/a&gt; component adds support for the Texas Instruments CC1101 Sub-1GHz transceiver, enabling 433MHz remote control integration and other sub-GHz wireless applications (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11849&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11849&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;433.92MHz support&lt;/strong&gt; - Perfect for integrating 433MHz remotes and sensors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ASK/OOK modulation&lt;/strong&gt; - Works with common remote control protocols&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core integration&lt;/strong&gt; - Designed to work with &lt;code dir=&quot;auto&quot;&gt;remote_receiver&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;remote_transmitter&lt;/code&gt; components&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Robust initialization&lt;/strong&gt; - Non-blocking state machine with proper chip reset handling&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;usb-cdc-acm-support&quot;&gt;USB CDC-ACM Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/usb_cdc_acm&quot;&gt;usb_cdc_acm&lt;/a&gt; component enables USB virtual serial port functionality on ESP32-S2 and ESP32-S3 devices (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11687&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11687&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-interface support&lt;/strong&gt; - Up to 2 independent CDC-ACM interfaces per device&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configurable buffers&lt;/strong&gt; - Adjustable RX/TX ring buffer sizes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line state callbacks&lt;/strong&gt; - Notifications for DTR, RTS, baud rate, and other line coding changes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bridge-ready&lt;/strong&gt; - Designed to connect USB serial interfaces to UART or other serial interfaces&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;wifi-info-callback-architecture&quot;&gt;WiFi Info Callback Architecture&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The WiFi component has been refactored from polling-based updates to event-driven callbacks, significantly improving responsiveness (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10748&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10748&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Immediate updates&lt;/strong&gt; - WiFi info sensors now update instantly when state changes instead of waiting for poll intervals&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced overhead&lt;/strong&gt; - Eliminates continuous polling in wifi_info sensors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform consistency&lt;/strong&gt; - All platforms (ESP8266, ESP32, LibreTiny, Pico W) now use the same callback infrastructure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New power save mode sensor&lt;/strong&gt; - Reports current WiFi power save mode (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11480&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11480&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AP active condition&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;wifi.ap_active&lt;/code&gt; condition for automation triggers (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11852&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11852&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;low-latency-uart-processing&quot;&gt;Low Latency UART Processing&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The UART component now supports a &lt;code dir=&quot;auto&quot;&gt;wake_loop_on_rx&lt;/code&gt; flag that wakes the main loop immediately when data arrives, enabling near-real-time serial processing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12172&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12172&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Z-Wave Proxy performance&lt;/strong&gt; - Reduces latency by ~10ms for WiFi-connected &lt;a href=&quot;https://www.home-assistant.io/blog/2025/10/13/portable-z-wave-with-wifi-and-poe/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ZWA-2 devices&lt;/a&gt;, building on the USB-connected Ethernet/PoE optimizations from 2025.11.0 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12135&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12135&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-time serial applications&lt;/strong&gt; - Any component requiring fast response to incoming serial data can now achieve sub-millisecond wake times by enabling this flag in their code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic infrastructure&lt;/strong&gt; - The socket wake infrastructure is automatically enabled when any UART requests RX wake&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;esp8266-socket-latency-elimination&quot;&gt;ESP8266 Socket Latency Elimination&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESP8266 previously had higher network latency than ESP32 and LibreTiny because it used polling for socket data, sleeping up to 16ms before discovering incoming data. This affected every API request and Home Assistant command. The loop now wakes within microseconds of data arriving using ESP8266’s &lt;code dir=&quot;auto&quot;&gt;esp_schedule()&lt;/code&gt; mechanism, bringing ESP8266 to near parity with ESP32 and LibreTiny. This is automatic for all ESP8266 devices with no configuration needed (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12397&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12397&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;memory-and-iram-optimizations&quot;&gt;Memory and IRAM Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release includes substantial memory optimizations, particularly for ESP32 devices using ESP-IDF:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FreeRTOS and Ring Buffer Flash Placement:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;~8KB IRAM savings&lt;/strong&gt; - FreeRTOS functions moved to flash by default (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12182&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12182&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;~1.5KB additional IRAM savings&lt;/strong&gt; - Ring buffer functions moved to flash (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12184&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12184&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escape hatches&lt;/strong&gt; - Use &lt;code dir=&quot;auto&quot;&gt;freertos_in_iram: true&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;ringbuf_in_iram: true&lt;/code&gt; if issues occur&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These changes prepare ESPHome for ESP-IDF 6.0 where flash placement becomes the default.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BLE Client Memory Reduction:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;24-40 bytes per BLE client&lt;/strong&gt; - Replaced &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; with fixed &lt;code dir=&quot;auto&quot;&gt;char[18]&lt;/code&gt; for MAC address storage (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12070&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12070&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Text Sensor Optimization:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;24-32 bytes per text sensor&lt;/strong&gt; - Eliminated duplicate string storage when no filters configured (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12205&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12205&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Dashboard Import Optimization:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Eliminates URL heap allocation&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Package import URL is now stored as a pointer to &lt;code dir=&quot;auto&quot;&gt;.rodata&lt;/code&gt; instead of a heap-allocated &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On ESP32, &lt;code dir=&quot;auto&quot;&gt;.rodata&lt;/code&gt; resides in flash, providing RAM savings.&lt;/li&gt;
&lt;li&gt;On ESP8266, &lt;code dir=&quot;auto&quot;&gt;.rodata&lt;/code&gt; is in RAM, but this still avoids heap overhead.&lt;/li&gt;
&lt;li&gt;(&lt;a href=&quot;https://github.com/esphome/esphome/pull/11951&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11951&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Connection Optimizations:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The API connection layer received significant optimizations to reduce heap fragmentation and memory churn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Eliminated per-packet heap allocation&lt;/strong&gt; - Previously every API packet received required a new heap allocation. The receive buffer is now reused across packets, with excess capacity released after initial sync completes. This reduces heap fragmentation on busy devices. For quiet devices, the initial sync memory spike is released rather than held for the lifetime of the connection. (Connections can last for months.) (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12133&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12133&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-copy API commands&lt;/strong&gt; - Select and light effect commands now process strings directly from protobuf buffer without heap allocation (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12329&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12329&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12384&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12384&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flash storage for device info&lt;/strong&gt; - Device info strings stored in flash on ESP8266 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12173&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12173&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flash storage for state subscriptions&lt;/strong&gt; - Home Assistant state subscriptions stored in flash instead of heap (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12008&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12008&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced service call storage&lt;/strong&gt; - Home Assistant service call strings use less heap (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12151&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12151&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APINoiseContext optimization&lt;/strong&gt; - Removed shared_ptr overhead (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11981&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11981&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loop-based reboot timeout&lt;/strong&gt; - Avoids scheduler heap churn (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12291&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12291&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Sensor Timeout Filter Optimization:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Eliminates scheduler heap churn&lt;/strong&gt; - Timeout filters now use a loop-based implementation instead of scheduler timeouts. This is particularly important for LD2410/LD2420/LD2450 users with many timeout filters, where the old implementation caused ~70 heap operations/second and constant scheduler pool exhaustion when someone was in range of the sensor (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11922&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11922&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;new-hardware-support&quot;&gt;New Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release adds support for 8 new components and numerous display models:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Sensor Components:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hlw8032&quot;&gt;hlw8032&lt;/a&gt; - Single-phase power metering IC (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7241&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#7241&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/stts22h&quot;&gt;stts22h&lt;/a&gt; - High-accuracy temperature sensor (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11778&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11778&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/thermopro_ble&quot;&gt;thermopro_ble&lt;/a&gt; - ThermoPro BLE temperature/humidity sensors (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11835&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11835&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hc8&quot;&gt;hc8&lt;/a&gt; - HC8 CO2 sensor (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11872&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11872&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New Time Component:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/time/bm8563&quot;&gt;bm8563&lt;/a&gt; - BM8563 I2C RTC (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11616&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11616&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New Display Models:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Waveshare 4.26” e-paper with SSD1677 controller (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11887&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11887&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Waveshare S3 LCD 3.16” (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12309&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12309&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Guition JC4827W543 480x272 display (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12034&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12034&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Guition JC4880P443 480x800 MIPI DSI display (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12068&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12068&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;M5Stack Core2 display (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12301&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12301&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Platform Enhancements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ESP32-C5 PSRAM support with quad mode and speeds up to 120MHz (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12215&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12215&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Seeed XIAO ESP32-C6 board definition (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12307&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12307&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Remote transmitter/receiver support for RP2040 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12048&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12048&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;nRF52 DC-DC converter settings (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11841&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11841&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;lvgl-improvements&quot;&gt;LVGL Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Multiple enhancements improve the LVGL experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Direct button text&lt;/strong&gt; - Set &lt;code dir=&quot;auto&quot;&gt;text:&lt;/code&gt; directly on buttons without nested label widgets (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11964&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11964&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto row/column padding&lt;/strong&gt; - &lt;code dir=&quot;auto&quot;&gt;pad_all&lt;/code&gt; now applies to inter-row/column spacing in flex layouts (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11879&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11879&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display sync option&lt;/strong&gt; - New &lt;code dir=&quot;auto&quot;&gt;update_when_display_idle&lt;/code&gt; option syncs LVGL updates with display refresh (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11896&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11896&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced arc widget&lt;/strong&gt; - More arc parameters available in update actions (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12066&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12066&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scroll properties&lt;/strong&gt; - Added missing scroll-related configuration options (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11901&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11901&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;component-enhancements&quot;&gt;Component Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Gree Climate:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New &lt;code dir=&quot;auto&quot;&gt;turbo&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;light&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;health&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;xfan&lt;/code&gt; switches for supported models (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12160&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12160&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Climate IR:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optional humidity sensor support (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9805&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9805&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;SPS30 Particulate Sensor:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Idle mode functionality to extend sensor life and reduce power consumption (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12255&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12255&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;PCA9685 PWM:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Phase balancer option to fix LED flickering during animations (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9792&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9792&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Prometheus:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Event and text component metrics support (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10240&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10240&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;MCP3204 ADC:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Differential mode measurement support (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7436&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#7436&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;developer-features&quot;&gt;Developer Features&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;IDF Component Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shorthand syntax for ESP-IDF components like &lt;code dir=&quot;auto&quot;&gt;espressif/esp_hosted^2.6.6&lt;/code&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12127&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12127&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;YAML can now override component versions defined in code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Enhancements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;state_subscription_only&lt;/code&gt; flag for reliable API connection detection without logger false positives (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11906&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11906&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;New &lt;code dir=&quot;auto&quot;&gt;measurement_angle&lt;/code&gt; state class for angle sensors (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12085&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12085&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Micronova&lt;/strong&gt;: Multiple configuration changes (&lt;a href=&quot;https://github.com/esphome/esphome/pull/12226&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12226&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12318&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12318&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/12371&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12371&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;update_interval&lt;/code&gt; moved from hub to individual entities - remove from &lt;code dir=&quot;auto&quot;&gt;micronova:&lt;/code&gt; section and add to each sensor/text_sensor&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;memory_location&lt;/code&gt; now restricted to read locations (0x00-0x79) - subtract 0x80 from values above 0x79&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;memory_write_location&lt;/code&gt; removed from number entities (now calculated automatically)&lt;/li&gt;
&lt;li&gt;Custom button/sensor entities now require explicit &lt;code dir=&quot;auto&quot;&gt;memory_location&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;address&lt;/code&gt; configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Prometheus&lt;/strong&gt;: Light color metrics (&lt;code dir=&quot;auto&quot;&gt;light_color_*&lt;/code&gt;) are now only generated if the light component supports those color modes. This reduces memory usage on ESP8266 but may affect monitoring setups that expected all metrics regardless of light capabilities. &lt;a href=&quot;https://github.com/esphome/esphome/pull/9530&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9530&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Text Sensor&lt;/strong&gt;: The public &lt;code dir=&quot;auto&quot;&gt;raw_state&lt;/code&gt; member has been removed. If you access &lt;code dir=&quot;auto&quot;&gt;.raw_state&lt;/code&gt; directly in a lambda, update to use &lt;code dir=&quot;auto&quot;&gt;.get_raw_state()&lt;/code&gt; instead. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12205&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12205&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;platform-changes&quot;&gt;Platform Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;I2C on ESP32-C5/C6/P4&lt;/strong&gt;: Fixed I2C port logic for chips with Low Power (LP) I2C ports. Users with multiple I2C buses on these chips may need to verify their port assignments. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12063&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12063&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;behavior-changes&quot;&gt;Behavior Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WiFi Info&lt;/strong&gt;: Text sensors now use callback-based updates instead of polling. Updates happen immediately when WiFi state changes rather than on fixed intervals. This improves responsiveness but may change timing behavior if your automations depended on the polling interval. &lt;a href=&quot;https://github.com/esphome/esphome/pull/10748&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10748&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Component::mark_failed() and status_set_error()&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt; overloads are deprecated and will be removed in 2026.6.0. Use &lt;code dir=&quot;auto&quot;&gt;LOG_STR()&lt;/code&gt; instead: &lt;code dir=&quot;auto&quot;&gt;this-&gt;mark_failed(LOG_STR(&quot;Error message&quot;))&lt;/code&gt;. This fixes dangling pointer bugs when passing temporary strings. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12021&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12021&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;BLEClientBase::address_str()&lt;/strong&gt;: Return type changed from &lt;code dir=&quot;auto&quot;&gt;const std::string&amp;#x26;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt;. Remove &lt;code dir=&quot;auto&quot;&gt;.c_str()&lt;/code&gt; calls: &lt;code dir=&quot;auto&quot;&gt;client-&gt;address_str()&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;client-&gt;address_str().c_str()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12070&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12070&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TextSensor::raw_state&lt;/strong&gt;: Changed from public member to protected &lt;code dir=&quot;auto&quot;&gt;raw_state_&lt;/code&gt;. Use &lt;code dir=&quot;auto&quot;&gt;get_raw_state()&lt;/code&gt; method instead of direct member access. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12205&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12205&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WiFi component callbacks&lt;/strong&gt;: New callback architecture with &lt;code dir=&quot;auto&quot;&gt;wifi_connect_state_callback_&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ip_state_callback_&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;wifi_scan_state_callback_&lt;/code&gt;. Automation triggers moved to &lt;code dir=&quot;auto&quot;&gt;automation.h&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/10748&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10748&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Micronova&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;MicroNovaFunctions&lt;/code&gt; enum removed - value interpretation now determined at compile time. The &lt;code dir=&quot;auto&quot;&gt;get_set_fan_speed_offset()&lt;/code&gt; public method removed from sensor entity. &lt;a href=&quot;https://github.com/esphome/esphome/pull/12363&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12363&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For detailed migration guides and API documentation, see the &lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome Developers Documentation&lt;/a&gt;.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2025-12-1---december-19&quot;&gt;Release 2025.12.1 - December 19&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[cc1101] Fix default frequencies &lt;a href=&quot;https://github.com/esphome/esphome/pull/12539&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12539&lt;/a&gt; by &lt;a href=&quot;https://github.com/anna-oake&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@anna-oake&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[pm1006] Fix “never” update interval detection &lt;a href=&quot;https://github.com/esphome/esphome/pull/12529&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12529&lt;/a&gt; by &lt;a href=&quot;https://github.com/jackwilsdon&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jackwilsdon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bme68x_bsec2_i2c] Add MULTI_CONF to fix multiple sensors &lt;a href=&quot;https://github.com/esphome/esphome/pull/12535&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12535&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_camera] Fix I2C driver conflict with other components &lt;a href=&quot;https://github.com/esphome/esphome/pull/12533&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12533&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[template.alarm_control_panel] Fix compile without binary_sensor &lt;a href=&quot;https://github.com/esphome/esphome/pull/12548&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12548&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble, esp32_ble_tracker] Fix crash, error messages when &lt;code dir=&quot;auto&quot;&gt;ble.disable&lt;/code&gt; called during boot &lt;a href=&quot;https://github.com/esphome/esphome/pull/12560&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12560&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-12-2---december-23&quot;&gt;Release 2025.12.2 - December 23&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[pca9685,sx126x,sx127x] Use frequency/float_range check &lt;a href=&quot;https://github.com/esphome/esphome/pull/12490&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12490&lt;/a&gt; by &lt;a href=&quot;https://github.com/ximex&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ximex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix for &lt;code dir=&quot;auto&quot;&gt;wifi_info&lt;/code&gt; when static IP is configured &lt;a href=&quot;https://github.com/esphome/esphome/pull/12576&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12576&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[display_menu_base] Call on_value_ after updating the select &lt;a href=&quot;https://github.com/esphome/esphome/pull/12584&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12584&lt;/a&gt; by &lt;a href=&quot;https://github.com/ellull&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ellull&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[hub75] Bump esp-hub75 version to 0.1.7 &lt;a href=&quot;https://github.com/esphome/esphome/pull/12564&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12564&lt;/a&gt; by &lt;a href=&quot;https://github.com/stuartparmenter&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@stuartparmenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[syslog] send NIL (”-”) as timestamp if time source is not valid &lt;a href=&quot;https://github.com/esphome/esphome/pull/12588&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12588&lt;/a&gt; by &lt;a href=&quot;https://github.com/leo-b&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@leo-b&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[cc1101] Fix option defaults and move them to YAML &lt;a href=&quot;https://github.com/esphome/esphome/pull/12608&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12608&lt;/a&gt; by &lt;a href=&quot;https://github.com/anna-oake&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@anna-oake&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_camera] Throttle frame logging to reduce overhead and improve throughput &lt;a href=&quot;https://github.com/esphome/esphome/pull/12586&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12586&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[cc1101] Fix packet mode RSSI/LQI &lt;a href=&quot;https://github.com/esphome/esphome/pull/12630&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12630&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-12-3---december-30&quot;&gt;Release 2025.12.3 - December 30&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[lvgl] Fix lambdas in canvas actions called from outside LVGL context &lt;a href=&quot;https://github.com/esphome/esphome/pull/12671&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12671&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix incremental build failures when adding components on ESP32-Arduino &lt;a href=&quot;https://github.com/esphome/esphome/pull/12745&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12745&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-12-4---december-31&quot;&gt;Release 2025.12.4 - December 31&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[hub75] Add clipping check &lt;a href=&quot;https://github.com/esphome/esphome/pull/12762&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12762&lt;/a&gt; by &lt;a href=&quot;https://github.com/stuartparmenter&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@stuartparmenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix ESP-IDF reporting connected before DHCP completes on reconnect &lt;a href=&quot;https://github.com/esphome/esphome/pull/12755&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12755&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[docker] Add build-essential to fix ruamel.yaml 0.19.0 compilation &lt;a href=&quot;https://github.com/esphome/esphome/pull/12769&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12769&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-12-5---january-6&quot;&gt;Release 2025.12.5 - January 6&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[lvgl] Fix arc background angles &lt;a href=&quot;https://github.com/esphome/esphome/pull/12773&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12773&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sn74hc595]: fix ‘Attempted read from write-only channel’ when using esp-idf framework &lt;a href=&quot;https://github.com/esphome/esphome/pull/12801&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12801&lt;/a&gt; by &lt;a href=&quot;https://github.com/aanikei&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@aanikei&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wts01] Fix negative values for WTS01 sensor &lt;a href=&quot;https://github.com/esphome/esphome/pull/12835&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12835&lt;/a&gt; by &lt;a href=&quot;https://github.com/cnrd&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@cnrd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble] Remove requirement for configured network &lt;a href=&quot;https://github.com/esphome/esphome/pull/12891&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12891&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[cc1101] Add PLL lock verification and retry support &lt;a href=&quot;https://github.com/esphome/esphome/pull/13006&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13006&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-12-6---january-13&quot;&gt;Release 2025.12.6 - January 13&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[espnow] fix channel validation &lt;a href=&quot;https://github.com/esphome/esphome/pull/13057&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13057&lt;/a&gt; by &lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[seeed_mr24hpc1] Add ifdef guards for conditional entity types &lt;a href=&quot;https://github.com/esphome/esphome/pull/13147&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13147&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ltr_als_ps] Remove incorrect device_class from count sensors &lt;a href=&quot;https://github.com/esphome/esphome/pull/13167&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13167&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[packet_transport] Fix packet size check to account for round4 padding &lt;a href=&quot;https://github.com/esphome/esphome/pull/13165&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13165&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[remote_transmitter] Fix ESP8266 timing by using busy loop &lt;a href=&quot;https://github.com/esphome/esphome/pull/13172&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13172&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esphome] Fix OTA backend abort not being called on error &lt;a href=&quot;https://github.com/esphome/esphome/pull/13182&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13182&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-12-7---january-16&quot;&gt;Release 2025.12.7 - January 16&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[i2s_audio] Bugfix: Buffer overflow in software volume control &lt;a href=&quot;https://github.com/esphome/esphome/pull/13190&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13190&lt;/a&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Use subtraction for protobuf bounds checking &lt;a href=&quot;https://github.com/esphome/esphome/pull/13306&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#13306&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2025.12.0/&quot;&gt;full 2025.12.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2025.11.0: WiFi overhaul and ultra-low latency events</title><link>https://esphome.io/blog/2025/11/19/esphome-2025-11/</link><guid isPermaLink="true">https://esphome.io/blog/2025/11/19/esphome-2025-11/</guid><description>ESPHome 2025.11.0 overhauls WiFi connection handling, cuts event processing latency across BLE, USB, MQTT and ESP-NOW, frees several KB of RAM and flash, and adds seven new components.</description><pubDate>Wed, 19 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/bh1900nux/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/bh1900nux-evk-001.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;BH1​9​0​0​NUX&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hdc2010/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/hdc2010.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;HDC2​0​1​0​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/tinyusb/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/usb.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;TinyUSB&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/mcp3221/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/mcp3221.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;MCP3​2​2​1​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/hlk_fm22x/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/face.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;HLK-​FM2​2​x ​Face ​Recognition ​Module&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/time/rx8130/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/clock-outline.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;RX8​1​3​0​ ​RTC&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;

&lt;p&gt;ESPHome 2025.11.0 is a performance and reliability-focused release that makes your devices faster, more reliable, and more capable than ever before. WiFi connectivity gets a complete overhaul with intelligent mesh network handling, dramatically faster connection times, and enhanced security controls. Memory optimizations free up &lt;strong&gt;2-31KB of RAM&lt;/strong&gt; and &lt;strong&gt;10KB+ of flash&lt;/strong&gt;, giving even resource-constrained devices room to grow. A new infrastructure change slashes event processing latency by &lt;strong&gt;600-1,300x&lt;/strong&gt;—making BLE Proxy GATT operations rival local Bluetooth adapters, even over the network.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WiFi improvements&lt;/strong&gt; address the most common connectivity pain points: devices no longer get stuck on failed access points in mesh networks, hidden network connections are 2-6 seconds faster, and the new &lt;code dir=&quot;auto&quot;&gt;min_auth_mode&lt;/code&gt; option provides security controls with WPA2 defaults. The redesigned connection strategy with intelligent AP selection and reliable reconnection logic delivers the rock-solid WiFi performance users expect.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ultra-low latency event processing&lt;/strong&gt; transforms responsiveness across BLE, USB, MQTT, ESP-NOW, and wake word detection—reducing latency from 0-16ms to just ~12 microseconds. Voice assistants respond faster to wake words, BLE devices pair quicker, and MQTT automations trigger with sub-millisecond precision. This zero-configuration optimization automatically benefits all affected components on ESP32 platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Memory optimizations&lt;/strong&gt; touch nearly every core component—WiFi scan management, select options, lights, climate controls, sensors, and the action framework. Sensor filter optimizations deliver the most dramatic gains, with sliding window filters saving up to 25KB of RAM on configurations that previously struggled with memory constraints. These improvements enable more complex configurations on the same hardware.&lt;/p&gt;
&lt;p&gt;New hardware support expands ESPHome’s reach with 7 new components including the HDC2010 sensor, MCP3221 ADC, HLK-FM22X face recognition module, BH1900NUX sensor, RX8130 RTC, and TinyUSB foundation support for ESP32-S2/S3. Platform enhancements bring I2C and BLE logging to nRF52, while ESP32 gains hosted BLE for chips without native Bluetooth and ESP-NOW transport capabilities.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;enhanced-wifi-security-and-reliability&quot;&gt;Enhanced WiFi Security and Reliability&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Dramatically Improved WiFi Reliability and Connection Times&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11805&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11805&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;A major step forward in WiFi reliability addresses critical connectivity issues in mesh networks and multi-AP environments. Previously, devices would get stuck repeatedly trying the strongest signal even when that access point was rejecting connections—a bug introduced in 2025.8.2 that made the priority-based failover system ineffective.&lt;/p&gt;
&lt;p&gt;The redesigned connection strategy delivers measurable improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Intelligent AP selection&lt;/strong&gt;: Connection failure history now takes precedence over signal strength, enabling automatic failover to working access points instead of getting stuck on failed BSSIDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faster initial connections&lt;/strong&gt;: Explicit hidden network probing phase with smart skipping of visible networks reduces connection time by 2-6 seconds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reliable reconnections&lt;/strong&gt;: Two-attempt BSSID filtering eliminates false positives from normal WiFi stack transitions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Natural mesh handling&lt;/strong&gt;: Simplified architecture removes 150+ lines of complex BSSID cycling logic—the priority degradation system now naturally handles mesh networks through scan-based retry cycles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clearer diagnostics&lt;/strong&gt;: State machine-based retry phases with improved logging make connection issues easier to troubleshoot&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory efficiency&lt;/strong&gt;: Automatic priority reset when all BSSIDs fail equally (saves up to 96 bytes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This release restores and improves upon the reliable failover behavior users expect in multi-AP deployments, while reducing connection latency and memory overhead.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configurable Minimum Authentication Mode&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11814&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11814&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Added &lt;code dir=&quot;auto&quot;&gt;min_auth_mode&lt;/code&gt; configuration option to control WiFi authentication security:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Secure default&lt;/strong&gt;: WPA2 minimum authentication mode protects against downgrade attacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explicit security control&lt;/strong&gt;: Choose between WPA, WPA2, or WPA3 (ESP32 only)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backward compatibility&lt;/strong&gt;: Can be lowered to WPA for legacy routers&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;wifi&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ssid&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;MyNetwork&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;password123&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;min_auth_mode&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;WPA2&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Recommended for security&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;memory-optimizations-for-resource-constrained-devices&quot;&gt;Memory Optimizations for Resource-Constrained Devices&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.11.0 delivers substantial memory improvements across the entire framework, with measured savings ranging from &lt;strong&gt;2-7KB of RAM on typical devices&lt;/strong&gt; and up to &lt;strong&gt;31KB of RAM on sensor-heavy configurations&lt;/strong&gt;. Flash savings reach &lt;strong&gt;10KB+&lt;/strong&gt; on ESP32/ESP8266 platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sensor Filter Optimizations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sliding window filters&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11282&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11282&lt;/a&gt;) - Saves &lt;strong&gt;22-25KB RAM&lt;/strong&gt; on large batch windows, &lt;strong&gt;90% on sliding windows&lt;/strong&gt;, &lt;strong&gt;1,748 bytes flash&lt;/strong&gt; on ESP8266. Prevents OOM crashes on ESP32 devices with multiple sensors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filter value lists&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11407&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11407&lt;/a&gt;) - Saves &lt;strong&gt;444 bytes flash&lt;/strong&gt; on ESP8266, 18-52% faster execution&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Calibration/OR filters&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11437&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11437&lt;/a&gt;) - Saves &lt;strong&gt;464 bytes flash&lt;/strong&gt;, &lt;strong&gt;48 bytes RAM&lt;/strong&gt; on ESP8266&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Component Optimizations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WiFi component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11205&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11205&lt;/a&gt;) - Saves &lt;strong&gt;440-1,192 bytes RAM&lt;/strong&gt; depending on network density&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Select component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11514&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11514&lt;/a&gt;) - Saves &lt;strong&gt;270-2,800 bytes per select&lt;/strong&gt; depending on option count&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Light component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11348&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11348&lt;/a&gt;) - Saves &lt;strong&gt;1,756 bytes flash&lt;/strong&gt; on ESP8266, &lt;strong&gt;~108 bytes RAM&lt;/strong&gt; per 6 lights&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Climate component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11466&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11466&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11621&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11621&lt;/a&gt;) - Saves &lt;strong&gt;~440 bytes RAM&lt;/strong&gt; per climate entity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fan component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11483&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11632&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11632&lt;/a&gt;) - Saves &lt;strong&gt;~24 bytes per fan&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Event component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11463&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11463&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11767&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11767&lt;/a&gt;) - Saves &lt;strong&gt;1,248 bytes flash&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Global Controller Registry&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11772&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11772&lt;/a&gt;) - Saves &lt;strong&gt;388-6,148 bytes RAM&lt;/strong&gt; depending on entity count&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action framework&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11704&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11704&lt;/a&gt;) - Saves &lt;strong&gt;356 bytes flash&lt;/strong&gt;, eliminates RAM allocations in automations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Script component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11308&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11308&lt;/a&gt;) - Saves &lt;strong&gt;1,592 bytes flash&lt;/strong&gt; on ESP32&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32-IDF&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10930&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10930&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11441&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11441&lt;/a&gt;) - Saves &lt;strong&gt;~10KB combined&lt;/strong&gt; (1.3KB + 8.7KB)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network component&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11707&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11707&lt;/a&gt;) - Saves &lt;strong&gt;32-72 bytes per network component&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Light effects&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11487&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11487&lt;/a&gt;) - Saves &lt;strong&gt;24-32 bytes per effect&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WiFi priority&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11830&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11830&lt;/a&gt;) - Saves &lt;strong&gt;3 bytes per network entry&lt;/strong&gt; plus up to &lt;strong&gt;96 bytes&lt;/strong&gt; from auto-recovery&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Note on Breaking Changes:&lt;/strong&gt; These optimizations required API changes for external component developers. See &lt;a href=&quot;#breaking-changes&quot;&gt;Breaking Changes&lt;/a&gt; section for migration details. Standard YAML configurations remain fully compatible but custom code in lambdas may require updates.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;ultra-low-latency-event-processing&quot;&gt;Ultra-Low Latency Event Processing&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Thread-Safe Loop Wake Mechanism&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11681&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11681&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;A new infrastructure change eliminates event processing delays across multiple components. Previously, events from background tasks (BLE, USB, MQTT, ESP-NOW, wake word detection) would queue and wait up to 16ms for the next &lt;code dir=&quot;auto&quot;&gt;select()&lt;/code&gt; timeout before processing. The new &lt;code dir=&quot;auto&quot;&gt;wake_loop_threadsafe()&lt;/code&gt; mechanism uses a UDP loopback socket to immediately wake the main event loop when events arrive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Latency Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Before&lt;/strong&gt;: 0-16ms average ~8ms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;After&lt;/strong&gt;: ~12 microseconds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speedup&lt;/strong&gt;: 600-1,300x faster event processing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Components with Ultra-Low Latency:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BLE operations&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11663&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11663&lt;/a&gt;) - Bluetooth Proxy, BLE Client GATT operations, HomeKit pairing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;USB Host&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11683&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11683&lt;/a&gt;) - USB event processing over 1000x faster&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MQTT&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11695&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11695&lt;/a&gt;) - ESP32 only (ESP8266 already runs in main loop)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP-NOW&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11696&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11696&lt;/a&gt;) - Packet reception and transmission completion&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Micro Wake Word&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11698&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11698&lt;/a&gt;) - Near-instant automation responses, all triggers fire within same millisecond&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Real-World Impact:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BLE Proxy GATT operations&lt;/strong&gt; now rival or exceed BlueZ local adapters in Home Assistant, even when operating over the network&lt;/li&gt;
&lt;li&gt;Faster wake word detection response for voice assistants&lt;/li&gt;
&lt;li&gt;Improved BLE connection and pairing times&lt;/li&gt;
&lt;li&gt;Reduced MQTT automation trigger latency&lt;/li&gt;
&lt;li&gt;Faster USB event handling (e.g., Z-Wave PoE proxies)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This optimization requires no configuration changes and automatically benefits all affected components on ESP32 platforms.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;high-performance-networking-for-media-streaming&quot;&gt;High-Performance Networking for Media Streaming&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Automatic Network Performance Tuning&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11812&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11812&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Introduced centralized high-performance networking system where components request optimized settings through &lt;code dir=&quot;auto&quot;&gt;network.require_high_performance_networking()&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PSRAM-aware configuration&lt;/strong&gt;: Aggressive settings (512KB TCP windows) when PSRAM guaranteed, conservative (65KB windows) otherwise&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WiFi optimization&lt;/strong&gt;: Automatically applies optimized WiFi driver settings when high-performance mode enabled&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic enablement&lt;/strong&gt;: Speaker media player automatically enables high-performance networking (fixes streaming stuttering issues)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User control&lt;/strong&gt;: New &lt;code dir=&quot;auto&quot;&gt;network.enable_high_performance&lt;/code&gt; option to explicitly enable/disable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This optimization is critical for ESP32-S3 devices running voice assistants and media streaming, eliminating audio stuttering caused by insufficient WiFi buffer sizes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PSRAM Configuration Options&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11411&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11411&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Added &lt;code dir=&quot;auto&quot;&gt;ignore_not_found&lt;/code&gt; option (default &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt;) to allow disabling &lt;code dir=&quot;auto&quot;&gt;CONFIG_SPIRAM_IGNORE_NOTFOUND&lt;/code&gt;. When set to &lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; on devices with guaranteed PSRAM, enables WiFi driver to configure larger buffers for optimal streaming performance. Also improves boot reliability by managing heap allocations before PSRAM initialization.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-hardware-support&quot;&gt;New Hardware Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;7 New Sensor/Device Components:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/hdc2010&quot;&gt;HDC2010&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/6674&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#6674&lt;/a&gt;) - Texas Instruments temperature and humidity sensor&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/mcp3221&quot;&gt;MCP3221&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7764&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#7764&lt;/a&gt;) - I2C A-D converter with configurable reference voltage&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/hlk_fm22x&quot;&gt;HLK-FM22X&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/8059&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#8059&lt;/a&gt;) - Face recognition module family&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/sensor/bh1900nux&quot;&gt;BH1900NUX&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/8631&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#8631&lt;/a&gt;) - Rohm Semiconductor temperature sensor&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/time/rx8130&quot;&gt;RX8130&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10511&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10511&lt;/a&gt;) - Epson RTC chip (used in M5Stack devices)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/ble_nus&quot;&gt;BLE NUS Logger&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9846&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9846&lt;/a&gt;) - Logging over BLE for nRF52 platform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://esphome.io/components/tinyusb&quot;&gt;TinyUSB&lt;/a&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11678&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11678&lt;/a&gt;) - USB device functionality foundation for ESP32-S2/S3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Extended Hardware Support:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GP8403 DAC now supports GP8413 (15-bit) model (&lt;a href=&quot;https://github.com/esphome/esphome/pull/7726&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#7726&lt;/a&gt;) with higher precision&lt;/li&gt;
&lt;li&gt;Toshiba climate supports RAS-2819T air conditioner (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9490&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9490&lt;/a&gt;) with two-packet IR protocol&lt;/li&gt;
&lt;li&gt;Dallas temperature sensors support index-based addressing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11346&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11346&lt;/a&gt;) for devices without programmable addresses&lt;/li&gt;
&lt;li&gt;SX126x LoRa module pins now support GPIO port expanders (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11782&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11782&lt;/a&gt;) for SeeedStudio SenseCAP Indicator&lt;/li&gt;
&lt;li&gt;Mopeka Standard Check sensors support alternate ID 0x44 (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10907&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10907&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Platform &amp;#x26; Feature Expansions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;nRF52 platform&lt;/strong&gt; - I2C support (&lt;a href=&quot;https://github.com/esphome/esphome/pull/8150&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#8150&lt;/a&gt;), BLE NUS logging (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9846&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9846&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/9861&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9861&lt;/a&gt;), GPIO voltage control (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9858&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9858&lt;/a&gt;), GPIO input by switching to polling mode (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11664&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11664&lt;/a&gt;), and Seeed XIAO BLE board improvements (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10698&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10698&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP-NOW transport&lt;/strong&gt; - Added ESP-NOW as a transport platform for packet_transport component (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11025&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11025&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IR Remote protocols&lt;/strong&gt; - Dyson AM07 fan support (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10163&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10163&lt;/a&gt;), Symphony protocol (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10777&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10777&lt;/a&gt;), Toshiba RAS-2819T AC (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9490&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9490&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;esp32-platform-enhancements&quot;&gt;ESP32 Platform Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;ESP-IDF 5.5.1 and Arduino 3.3.2&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9839&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9839&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Major framework updates bring the latest ESP-IDF 5.5.1 and Arduino 3.3.2 to ESPHome:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP-IDF 5.5.1&lt;/strong&gt;: Latest features and bug fixes from Espressif&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arduino 3.3.2&lt;/strong&gt;: Updated Arduino framework with improved stability&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory improvements&lt;/strong&gt;: Significant RAM gains (+3.1-3.3MB free RAM)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform version&lt;/strong&gt;: Updated to 55.03.31-2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These updates are automatically applied when using the default framework versions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hosted BLE Support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11167&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11167&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ESP32 P4 and other chips without integrated Bluetooth now support BLE through external controllers using ESP-Hosted API. Enables Bluetooth Proxy functionality on previously unsupported ESP32 variants.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hosted OTA Support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11562&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11562&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Firmware updates for ESP32 co-processors are now supported via ESP-Hosted API, enabling OTA functionality for hosted configurations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brownout Protection&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11306&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11306&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ESP-IDF builds now automatically reduce PHY TX power during brownout conditions to prevent boot loops. This feature was previously only available in Arduino framework builds. Can be disabled if needed through sdkconfig options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configurable Main Loop Stack Size&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10564&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10564&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ESP32 ESP-IDF configurations can now tune the main loop stack size for complex setups:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esp32&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;framework&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp-idf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;advanced&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;main_loop_stack_size&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;16384&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Increase for deeply nested components&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Framework Source Options&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11125&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11125&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ESP32 framework configuration now accepts additional PlatformIO source schemes beyond HTTP, including &lt;code dir=&quot;auto&quot;&gt;symlink://&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;git://&lt;/code&gt;, and other repository protocols for local development.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;openthread-improvements&quot;&gt;OpenThread Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Over-The-Air Updates&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11095&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11095&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;OpenThread devices (ESP32-H2) now support OTA updates via &lt;code dir=&quot;auto&quot;&gt;esphome run&lt;/code&gt;. The mDNS address is automatically populated as the device’s default address, eliminating the need to manually specify &lt;code dir=&quot;auto&quot;&gt;--device &amp;#x3C;address&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sleepy End Device Support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11374&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11374&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Added &lt;code dir=&quot;auto&quot;&gt;poll_period&lt;/code&gt; configuration for MTD (Minimal Thread Device) mode, enabling Sleep End Device (SED) behavior for battery-powered Thread devices:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;openthread&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;device_type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;MTD&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;poll_period&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;40s&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Radio turns off between polls&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;nrf52-platform-expansion&quot;&gt;nRF52 Platform Expansion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The nRF52 (Zephyr) platform received extensive new functionality:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;I2C Support&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/8150&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#8150&lt;/a&gt;) - Full I2C bus support for sensors and peripherals&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BLE Logging&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9846&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9846&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/9861&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9861&lt;/a&gt;) - Log viewing via &lt;code dir=&quot;auto&quot;&gt;esphome logs --device BLE&lt;/code&gt; or MAC address&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPIO High Voltage Mode&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/9858&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9858&lt;/a&gt;) - Adjustable voltage levels for USB-powered operation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Xiao BLE Bootloader Fix&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10698&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10698&lt;/a&gt;) - Corrected default bootloader, fixed upload, added runtime mismatch detection&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;lvgl-display-enhancements&quot;&gt;LVGL Display Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Simplified Layout System&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10149&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10149&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;LVGL widgets now support shorthand layout methods for easier configuration:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;lvgl&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;widgets&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;container&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;layout&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;vertical&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Simple flex layout&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;widgets&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Item 1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Item 2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;container&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;layout&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3x2&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Simple grid layout&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;New &lt;code dir=&quot;auto&quot;&gt;container&lt;/code&gt; widget provides styling-free base with 100% default dimensions. Added &lt;code dir=&quot;auto&quot;&gt;stretch&lt;/code&gt; option for flex layouts and substantial speedup of config validation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rendering Triggers and NaN Substitution&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11628&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11628&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11712&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11712&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Added &lt;code dir=&quot;auto&quot;&gt;on_draw_start&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;on_draw_end&lt;/code&gt; triggers for coordinating e-paper display updates. Text formatting now supports NaN substitution for graceful handling of unavailable sensor values:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;lvgl&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;widgets&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;label&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;%.1f°C&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;id(temp_sensor)&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;if_nan&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;--.-°C&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Show when sensor unavailable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;display-component-improvements&quot;&gt;Display Component Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;E-Paper SPI Refactoring&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11540&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11540&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Major improvements to e-paper displays:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Faster transfers&lt;/strong&gt;: Larger data blocks for Spectra displays&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimized state machine&lt;/strong&gt;: Code-based sequence instead of linear queue saves memory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Board-specific configs&lt;/strong&gt;: Pre-configured pin mappings (Seeed-reTerminal-E1002)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved timing&lt;/strong&gt;: Internal delay handling instead of loop disabling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fixed busy pin logic&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11349&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11349&lt;/a&gt;): Corrected active-low detection&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Component Idle Detection&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11651&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11651&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;New &lt;code dir=&quot;auto&quot;&gt;component.is_idle&lt;/code&gt; condition and &lt;code dir=&quot;auto&quot;&gt;is_idle()&lt;/code&gt; method for automations that need to wait for displays to finish updating before proceeding:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;lvgl&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;on_draw_end&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;component.update&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;epaper_display&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;wait_until&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;component.is_idle&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;epaper_display&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Wait for display ready&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;lvgl.resume&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;configuration-and-developer-tools&quot;&gt;Configuration and Developer Tools&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Advanced Substitution Features&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11203&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11203&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;!extend&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;!remove&lt;/code&gt; tags now support substitutions and Jinja templates:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;substitutions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;COMPONENT_TO_REMOVE&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;component3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;packages&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;base&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!remove&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;${COMPONENT_TO_REMOVE}&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Conditional removal&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Memory Analysis Command&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11395&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11395&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;New &lt;code dir=&quot;auto&quot;&gt;esphome analyze-memory &amp;#x3C;config.yaml&gt;&lt;/code&gt; command provides detailed memory usage breakdown by component:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compiles configuration (fast relink if cached)&lt;/li&gt;
&lt;li&gt;Analyzes memory usage by component and external components&lt;/li&gt;
&lt;li&gt;Displays comprehensive memory report&lt;/li&gt;
&lt;li&gt;Helps identify optimization opportunities&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;component-specific-enhancements&quot;&gt;Component-Specific Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;sensors&quot;&gt;Sensors&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Dallas temperature sensors support index-based addressing (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11346&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11346&lt;/a&gt;) for devices without programmable addresses&lt;/li&gt;
&lt;li&gt;INA2xx reset control (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10787&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10787&lt;/a&gt;): Preserve counters through ESP resets with &lt;code dir=&quot;auto&quot;&gt;reset_on_boot: false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;XGZP68xx oversampling (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10306&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10306&lt;/a&gt;): Configurable oversampling up to 32768x for improved accuracy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Improved Improv WiFi Provisioning&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10757&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10757&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ESP32 Improv now supports &lt;code dir=&quot;auto&quot;&gt;next_url&lt;/code&gt; with template substitutions for post-provisioning redirection:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esp32_improv&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;next_url&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;https://example.com/setup?device={{device_name}}&amp;#x26;ip={{ip_address}}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Sensor Heartbeat Filter Options&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/10993&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10993&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Heartbeat filter adds &lt;code dir=&quot;auto&quot;&gt;optimistic&lt;/code&gt; mode to forward new values immediately while still repeating periodically:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sensor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;filters&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;heartbeat&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;period&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;100ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;optimistic&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Forward immediately + repeat&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;ESP-NOW Packet Transport&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11025&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11025&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;ESP-NOW now available as transport platform for packet_transport component, enabling direct ESP32-to-ESP32 wireless sensor data transmission.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Remote Transmitter Non-Blocking Mode&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11524&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11524&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Remote transmitter operations no longer block the main loop by default, preventing “took a long time for an operation” warnings during long IR transmissions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HTTP Request Trigger Variables&lt;/strong&gt; (&lt;a href=&quot;https://github.com/esphome/esphome/pull/11464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11464&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;HTTP request actions now pass trigger variables correctly into &lt;code dir=&quot;auto&quot;&gt;on_response&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;on_error&lt;/code&gt; triggers.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;

&lt;div&gt;&lt;h3 id=&quot;user-facing-breaking-changes&quot;&gt;User-Facing Breaking Changes&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;wifi--network&quot;&gt;WiFi &amp;#x26; Network&lt;/h4&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WiFi&lt;/strong&gt;: WiFi and Ethernet components no longer block other components’ setup until connected. Components with setup priority &gt; WIFI (802.3) now initialize immediately, even if network is disconnected. &lt;a href=&quot;https://github.com/esphome/esphome/pull/9823&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9823&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WiFi min_auth_mode&lt;/strong&gt;: ESP8266 default will change from &lt;code dir=&quot;auto&quot;&gt;WPA&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;WPA2&lt;/code&gt; in 2026.6.0. Users with WPA-only routers must explicitly set &lt;code dir=&quot;auto&quot;&gt;min_auth_mode: WPA&lt;/code&gt; before then. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11814&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11814&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WiFi priority&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;priority&lt;/code&gt; configuration option now only accepts integers (-128 to 127) instead of floats. Change &lt;code dir=&quot;auto&quot;&gt;priority: 5.5&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;priority: 5&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11830&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11830&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;.local addresses&lt;/strong&gt;: .local addresses now require mDNS to be enabled for DNS resolution. Previously attempted DNS resolution could add 10+ second delays. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11508&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11508&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Network high performance&lt;/strong&gt;: Speaker media player now always enables high performance networking mode (previously only with codec support). Users can override with &lt;code dir=&quot;auto&quot;&gt;enable_high_performance&lt;/code&gt; under the network component if needed. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11812&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11812&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;esp32-platform&quot;&gt;ESP32 Platform&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP32 brownout protection&lt;/strong&gt;: ESP-IDF now reduces PHY TX power during brownout to prevent boot loops. Can be disabled with &lt;code dir=&quot;auto&quot;&gt;sdkconfig_options: CONFIG_ESP_PHY_REDUCE_TX_POWER: n&lt;/code&gt; if needed. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11306&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11306&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ESP32 PSRAM&lt;/strong&gt;: PSRAM is no longer auto-loaded by components that depend on it (such as &lt;code dir=&quot;auto&quot;&gt;esp32_camera&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;speaker&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;media_player&lt;/code&gt;). Users must now explicitly add a &lt;code dir=&quot;auto&quot;&gt;psram:&lt;/code&gt; configuration block to their YAML. Additionally, for ESP32-S3, the &lt;code dir=&quot;auto&quot;&gt;mode&lt;/code&gt; option is now required since S3 supports both quad and octal modes. Typically, 2MB PSRAM uses &lt;code dir=&quot;auto&quot;&gt;quad&lt;/code&gt; mode while 8 or 16MB uses &lt;code dir=&quot;auto&quot;&gt;octal&lt;/code&gt; mode—check your module’s datasheet. Example configuration:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;psram&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mode&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;octal&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Required for ESP32-S3, use &apos;quad&apos; or &apos;octal&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;speed&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;80MHz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/esphome/esphome/pull/11470&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11470&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-behavior-changes&quot;&gt;Component Behavior Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Script max_runs&lt;/strong&gt;: Queued scripts now default to &lt;code dir=&quot;auto&quot;&gt;max_runs: 5&lt;/code&gt; (allowing 1 running + 4 queued instances) instead of unlimited to prevent crashes from unbounded memory growth. Set &lt;code dir=&quot;auto&quot;&gt;max_runs&lt;/code&gt; explicitly if you need more capacity. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11308&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11308&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remote transmitter&lt;/strong&gt;: Remote transmitter now defaults to non-blocking mode to prevent long blocking operations (&gt;30ms). &lt;a href=&quot;https://github.com/esphome/esphome/pull/11524&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11524&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fan preset modes&lt;/strong&gt;: Fan preset modes now preserve the order defined in YAML instead of being sorted alphabetically. The order in Home Assistant will match your YAML configuration order. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11483&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Select state&lt;/strong&gt;: The public &lt;code dir=&quot;auto&quot;&gt;state&lt;/code&gt; member has been deprecated and will be removed in 2026.5.0. Use &lt;code dir=&quot;auto&quot;&gt;current_option()&lt;/code&gt; method instead. Deprecation warnings will be shown during compilation. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11623&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-specific-changes&quot;&gt;Component-Specific Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HM3301&lt;/strong&gt;: AQI calculation updated to EPA 2024 standard. Values will change compared to the old 2012 formula. &lt;a href=&quot;https://github.com/esphome/esphome/pull/9442&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9442&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GDK101&lt;/strong&gt;: Firmware version is now reported as a string instead of a float division result. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11029&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11029&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Uponor Smatrix&lt;/strong&gt;: The &lt;code dir=&quot;auto&quot;&gt;address&lt;/code&gt; property of the &lt;code dir=&quot;auto&quot;&gt;uponor_smatrix&lt;/code&gt; component was removed. Device addresses are now 32-bit instead of separate 16-bit system and device addresses. Update configurations by prepending the previous system address to individual device addresses. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11066&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11066&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pipsolar&lt;/strong&gt;: Fixed typo &lt;code dir=&quot;auto&quot;&gt;warnung_low_pv_energy&lt;/code&gt; renamed to &lt;code dir=&quot;auto&quot;&gt;warning_low_pv_energy&lt;/code&gt;. Update YAML configurations. &lt;a href=&quot;https://github.com/esphome/esphome/pull/10291&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10291&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;E-Paper SPI&lt;/strong&gt;: Busy pin logic corrected to match datasheet (active low). Some e-paper displays may behave differently. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11349&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11349&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;nRF52 bootloader&lt;/strong&gt;: Default bootloader changed for &lt;code dir=&quot;auto&quot;&gt;xiao_ble&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;adafruit_itsybitsy_nrf52840&lt;/code&gt; boards. Warning shown if generic Adafruit bootloader is used. &lt;a href=&quot;https://github.com/esphome/esphome/pull/10698&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10698&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HTTP request triggers&lt;/strong&gt;: Changed from multiple on_response/on_error triggers to a single trigger that receives variables. Update automation configurations to use the new variable-based trigger format. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11464&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;yaml-lambda-changes&quot;&gt;YAML Lambda Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Users who access component members directly in YAML lambdas may need updates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Select&lt;/strong&gt;: Change &lt;code dir=&quot;auto&quot;&gt;id(my_select).state&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;id(my_select).current_option()&lt;/code&gt; (deprecated, will be removed in 2026.5.0). &lt;a href=&quot;https://github.com/esphome/esphome/pull/11623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11623&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fan&lt;/strong&gt;: Change &lt;code dir=&quot;auto&quot;&gt;id(my_fan).preset_mode&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;id(my_fan).get_preset_mode()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11632&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11632&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event&lt;/strong&gt;: Change &lt;code dir=&quot;auto&quot;&gt;id(my_event).last_event_type&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;id(my_event).get_last_event_type()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11767&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11767&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Climate&lt;/strong&gt;: Custom mode members are now private. Change direct access to public accessor methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check if active: &lt;code dir=&quot;auto&quot;&gt;id(my_climate).custom_fan_mode.has_value()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;id(my_climate).has_custom_fan_mode()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;id(my_climate).custom_preset.has_value()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;id(my_climate).has_custom_preset()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Get value: &lt;code dir=&quot;auto&quot;&gt;id(my_climate).custom_fan_mode.value()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;id(my_climate).get_custom_fan_mode()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;id(my_climate).custom_preset.value()&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;id(my_climate).get_custom_preset()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/esphome/esphome/pull/11621&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11621&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h3 id=&quot;breaking-changes-for-developers&quot;&gt;Breaking Changes for Developers&lt;/h3&gt;&lt;/div&gt;

&lt;p&gt;The following changes affect external component developers. Standard YAML configurations are generally not affected.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;core-framework-changes&quot;&gt;Core Framework Changes&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Action/Trigger Framework&lt;/strong&gt;: All action/trigger/condition method signatures changed to use const references (&lt;code dir=&quot;auto&quot;&gt;const Ts&amp;#x26;... x&lt;/code&gt;) instead of pass-by-value (&lt;code dir=&quot;auto&quot;&gt;Ts... x&lt;/code&gt;). See the &lt;a href=&quot;https://developers.esphome.io/blog/2025/11/06/action-framework-performance-optimization/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Action Framework Performance Optimization&lt;/a&gt; blog post for migration details. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11704&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11704&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Controller API&lt;/strong&gt;: Controllers now use global registry pattern. Method signatures changed to remove unused state parameters (e.g., &lt;code dir=&quot;auto&quot;&gt;on_sensor_update(sensor::Sensor *obj)&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;on_sensor_update(sensor::Sensor *obj, float state)&lt;/code&gt;). External controller implementations extremely rare. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11772&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11772&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;EntityBase::hash_base()&lt;/strong&gt;: Removed deprecated virtual method (deprecated since June 2022). Remove &lt;code dir=&quot;auto&quot;&gt;hash_base()&lt;/code&gt; overrides from external components. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11783&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11783&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;hexencode()&lt;/strong&gt;: Removed function deprecated since 2022.1. Use alternative encoding methods. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11383&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11383&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Schema constants&lt;/strong&gt;: Removed deprecated schema constants from core. Update external components to use current schema helpers. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11591&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11591&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;component-specific-api-changes&quot;&gt;Component-Specific API Changes&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;climate&quot;&gt;Climate&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://developers.esphome.io/blog/2025/11/07/climate-entity-class-finitesetmask-and-flash-storage-optimizations/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Climate Entity Class: FiniteSetMask and Flash Storage Optimizations&lt;/a&gt; blog post for migration details.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom modes storage&lt;/strong&gt;: Changed from &lt;code dir=&quot;auto&quot;&gt;std::set&amp;#x3C;std::string&gt;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;FiniteSetMask&lt;/code&gt; for supported modes, and from &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x3C;std::string&gt;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x3C;const char *&gt;&lt;/code&gt; for custom fan modes and presets. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11466&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11466&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11621&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11621&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Member access&lt;/strong&gt;: Climate device members (&lt;code dir=&quot;auto&quot;&gt;custom_fan_mode_&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;custom_preset_&lt;/code&gt;) are now private. Use protected setter methods (&lt;code dir=&quot;auto&quot;&gt;set_custom_fan_mode_()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;set_custom_preset_()&lt;/code&gt;) in derived classes. Use public accessor methods to read values: &lt;code dir=&quot;auto&quot;&gt;has_custom_fan_mode()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_custom_fan_mode()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;has_custom_preset()&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;get_custom_preset()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11621&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11621&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deprecated methods&lt;/strong&gt;: Removed methods deprecated in 1.20 (July 2021). &lt;a href=&quot;https://github.com/esphome/esphome/pull/11388&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11388&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;light&quot;&gt;Light&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://developers.esphome.io/blog/2025/11/07/light-entity-class-memory-optimizations/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Light Entity Class: Memory Optimizations&lt;/a&gt; blog post for migration details.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Color modes&lt;/strong&gt;: Replaced &lt;code dir=&quot;auto&quot;&gt;std::set&amp;#x3C;ColorMode&gt;&lt;/code&gt; with &lt;code dir=&quot;auto&quot;&gt;ColorModeMask&lt;/code&gt; bitmask class. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11348&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11348&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Effect names&lt;/strong&gt;: Changed from &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt; for effect names. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11487&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11487&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deprecated methods&lt;/strong&gt;: Removed methods deprecated in 2021.8.0. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11389&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11389&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;fan&quot;&gt;Fan&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://developers.esphome.io/blog/2025/11/07/fan-entity-class-preset-mode-flash-storage-and-order-preservation/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Fan Entity Class: Preset Mode Flash Storage and Order Preservation&lt;/a&gt; blog post for migration details.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Preset modes&lt;/strong&gt;: Changed from &lt;code dir=&quot;auto&quot;&gt;std::set&amp;#x3C;std::string&gt;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x3C;const char *&gt;&lt;/code&gt;. The &lt;code dir=&quot;auto&quot;&gt;.preset_mode&lt;/code&gt; public member has been removed - use &lt;code dir=&quot;auto&quot;&gt;get_preset_mode()&lt;/code&gt; for reading and &lt;code dir=&quot;auto&quot;&gt;set_preset_mode_()&lt;/code&gt; for writing in derived classes. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11483&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11483&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11632&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11632&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deprecated code&lt;/strong&gt;: Removed code deprecated in 2022.2. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11392&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11392&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;select&quot;&gt;Select&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://developers.esphome.io/blog/2025/11/07/select-entity-class-index-based-operations-and-flash-storage/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Select Entity Class: Index-Based Operations and Flash Storage&lt;/a&gt; blog post for migration details.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Options storage&lt;/strong&gt;: Changed from &lt;code dir=&quot;auto&quot;&gt;std::vector&amp;#x3C;std::string&gt;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;FixedVector&amp;#x3C;const char *&gt;&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11514&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11514&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;State member&lt;/strong&gt;: Public &lt;code dir=&quot;auto&quot;&gt;state&lt;/code&gt; member deprecated (will be removed in 2026.5.0). Use &lt;code dir=&quot;auto&quot;&gt;current_option()&lt;/code&gt; method instead. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11623&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Index-based operations&lt;/strong&gt;: Added optional &lt;code dir=&quot;auto&quot;&gt;control(size_t index)&lt;/code&gt; override for more efficient implementations. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11623&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11623&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;event&quot;&gt;Event&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://developers.esphome.io/blog/2025/11/07/event-entity-class-memory-optimizations/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Event Entity Class: Memory Optimizations&lt;/a&gt; blog post for migration details.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Event types storage&lt;/strong&gt;: Changed from &lt;code dir=&quot;auto&quot;&gt;FixedVector&amp;#x3C;std::string&gt;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;FixedVector&amp;#x3C;const char *&gt;&lt;/code&gt;. The &lt;code dir=&quot;auto&quot;&gt;last_event_type&lt;/code&gt; field is now private - use &lt;code dir=&quot;auto&quot;&gt;get_last_event_type()&lt;/code&gt; getter instead. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11463&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11463&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11767&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11767&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;network-components&quot;&gt;Network Components&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://developers.esphome.io/blog/2025/11/20/network-use-address-optimization/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Network get_use_address() Optimization&lt;/a&gt; blog post for migration details.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WiFi scan results&lt;/strong&gt;: External components that access WiFi scan results after connection must call &lt;code dir=&quot;auto&quot;&gt;wifi.request_wifi_scan_results()&lt;/code&gt; in their &lt;code dir=&quot;auto&quot;&gt;to_code()&lt;/code&gt; function to prevent cleanup. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11205&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11205&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;use_address&lt;/strong&gt;: Changed from &lt;code dir=&quot;auto&quot;&gt;const std::string &amp;#x26;&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;const char *&lt;/code&gt; in WiFi, Ethernet, and OpenThread components. Remove &lt;code dir=&quot;auto&quot;&gt;.c_str()&lt;/code&gt; calls when using &lt;code dir=&quot;auto&quot;&gt;get_use_address()&lt;/code&gt;. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11707&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11707&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;other-components&quot;&gt;Other Components&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cover&lt;/strong&gt;: Removed methods deprecated in 2021.9. Update to current cover API. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11391&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11391&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Nextion&lt;/strong&gt;: Removed methods deprecated in 1.20 (July 2021). Update to current nextion API. &lt;a href=&quot;https://github.com/esphome/esphome/pull/11393&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11393&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;esp32-specific-changes&quot;&gt;ESP32-Specific Changes&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP-IDF advanced options&lt;/strong&gt;: New options to disable libc locks in IRAM and VFS features. External components using these features must call helper functions to register needs. &lt;a href=&quot;https://github.com/esphome/esphome/pull/10930&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10930&lt;/a&gt;, &lt;a href=&quot;https://github.com/esphome/esphome/pull/11441&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11441&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;migration-resources&quot;&gt;Migration Resources&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For detailed migration guides and examples, see the &lt;a href=&quot;https://developers.esphome.io/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ESPHome developer documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The 2025.11 release blog posts include comprehensive migration examples for common use cases.&lt;/p&gt;


&lt;div&gt;&lt;h2 id=&quot;release-2025-11-1---november-24&quot;&gt;Release 2025.11.1 - November 24&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[graph] Fix legend border &lt;a href=&quot;https://github.com/esphome/esphome/pull/12000&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12000&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[network] Fix IPAddress constructor causing comparison failures and garbage output &lt;a href=&quot;https://github.com/esphome/esphome/pull/12005&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12005&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ltr501][ltr_als_ps] Rename enum to avoid collision with lwip defines &lt;a href=&quot;https://github.com/esphome/esphome/pull/12017&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12017&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[cst816][packet_transport][udp][wake_on_lan] Fix error messages &lt;a href=&quot;https://github.com/esphome/esphome/pull/12019&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12019&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[jsn_sr04t] Fix model AJ_SR04M &lt;a href=&quot;https://github.com/esphome/esphome/pull/11992&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11992&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[cst816][http_request] Fix status_set_error() dangling pointer bugs &lt;a href=&quot;https://github.com/esphome/esphome/pull/12033&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12033&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Fix C2 builds &lt;a href=&quot;https://github.com/esphome/esphome/pull/12050&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12050&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Add support for passing yaml files to clean-all &lt;a href=&quot;https://github.com/esphome/esphome/pull/12039&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12039&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[script][wait_until] Fix FIFO ordering and reentrancy bugs &lt;a href=&quot;https://github.com/esphome/esphome/pull/12049&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12049&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp_ldo,mipi_dsi,mipi_rgb] Fix dangling pointer bugs in mark_failed() &lt;a href=&quot;https://github.com/esphome/esphome/pull/12077&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12077&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[online_image] Fix some large PNGs causing watchdog timeout &lt;a href=&quot;https://github.com/esphome/esphome/pull/12025&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12025&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-11-2---november-27&quot;&gt;Release 2025.11.2 - November 27&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[nextion] Do not set alternative baud rate when not specified or &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;= 0&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/12097&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12097&lt;/a&gt; by &lt;a href=&quot;https://github.com/edwardtfn&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@edwardtfn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Fix platformio flash size print &lt;a href=&quot;https://github.com/esphome/esphome/pull/12099&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12099&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[script] Fix script.wait hanging when triggered from on_boot &lt;a href=&quot;https://github.com/esphome/esphome/pull/12102&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12102&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Allow multiple widgets per grid cell &lt;a href=&quot;https://github.com/esphome/esphome/pull/12091&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12091&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; (new-feature)&lt;/li&gt;
&lt;li&gt;[lvgl] Fix position of errors in widget config &lt;a href=&quot;https://github.com/esphome/esphome/pull/12111&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12111&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Fix hosted update when there is no wifi &lt;a href=&quot;https://github.com/esphome/esphome/pull/12123&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12123&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Restore blocking setup until connected for RP2040 &lt;a href=&quot;https://github.com/esphome/esphome/pull/12142&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12142&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[scheduler] Fix use-after-move crash in heap operations &lt;a href=&quot;https://github.com/esphome/esphome/pull/12124&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12124&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-11-3---december-3&quot;&gt;Release 2025.11.3 - December 3&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[build] Don’t clear pio cache unless requested &lt;a href=&quot;https://github.com/esphome/esphome/pull/11966&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11966&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[usb_uart] Wake main loop immediately when USB data arrives &lt;a href=&quot;https://github.com/esphome/esphome/pull/12148&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12148&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[espnow] Initialize LwIP stack when running without WiFi component &lt;a href=&quot;https://github.com/esphome/esphome/pull/12169&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12169&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[helpers] Add conversion from FixedVector to std::vector &lt;a href=&quot;https://github.com/esphome/esphome/pull/12179&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12179&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[hlk_fm22x] Fix Action::play method signatures &lt;a href=&quot;https://github.com/esphome/esphome/pull/12192&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12192&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mopeka_pro_check] Fix negative temperatures &lt;a href=&quot;https://github.com/esphome/esphome/pull/12198&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12198&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ade7953] Apply voltage_gain setting to both channels &lt;a href=&quot;https://github.com/esphome/esphome/pull/12180&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12180&lt;/a&gt; by &lt;a href=&quot;https://github.com/dlitz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@dlitz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix clean all on windows &lt;a href=&quot;https://github.com/esphome/esphome/pull/12217&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12217&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rtl87xx] Fix AsyncTCP compilation by upgrading FreeRTOS to 8.2.3 &lt;a href=&quot;https://github.com/esphome/esphome/pull/12230&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12230&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[analog_threshold] Fix oscillation when using invert filter &lt;a href=&quot;https://github.com/esphome/esphome/pull/12251&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12251&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rtl87xx] Fix FreeRTOS version for RTL8720C boards &lt;a href=&quot;https://github.com/esphome/esphome/pull/12261&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12261&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-11-4---december-4&quot;&gt;Release 2025.11.4 - December 4&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[esp32] Add build flag to suppress noexecstack message &lt;a href=&quot;https://github.com/esphome/esphome/pull/12272&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12272&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ld2420] Add missing USE_SELECT ifdefs &lt;a href=&quot;https://github.com/esphome/esphome/pull/12275&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12275&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[config] Provide path for &lt;code dir=&quot;auto&quot;&gt;has_at_most_one_of&lt;/code&gt; messages &lt;a href=&quot;https://github.com/esphome/esphome/pull/12277&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12277&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[es8311] Remove MIN and MAX from mic_gain enum options &lt;a href=&quot;https://github.com/esphome/esphome/pull/12281&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12281&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_hosted] Fix build and bump IDF component version to 2.7.0 &lt;a href=&quot;https://github.com/esphome/esphome/pull/12282&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12282&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[CI] Trigger generic version notifier job on release &lt;a href=&quot;https://github.com/esphome/esphome/pull/12292&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12292&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[scheduler] Fix use-after-free when cancelling timeouts from non-main-loop threads &lt;a href=&quot;https://github.com/esphome/esphome/pull/12288&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12288&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-11-5---december-9&quot;&gt;Release 2025.11.5 - December 9&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[binary_sensor] Fix reporting of ‘unknown’ &lt;a href=&quot;https://github.com/esphome/esphome/pull/12296&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12296&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Number saves value on interactive change &lt;a href=&quot;https://github.com/esphome/esphome/pull/12315&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12315&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[scheduler] Fix missing lock when recycling items in defer queue processing &lt;a href=&quot;https://github.com/esphome/esphome/pull/12343&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12343&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix scan timeout loop when scan returns zero networks &lt;a href=&quot;https://github.com/esphome/esphome/pull/12354&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12354&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[libretiny] Fix WiFi scan timeout loop when scan fails &lt;a href=&quot;https://github.com/esphome/esphome/pull/12356&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12356&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mqtt] Fix logger method case sensitivity error &lt;a href=&quot;https://github.com/esphome/esphome/pull/12379&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#12379&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2025.11.0/&quot;&gt;full 2025.11.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2025.10.0: Z-Wave Proxy and Arduino as an IDF component</title><link>https://esphome.io/blog/2025/10/15/esphome-2025-10/</link><guid isPermaLink="true">https://esphome.io/blog/2025/10/15/esphome-2025-10/</guid><description>ESPHome 2025.10.0 adds the Z-Wave Proxy component, rebuilds ESP32 Arduino builds on top of ESP-IDF, introduces a unified SPI ePaper component, and hardens OTA and API security.</description><pubDate>Wed, 15 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/zwave_proxy/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/z-wave.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Z-​Wave ​Proxy&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/display/epaper_spi/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/epaper.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;ePaper ​SPI ​Displays&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/wts01/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/wts01.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;WTS0​1​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/lm75b/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/lm75b.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LM7​5​B&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.10.0 delivers major architectural improvements, new communication protocols, and extensive performance
optimizations. This release focuses on enhancing security, improving memory efficiency, and expanding hardware support
while introducing groundbreaking new features.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Highlights:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Z-Wave Proxy&lt;/strong&gt; - Bridge Z-Wave devices to Home Assistant through ESPHome&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arduino as IDF Component&lt;/strong&gt; - Unified ESP32 framework architecture (breaking change)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced ePaper Display Support&lt;/strong&gt; - New unified SPI ePaper component&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security Enhancements&lt;/strong&gt; - SHA256 OTA authentication, password deprecation, and API hardening with OOM protection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API Improvements&lt;/strong&gt; - Home Assistant action responses and configurable connection limits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensive Memory Optimizations&lt;/strong&gt; - Flash and RAM savings across all platforms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New Sensor Components&lt;/strong&gt; - WTS01 and LM75B temperature sensors&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;z-wave-proxy&quot;&gt;Z-Wave Proxy&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/zwave_proxy/&quot;&gt;Zwave Proxy&lt;/a&gt; component enables network-based connectivity for Z-Wave hardware
by proxying serial communication between a Z-Wave modem SoC and Z-Wave JS over WiFi or Ethernet. This component was
specifically designed for the &lt;a href=&quot;https://www.home-assistant.io/connect/zwa-2/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Home Assistant ZWA-2 Z-Wave Adapter&lt;/a&gt;, which combines an ESP32 and a Z-Wave modem in a single device, but could support other Z-Wave hardware in the future.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Remote Z-Wave placement&lt;/strong&gt; - Position your Z-Wave modem anywhere in your home with WiFi/Ethernet connectivity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Serial-to-network bridge&lt;/strong&gt; - Proxies UART communication between Z-Wave hardware and Z-Wave JS via ESPHome’s
native API&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible deployment&lt;/strong&gt; - Use ESP32 devices to extend Z-Wave modem placement beyond USB cable reach&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low latency performance&lt;/strong&gt; - Achieves 50-60ms typical latency (as low as 35ms under ideal conditions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ethernet recommended&lt;/strong&gt; - Best reliability with wired connections, though WiFi is supported&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This component is particularly useful for optimizing Z-Wave mesh network topology by placing the Z-Wave controller in
a central location, even when your server is in a basement or closet.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;arduino-as-idf-component-major-architectural-change&quot;&gt;Arduino as IDF Component (Major Architectural Change)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release includes a fundamental change in how ESP32 Arduino builds work - &lt;strong&gt;Arduino is now integrated as an ESP-IDF component&lt;/strong&gt; rather than a separate framework. This is the biggest architectural change for ESP32 in ESPHome’s history.&lt;/p&gt;
&lt;p&gt;Previously, Arduino came as a precompiled framework with everything baked in - you got whatever upstream decided, whether you needed it or not. This led to bloated builds that often &lt;strong&gt;couldn’t even fit on devices&lt;/strong&gt; with limited flash space. You were stuck with the upstream choices and locked out of ESP-IDF features.&lt;/p&gt;
&lt;p&gt;Now Arduino is built as an ESP-IDF component alongside your configuration. ESPHome compiles only what you actually use, eliminating the bloat. You get access to ESP-IDF features while still using Arduino libraries when you need them. This aligns with Espressif’s recommended approach and is how the Arduino ecosystem is evolving.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Memory Savings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;20-30KB RAM savings&lt;/strong&gt; on Arduino builds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Additional ~8KB RAM savings&lt;/strong&gt; if using the web server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smaller binary sizes&lt;/strong&gt; overall&lt;/li&gt;
&lt;li&gt;Better memory efficiency through shared libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Development Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Faster fixes for underlying components&lt;/strong&gt; - Many components now share the same implementations between Arduino and ESP-IDF, eliminating duplicate maintenance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access to latest ESP-IDF 5.4&lt;/strong&gt; features while using Arduino libraries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced maintenance burden&lt;/strong&gt; - One framework to maintain instead of two separate paths&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proof&lt;/strong&gt; - Follows Espressif’s direction for the ESP32 ecosystem&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Build Time Trade-off:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Arduino builds now take longer (Arduino is compiled on top of ESP-IDF)&lt;/li&gt;
&lt;li&gt;ESP-IDF builds are now &lt;strong&gt;2-3x faster&lt;/strong&gt; than Arduino builds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consider migrating to ESP-IDF&lt;/strong&gt; if build time matters to you&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;should-you-migrate-to-esp-idf&quot;&gt;Should You Migrate to ESP-IDF?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;We recommend ESP-IDF for most users&lt;/strong&gt;, especially for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bluetooth Proxy devices (lower memory usage)&lt;/li&gt;
&lt;li&gt;New projects&lt;/li&gt;
&lt;li&gt;Configurations where you want faster builds&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Arduino is still fully supported and works great if you need it for specific Arduino libraries. See our &lt;a href=&quot;https://esphome.io/guides/esp32_arduino_to_idf&quot;&gt;Arduino to ESP-IDF migration guide&lt;/a&gt; for help switching - it’s easier than you might think!&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-you-need-to-know&quot;&gt;What You Need to Know&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Most users:&lt;/strong&gt; Your configuration will work without changes. ESPHome handles the framework integration automatically.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;External component developers:&lt;/strong&gt; If you maintain external components using Arduino-specific APIs, review &lt;a href=&quot;https://docs.espressif.com/projects/arduino-esp32/en/latest/esp-idf_component.html&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Espressif’s Arduino as ESP-IDF component documentation&lt;/a&gt; and test your components with this release.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Breaking change details:&lt;/strong&gt; Framework version handling has been improved with stricter validation. See the breaking changes section for specifics.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;epaper-spi-display-component&quot;&gt;ePaper SPI Display Component&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/display/epaper_spi/&quot;&gt;Epaper Spi&lt;/a&gt; component provides a unified, modernized interface for
SPI-based ePaper displays:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cleaner configuration&lt;/strong&gt; with consistent API across models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better performance&lt;/strong&gt; with optimized refresh cycles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved partial update&lt;/strong&gt; handling where supported&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced memory overhead&lt;/strong&gt; through efficient buffering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Current Status:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Currently supports one display model, with additional models from the
&lt;a href=&quot;https://esphome.io/components/display/waveshare_epaper/&quot;&gt;waveshare_epaper&lt;/a&gt; component being migrated over time. This
new architecture provides a more maintainable codebase for future ePaper display support.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;security-enhancements&quot;&gt;Security Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.10.0 significantly improves security with several key changes. We conducted an internal security audit that didn’t find any privilege escalation issues but identified many hardening opportunities. We’ve addressed these in this release and will continue to focus on internal security testing in the coming months.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;sha256-ota-authentication&quot;&gt;SHA256 OTA Authentication&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;OTA authentication has been upgraded from MD5 to SHA256 for better security:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modern cryptographic hashing&lt;/strong&gt; replaces legacy MD5 authentication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware acceleration&lt;/strong&gt; on supported ESP32 variants (S3, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-blocking authentication&lt;/strong&gt; for better performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graceful transition period&lt;/strong&gt; - Both SHA256 and MD5 are accepted through 2025.12.x&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MD5 will be rejected starting with 2026.1.0&lt;/strong&gt; on platforms that support SHA256&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;During the transition, you’ll see a warning when MD5 is used. After 2026.1.0, downgrading to older ESPHome versions will require serial flashing instead of OTA.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bonus improvement:&lt;/strong&gt; Extended handshake timeout (20s) makes OTA more reliable on poor WiFi connections without freezing the device.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;api-password-deprecation---heads-up&quot;&gt;API Password Deprecation - Heads Up&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;If you’re still using password authentication for the API, now’s the time to switch to encryption. Password support will be removed in &lt;strong&gt;version 2026.1.0&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This release adds better warnings so you’ll know if you need to update your configuration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;You’ll see a clear warning&lt;/strong&gt; if you’re using passwords - no surprises when support is removed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Can’t use both&lt;/strong&gt; - if you try to configure both password and encryption, ESPHome will stop you (this combination has never worked properly and causes connection failures)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy migration&lt;/strong&gt; - just switch from &lt;code dir=&quot;auto&quot;&gt;password:&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;encryption:&lt;/code&gt; with a key&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You have time&lt;/strong&gt; - password support works until 2026.1.0, giving you plenty of time to update&lt;/li&gt;
&lt;/ul&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;WARNING&lt;/p&gt;
&lt;p&gt;If you’re using &lt;code dir=&quot;auto&quot;&gt;password:&lt;/code&gt; in your API configuration, please migrate to &lt;code dir=&quot;auto&quot;&gt;encryption:&lt;/code&gt; before version 2026.1.0.
Password authentication will be removed at that time. You can’t use both password and encryption together -
pick one (and encryption is the better choice for security).&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;dashboard-improvements&quot;&gt;Dashboard Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The ESPHome Dashboard now uses WebSockets instead of HTTP polling for real-time updates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Instant updates&lt;/strong&gt; - Device status changes appear immediately (no more 1-2 second polling delay)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snappier interface&lt;/strong&gt; - Everything feels more responsive&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lower server load&lt;/strong&gt; - More efficient than constant HTTP polling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logs start instantly&lt;/strong&gt; - The logs command now skips external component updates, eliminating 5-30 second delays when internet is unavailable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you manage multiple devices, the dashboard will feel noticeably faster and more responsive. Viewing logs is now instant even in offline or isolated network environments.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;device-onboarding-improvements&quot;&gt;Device Onboarding Improvements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Getting your ESPHome devices online has never been easier. This release brings major improvements to the initial setup experience, particularly for ESP32-IDF devices and the &lt;a href=&quot;https://esphome.io/guides/made_for_esphome/&quot;&gt;Made for ESPHome&lt;/a&gt; program.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;captive-portal-for-esp-idf&quot;&gt;Captive Portal for ESP-IDF&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;This is huge.&lt;/strong&gt; ESP-IDF devices now have full captive portal support, which means you don’t have to figure out which IP address to type into your browser anymore. When you connect to the device’s access point, your phone or computer automatically detects the captive portal and opens the configuration page - just like connecting to hotel or airport WiFi.&lt;/p&gt;
&lt;p&gt;This brings ESP-IDF up to feature parity with Arduino for onboarding, and since most new ESPHome devices are running ESP-IDF, this dramatically improves the out-of-box experience. The implementation includes a lightweight DNS server that runs in ESPHome’s event loop, responding to all DNS queries with the device’s IP address to trigger captive portal detection on iOS, Android, and other platforms.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;improved-improv-ble-performance&quot;&gt;Improved Improv BLE Performance&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://www.improv-wifi.com/ble/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Improv Wi-Fi over BLE&lt;/a&gt; is the standard way to provision ESPHome devices over Bluetooth, and we’ve made it significantly faster and more reliable:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;26x faster service lookups&lt;/strong&gt; for typical 3-service configurations by replacing HashMap with vectors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1KB flash savings&lt;/strong&gt; plus reduced RAM usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better discoverability&lt;/strong&gt; - Device names are now visible to passive BLE scanners, making ESPHome devices easier to find on a wider range of BLE scanning technologies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Why passive scanning matters:&lt;/strong&gt; Many home automation systems and BLE scanners only support passive scanning (not active scanning). Making the device name visible to passive scanners means your devices show up in more scanning apps and are easier to identify during setup.&lt;/p&gt;
&lt;p&gt;These improvements directly support the &lt;a href=&quot;https://esphome.io/guides/made_for_esphome/&quot;&gt;Made for ESPHome program&lt;/a&gt;, which requires Improv provisioning via BLE for Wi-Fi projects to ensure a consistent, high-quality setup experience across all ESPHome-compatible products.&lt;/p&gt;
&lt;p&gt;The Made for ESPHome program requires Improv BLE provisioning for Wi-Fi projects. See the &lt;a href=&quot;https://esphome.io/guides/made_for_esphome/&quot;&gt;certification requirements&lt;/a&gt; for details.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;home-assistant-action-responses&quot;&gt;Home Assistant Action Responses&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The API now supports receiving responses from Home Assistant actions, enabling bidirectional communication:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Capabilities:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Call Home Assistant actions&lt;/strong&gt; from ESPHome&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Receive response data&lt;/strong&gt; for processing in automations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced integration&lt;/strong&gt; with Home Assistant services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New automation possibilities&lt;/strong&gt; with real-time data exchange&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This feature enables more sophisticated integrations, such as querying state from Home Assistant for use in ESPHome
logic.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;yaml-enhancements&quot;&gt;YAML Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;literal-substitutions&quot;&gt;Literal Substitutions&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;code dir=&quot;auto&quot;&gt;!literal&lt;/code&gt; tag allows raw string values in substitutions without variable expansion:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;substitutions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;json_template&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;!literal&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;{&quot;key&quot;: &quot;${value}&quot;}&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This is particularly useful for JSON templates and other contexts where dollar signs should not trigger
substitution.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;dynamic-auto-loading&quot;&gt;Dynamic Auto-Loading&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Components can now conditionally auto-load dependencies based on configuration, reducing unnecessary component
inclusion and saving memory.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;memory--performance-optimizations&quot;&gt;Memory &amp;#x26; Performance Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.10.0 brings major memory efficiency improvements, with &lt;strong&gt;nearly 3KB of RAM savings&lt;/strong&gt; on typical configurations. As ESPHome has grown more capable over the years, memory usage has naturally increased with new features. ESP8266 devices with their ~40KB of free RAM were starting to feel the squeeze, and ESP32-C3 Bluetooth proxies were experiencing stability issues under load.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We’ve made these use cases much better.&lt;/strong&gt; Through systematic optimization efforts, we’ve reclaimed precious RAM and improved stability across the board. ESP8266 users get more headroom for complex configurations. ESP32-C3 Bluetooth proxy users get better stability with multiple active connections. All platforms benefit from faster performance and lower memory overhead.&lt;/p&gt;
&lt;p&gt;The improvements come from replacing heavy C++ STL containers (vectors, maps, sets) with lighter alternatives and moving data from RAM to flash storage where possible. Each optimization might save a few hundred bytes, but they add up quickly when applied across the codebase.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This is just the beginning&lt;/strong&gt; - we’re continuing this optimization work in 2025.11.0 and beyond. Expect more memory savings and performance improvements in upcoming releases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RAM Savings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;~3KB total RAM savings on ESP8266, ~1-2KB on ESP32&lt;/strong&gt; from all optimizations combined&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lock component&lt;/strong&gt;: 388 bytes flash + 23 bytes RAM per lock via bitmask optimization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 BLE Server&lt;/strong&gt;: 1KB flash savings by replacing HashMap with vectors (26x faster lookups)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Event Emitter&lt;/strong&gt;: 2.6KB flash savings via vector replacement (2.3x faster)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mDNS/OpenThread&lt;/strong&gt;: StaticVector eliminates dynamic allocation overhead&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Script names&lt;/strong&gt;: Moved to flash storage instead of RAM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component metadata&lt;/strong&gt;: Named structs replace std::pair overhead&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API&lt;/strong&gt;: Zero-copy techniques eliminate unnecessary data copying in Bluetooth proxy, Z-Wave proxy, and base API calls (authentication, time zones), reducing allocations and improving performance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Performance Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Logger&lt;/strong&gt;: 35-72% faster log formatting through optimized string handling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Server&lt;/strong&gt;: Significant reduction through lookup tables and IDF server unification&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scheduler&lt;/strong&gt;: Reduced function call overhead&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OTA&lt;/strong&gt;: Non-blocking authentication improves responsiveness&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;USB Host&lt;/strong&gt;: Dedicated FreeRTOS task for continuous event processing prevents data corruption during high-frequency transfers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These optimizations benefit all platforms, but ESP8266 users will notice the most dramatic stability improvements.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-components--features&quot;&gt;New Components &amp;#x26; Features&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;sensor-components&quot;&gt;Sensor Components&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WTS01&lt;/strong&gt; - Temperature sensor with UART interface&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LM75B&lt;/strong&gt; - Popular I2C temperature sensor&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;communication-features&quot;&gt;Communication Features&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiple CAN instances&lt;/strong&gt; on supported ESP32 platforms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UART enhancements&lt;/strong&gt; with multiple ESP32 features and fixes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote receiver demodulation&lt;/strong&gt; support on ESP32&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modbus courtesy responses&lt;/strong&gt; for improved protocol compliance&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;hardware-support&quot;&gt;Hardware Support&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LAN8670 PHY&lt;/strong&gt; support for Ethernet&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configurable Ethernet MAC address&lt;/strong&gt; in YAML&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QMC5883L DRDY pin&lt;/strong&gt; for maximum sampling rate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;USB host/UART&lt;/strong&gt; support on ESP32-P4&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;for-contributors&quot;&gt;For Contributors&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;If you contribute to ESPHome or maintain external components, you’ll notice some big improvements to the development experience:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CI Testing Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Much faster CI for large PRs&lt;/strong&gt; - Large PR test time reduced from ~1 hour to ~20 minutes through intelligent component grouping&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Release builds 6-7x faster&lt;/strong&gt; - Release test time reduced from 12+ hours to 1h40m&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smarter component testing&lt;/strong&gt; - Changed components get isolated test runners with full validation, while dependency-only components are grouped for speed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better feedback loops&lt;/strong&gt; - Get results faster, making it easier to iterate on contributions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;More reliable testing&lt;/strong&gt; - APT package caching (2m30s → 5s), retry logic for downloads, and utilization of a larger available disk partition (66GB instead of 23GB)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These improvements make it much easier to contribute to ESPHome by reducing wait times and making the CI system more efficient and reliable.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.10.0 includes several breaking changes requiring attention:&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;arduino-as-idf-component&quot;&gt;Arduino as IDF Component&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Framework architecture change&lt;/strong&gt; - Arduino is now integrated as an ESP-IDF component&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;/strong&gt;: Build process changes, potential incompatibilities with external components&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Required&lt;/strong&gt;: Test custom components, update framework version handling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR&lt;/strong&gt;: &lt;a href=&quot;https://github.com/esphome/esphome/pull/10647&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10647&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;api-changes&quot;&gt;API Changes&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Several API-related breaking changes improve security and efficiency:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ConnectRequest/Response renamed&lt;/strong&gt; to AuthenticationRequest/Response
&lt;a href=&quot;https://github.com/esphome/esphome/pull/10726&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10726&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password and encryption now mutually exclusive&lt;/strong&gt; with deprecation warnings
&lt;a href=&quot;https://github.com/esphome/esphome/pull/10871&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10871&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configurable connection limits&lt;/strong&gt; added with new defaults &lt;a href=&quot;https://github.com/esphome/esphome/pull/10939&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10939&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Message size limits&lt;/strong&gt; to prevent memory exhaustion &lt;a href=&quot;https://github.com/esphome/esphome/pull/10936&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10936&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ClientInfo::get_combined_info() removed&lt;/strong&gt; to eliminate heap fragmentation
&lt;a href=&quot;https://github.com/esphome/esphome/pull/10970&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10970&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HomeassistantServiceResponse renamed&lt;/strong&gt; to HomeassistantActionRequest
&lt;a href=&quot;https://github.com/esphome/esphome/pull/10839&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10839&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-changes&quot;&gt;Component Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;EKTF2232&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;rts_pin&lt;/code&gt; renamed to &lt;code dir=&quot;auto&quot;&gt;reset_pin&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/10720&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10720&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MMC5603&lt;/strong&gt;: Fixed incorrect calculation factor (values will change)
&lt;a href=&quot;https://github.com/esphome/esphome/pull/9925&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9925&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 BLE&lt;/strong&gt;: max_connections now shared between client and server
&lt;a href=&quot;https://github.com/esphome/esphome/pull/11006&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11006&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logger&lt;/strong&gt;: Runtime tag-specific log levels conditionally compiled
&lt;a href=&quot;https://github.com/esphome/esphome/pull/11004&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11004&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lock&lt;/strong&gt;: Internal representation changed to bitmask &lt;a href=&quot;https://github.com/esphome/esphome/pull/10977&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10977&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mDNS/OpenThread&lt;/strong&gt;: Services storage uses StaticVector &lt;a href=&quot;https://github.com/esphome/esphome/pull/10976&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10976&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;esp32-platform&quot;&gt;ESP32 Platform&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version handling improved&lt;/strong&gt; with stricter validation
&lt;a href=&quot;https://github.com/esphome/esphome/pull/10899&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10899&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web server&lt;/strong&gt;: IDF web server now used for Arduino builds
&lt;a href=&quot;https://github.com/esphome/esphome/pull/10991&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10991&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;audio&quot;&gt;Audio&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;esp-audio-libs updated to 2.0.1&lt;/strong&gt; with new FLAC decoder
&lt;a href=&quot;https://github.com/esphome/esphome/pull/10974&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10974&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most breaking changes involve internal optimizations and security improvements. Standard configurations should
continue working, but custom components and advanced setups may require updates.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;release-2025-10-1---october-16&quot;&gt;Release 2025.10.1 - October 16&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[mipi_spi] Rotation fixes &lt;a href=&quot;https://github.com/esphome/esphome/pull/11226&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11226&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; (new-feature)&lt;/li&gt;
&lt;li&gt;[ota] Fix MQTT resolution when static IP appears first in device list &lt;a href=&quot;https://github.com/esphome/esphome/pull/11272&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11272&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ota.esphome] Handle blank password the same as no password defined &lt;a href=&quot;https://github.com/esphome/esphome/pull/11271&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11271&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[tests] Fix OTA password test assertions after merge collision &lt;a href=&quot;https://github.com/esphome/esphome/pull/11275&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11275&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix enterprise wifi &lt;a href=&quot;https://github.com/esphome/esphome/pull/11276&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11276&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[substitutions] Fix AttributeError when using packages with substitutions &lt;a href=&quot;https://github.com/esphome/esphome/pull/11274&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11274&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-10-2---october-20&quot;&gt;Release 2025.10.2 - October 20&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[datetime] Fix DateTimeStateTrigger compilation when time component is not used &lt;a href=&quot;https://github.com/esphome/esphome/pull/11287&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11287&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Add ESP32 ROM functions to reserved ids &lt;a href=&quot;https://github.com/esphome/esphome/pull/11293&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11293&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[htu21d] Revert register address change &lt;a href=&quot;https://github.com/esphome/esphome/pull/11291&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11291&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Reduce tx power on Arduino in the event of a brownout &lt;a href=&quot;https://github.com/esphome/esphome/pull/11304&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11304&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[const] Add CONF_OPENTHREAD &lt;a href=&quot;https://github.com/esphome/esphome/pull/11318&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11318&lt;/a&gt; by &lt;a href=&quot;https://github.com/danstiner&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@danstiner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[dashboard] Fix binary download with packages using secrets after Path migration &lt;a href=&quot;https://github.com/esphome/esphome/pull/11313&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11313&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[dashboard] fix migration to Path &lt;a href=&quot;https://github.com/esphome/esphome/pull/11342&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11342&lt;/a&gt; by &lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[scd4x, bme68x] Fix temperature_offset to use the temperature_delta instead of temperature &lt;a href=&quot;https://github.com/esphome/esphome/pull/11347&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11347&lt;/a&gt; by &lt;a href=&quot;https://github.com/Spectre5&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Spectre5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix IndexError when OTA devices cannot be resolved &lt;a href=&quot;https://github.com/esphome/esphome/pull/11311&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11311&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Fix OTA rollback &lt;a href=&quot;https://github.com/esphome/esphome/pull/11300&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11300&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[openthread] Backport address resolution support to prevent OTA crash &lt;a href=&quot;https://github.com/esphome/esphome/pull/11312&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11312&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-10-3---october-24&quot;&gt;Release 2025.10.3 - October 24&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[hdc1080] Make HDC1080_CMD_CONFIGURATION failure a warning (and log it) &lt;a href=&quot;https://github.com/esphome/esphome/pull/11355&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11355&lt;/a&gt; by &lt;a href=&quot;https://github.com/pzich&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@pzich&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[uart] Make rx pin respect pullup and pulldown settings &lt;a href=&quot;https://github.com/esphome/esphome/pull/9248&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9248&lt;/a&gt; by &lt;a href=&quot;https://github.com/asergunov&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@asergunov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] handle mixed IP and DNS addresses correctly in resolve_ip_address &lt;a href=&quot;https://github.com/esphome/esphome/pull/11503&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11503&lt;/a&gt; by &lt;a href=&quot;https://github.com/Links2004&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Links2004&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-10-4---november-4&quot;&gt;Release 2025.10.4 - November 4&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[uart] Fix order of initialization calls &lt;a href=&quot;https://github.com/esphome/esphome/pull/11510&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11510&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix the LiberTiny bug with UART pin setup &lt;a href=&quot;https://github.com/esphome/esphome/pull/11518&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11518&lt;/a&gt; by &lt;a href=&quot;https://github.com/asergunov&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@asergunov&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_rgb] Fix rotation with custom model &lt;a href=&quot;https://github.com/esphome/esphome/pull/11585&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11585&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt; (new-feature)&lt;/li&gt;
&lt;li&gt;[lvgl] Fix nested lambdas in automations unable to access parameters &lt;a href=&quot;https://github.com/esphome/esphome/pull/11583&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11583&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[image] Catch and report svg load errors &lt;a href=&quot;https://github.com/esphome/esphome/pull/11619&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11619&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix event for binary sensor &lt;a href=&quot;https://github.com/esphome/esphome/pull/11636&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11636&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sdl] Fix keymappings &lt;a href=&quot;https://github.com/esphome/esphome/pull/11635&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11635&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-10-5---november-11&quot;&gt;Release 2025.10.5 - November 11&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[const] Add CONF_ROWS &lt;a href=&quot;https://github.com/esphome/esphome/pull/11249&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11249&lt;/a&gt; by &lt;a href=&quot;https://github.com/stuartparmenter&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@stuartparmenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Don’t allow python 3.14 &lt;a href=&quot;https://github.com/esphome/esphome/pull/11527&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11527&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[usb_uart] Fixes for transfer queue allocation &lt;a href=&quot;https://github.com/esphome/esphome/pull/11548&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11548&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix rotation with unusual width &lt;a href=&quot;https://github.com/esphome/esphome/pull/11680&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#11680&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2025.10.0/&quot;&gt;full 2025.10.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2025.9.0: MIPI RGB displays and a camera JPEG encoder</title><link>https://esphome.io/blog/2025/09/17/esphome-2025-9/</link><guid isPermaLink="true">https://esphome.io/blog/2025/09/17/esphome-2025-9/</guid><description>ESPHome 2025.9.0 adds MIPI RGB display support, a camera JPEG encoder, DFU support for nRF52, and ESPHome Builder improvements, along with extensive memory optimizations.</description><pubDate>Wed, 17 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/display/mipi_rgb/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/indicator.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;MIPI ​RGB ​Displays&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/camera/camera_encoder/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/camera.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Camera ​Encoder&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.9.0 brings significant enhancements to display technology, camera functionality, and performance
optimizations. This release focuses on advanced display capabilities, improved memory efficiency, and enhanced
developer tools while maintaining backward compatibility for most use cases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Highlights:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MIPI RGB Display support&lt;/strong&gt; for high-performance color displays with dedicated hardware acceleration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESPHome Builder improvements&lt;/strong&gt; with support for uploading existing YAML files and blank configurations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Camera JPEG encoder&lt;/strong&gt; enabling efficient image compression and streaming capabilities&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced NRF52 features&lt;/strong&gt; including DFU (Device Firmware Update) support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensive memory optimizations&lt;/strong&gt; reducing flash and RAM usage across all platforms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved sensor support&lt;/strong&gt; with enhanced BL0940 power monitoring capabilities&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component improvements&lt;/strong&gt; including restructured Inkplate e-paper display support&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;-welcome-jonathan-to-the-open-home-foundation-team&quot;&gt;🎉 Welcome Jonathan to the Open Home Foundation Team!&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We’re excited to announce that Jonathan (&lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;) has joined the
Open Home Foundation as a &lt;strong&gt;full-time developer on ESPHome&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Jonathan has been a long-standing and valued contributor, and now he’ll be able to focus fully on building
ESPHome — helping people create smart homes that are &lt;strong&gt;private, sustainable, and built on open standards&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This milestone is made possible by the support of our community and the Open Home Foundation’s mission to advance
&lt;strong&gt;open-source smart home technologies&lt;/strong&gt; while upholding the principles of &lt;strong&gt;privacy, choice, and sustainability&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If you’d like to support continued development of ESPHome and other open home projects, consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Supporting the Open Home Foundation&lt;/strong&gt; → &lt;a href=&quot;https://www.openhomefoundation.org/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;openhomefoundation.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribing to Home Assistant Cloud&lt;/strong&gt; → &lt;a href=&quot;https://www.nabucasa.com/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;nabucasa.com&lt;/a&gt; to help fund open-source development&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🚀 Welcome to the team, Jonathan — we can’t wait to see what you’ll help build!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;mipi-rgb-display-support&quot;&gt;MIPI RGB Display Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.9.0 introduces comprehensive support for MIPI RGB displays through the new
&lt;a href=&quot;https://esphome.io/components/display/mipi_rgb/&quot;&gt;Mipi Rgb&lt;/a&gt; component.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hardware acceleration&lt;/strong&gt; through dedicated MIPI controllers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High refresh rates&lt;/strong&gt; with excellent color reproduction&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unified configuration&lt;/strong&gt; supporting multiple display models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced CPU overhead&lt;/strong&gt; compared to traditional parallel displays&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Professional display quality&lt;/strong&gt; for advanced user interfaces&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MIPI RGB displays offer superior performance for applications requiring high-quality graphics, smooth animations, and
professional-grade user interfaces.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esphome-builder-enhancements&quot;&gt;ESPHome Builder Enhancements&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The ESPHome Builder web interface now offers improved flexibility for getting started with your projects:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Capabilities:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Upload existing YAML files&lt;/strong&gt; to continue working on configurations created elsewhere&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Start with a blank configuration&lt;/strong&gt; for complete customization from scratch&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;camera-jpeg-encoder&quot;&gt;Camera JPEG Encoder&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/camera/camera_encoder/&quot;&gt;Camera Encoder&lt;/a&gt; component adds efficient JPEG compression capabilities to
ESP32 camera implementations, enabling:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reduced bandwidth&lt;/strong&gt; for image transmission over WiFi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lower storage requirements&lt;/strong&gt; for image capture applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved streaming performance&lt;/strong&gt; with compressed image data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configurable quality settings&lt;/strong&gt; to balance size vs. quality&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware acceleration&lt;/strong&gt; where available on supported platforms&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This component is particularly valuable for security cameras, time-lapse photography, and any application requiring
efficient image handling.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;enhanced-nrf52-platform&quot;&gt;Enhanced NRF52 Platform&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Building on the NRF52 platform introduced in 2025.8.0, this release adds crucial development and deployment features:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Capabilities:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DFU (Device Firmware Update)&lt;/strong&gt; support for over-the-air updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved debugging tools&lt;/strong&gt; with enhanced Zephyr integration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These enhancements make NRF52 development more practical for production deployments while maintaining the low-power
advantages of Nordic semiconductors.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;memory--performance-optimizations&quot;&gt;Memory &amp;#x26; Performance Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.9.0 continues the optimization efforts with significant improvements:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flash Memory Savings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Component source strings moved to flash&lt;/strong&gt; (ESP8266) saving substantial RAM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPIO memory optimization&lt;/strong&gt; reducing usage by up to 50% through bit-packing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scheduler improvements&lt;/strong&gt; with memory pools to reduce heap fragmentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String optimizations&lt;/strong&gt; eliminating unnecessary allocations in core functions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Runtime Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enhanced GPIO expander support&lt;/strong&gt; with cached operations reducing I2C bus usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimized sensor logging&lt;/strong&gt; with compile-time string management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better timezone synchronization&lt;/strong&gt; allowing the timezone to be sent from Home Assistant for devices that are
pre-installed with ESPHome&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.9.0 includes several breaking changes that may require configuration updates:&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;core-preference-storage-changes&quot;&gt;Core Preference Storage Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Device ID consideration&lt;/strong&gt;: Preference storage now accounts for device_id to prevent conflicts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;/strong&gt;: Devices may lose some stored preferences on first boot after upgrade&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Required&lt;/strong&gt;: No configuration changes needed, but stored calibration data may need to be reconfigured&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;lvgl-spinbox-configuration&quot;&gt;LVGL Spinbox Configuration&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Configuration change&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;step&lt;/code&gt; property replaced with &lt;code dir=&quot;auto&quot;&gt;selected_digit&lt;/code&gt; for spinbox widgets&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;/strong&gt;: Existing LVGL spinbox configurations will fail validation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Required&lt;/strong&gt;: Update spinbox configurations to use &lt;code dir=&quot;auto&quot;&gt;selected_digit&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;step&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;bluetooth-proxy-connection-defaults&quot;&gt;Bluetooth Proxy Connection Defaults&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Default change&lt;/strong&gt;: Active connections now default to &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;/strong&gt;: Bluetooth proxy will allow active connections by default&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Required&lt;/strong&gt;: Explicitly set &lt;code dir=&quot;auto&quot;&gt;active: false&lt;/code&gt; if you want to maintain previous behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;api-and-memory-optimizations&quot;&gt;API and Memory Optimizations&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;String function changes&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;state_class_to_string()&lt;/code&gt; now returns &lt;code dir=&quot;auto&quot;&gt;const char*&lt;/code&gt; instead of &lt;code dir=&quot;auto&quot;&gt;std::string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component storage changes&lt;/strong&gt;: Component source strings moved to flash memory on ESP8266&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;/strong&gt;: Custom components using these functions may need updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Required&lt;/strong&gt;: Update custom components to handle new return types&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;inkplate-component-rename&quot;&gt;Inkplate Component Rename&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Component renamed&lt;/strong&gt;: Inkplate component has been renamed and grayscale handling improved&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;/strong&gt;: Existing Inkplate configurations will need component name updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Required&lt;/strong&gt;: Update component references in your configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most breaking changes are internal optimizations that shouldn’t affect typical configurations, but custom components
and advanced setups may require updates.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;release-2025-9-1---september-19&quot;&gt;Release 2025.9.1 - September 19&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[mqtt] Fix KeyError when MQTT logging configured without explicit level &lt;a href=&quot;https://github.com/esphome/esphome/pull/10774&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10774&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;fix(packet_transport): Add initialization for sensor configuration in packet transport &lt;a href=&quot;https://github.com/esphome/esphome/pull/10765&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10765&lt;/a&gt; by &lt;a href=&quot;https://github.com/TMaYaD&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@TMaYaD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Fix ESP8266 mDNS compilation failure caused by incorrect coroutine priorities &lt;a href=&quot;https://github.com/esphome/esphome/pull/10773&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10773&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[gpio] Fix unused function warnings when compiling with log level below DEBUG &lt;a href=&quot;https://github.com/esphome/esphome/pull/10779&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10779&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-9-2---september-29&quot;&gt;Release 2025.9.2 - September 29&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[esp32_improv] Disable loop by default until provisioning needed &lt;a href=&quot;https://github.com/esphome/esphome/pull/10764&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10764&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[libretiny] Fix lib_ignore handling and ignore incompatible libraries &lt;a href=&quot;https://github.com/esphome/esphome/pull/10846&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10846&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Set color_order to RGB for the Waveshare ESP32-S3-TOUCH-LCD-4.3 and ESP32-S3-TOUCH-LCD-7-800X480 &lt;a href=&quot;https://github.com/esphome/esphome/pull/10835&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10835&lt;/a&gt; by &lt;a href=&quot;https://github.com/stuartparmenter&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@stuartparmenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_improv] Fix crashes from uninitialized pointers and missing null checks &lt;a href=&quot;https://github.com/esphome/esphome/pull/10902&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10902&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sx126x] Fix issues with variable length FSK packets &lt;a href=&quot;https://github.com/esphome/esphome/pull/10911&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10911&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] Fix t-display-amoled &lt;a href=&quot;https://github.com/esphome/esphome/pull/10922&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10922&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-9-3---october-1&quot;&gt;Release 2025.9.3 - October 1&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[api] Prevent API from overriding noise encryption keys set in YAML &lt;a href=&quot;https://github.com/esphome/esphome/pull/10927&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10927&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sim800l] Fixed ignoring incoming calls. &lt;a href=&quot;https://github.com/esphome/esphome/pull/10865&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10865&lt;/a&gt; by &lt;a href=&quot;https://github.com/vmakeev&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@vmakeev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[voice_assistant] Fix wakeword string being reset while referenced &lt;a href=&quot;https://github.com/esphome/esphome/pull/10945&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10945&lt;/a&gt; by &lt;a href=&quot;https://github.com/abmantis&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@abmantis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2025.9.0/&quot;&gt;full 2025.9.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2025.8.0: nRF52 support and ESP-NOW mesh communication</title><link>https://esphome.io/blog/2025/08/20/esphome-2025-8/</link><guid isPermaLink="true">https://esphome.io/blog/2025/08/20/esphome-2025-8/</guid><description>ESPHome 2025.8.0 introduces the Nordic nRF52 platform built on Zephyr, ESP-NOW device-to-device communication, and MIPI DSI display support, and now requires Python 3.11 or newer.</description><pubDate>Wed, 20 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/nrf52/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/nrf52.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;NRF5​2​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/espnow/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/esp-now.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;ESP-​NOW&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/display/mipi_dsi/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/tab5.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;MIPI ​DSI ​Displays&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/ld2412/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ld2412.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LD2​4​1​2​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/runtime_stats/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/pulse.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;Runtime ​Stats&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.8.0 expands platform support with the introduction of Nordic nRF52 devices,
adds mesh communication capabilities, and delivers significant performance improvements. This release
focuses on architectural innovation and memory optimization while introducing new hardware possibilities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Highlights:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New nRF52 platform&lt;/strong&gt; based on Zephyr RTOS opens Nordic semiconductor ecosystem&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP-NOW mesh communication&lt;/strong&gt; enables direct device-to-device connectivity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High-performance MIPI DSI displays&lt;/strong&gt; for ESP32-P4 professional applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensive memory optimizations&lt;/strong&gt; with up to 10x performance improvements in key areas&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python 3.11+ requirement&lt;/strong&gt; (breaking change - Python 3.10 support dropped)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;nrf52-platform-support&quot;&gt;NRF52 Platform Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.8.0 introduces basic support for Nordic nRF52 series microcontrollers through the new
&lt;a href=&quot;https://esphome.io/components/nrf52/&quot;&gt;Nrf52&lt;/a&gt; platform. This implementation is built on the Zephyr RTOS, providing a robust
foundation for Nordic semiconductor devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complete platform integration&lt;/strong&gt; with ESPHome’s component ecosystem&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ADC support&lt;/strong&gt; for analog sensor reading with configurable resolution&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPIO functionality&lt;/strong&gt; with interrupt support and pin configuration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zephyr debug component&lt;/strong&gt; for advanced debugging and development&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The nRF52 platform opens up new possibilities for low-power, Bluetooth-enabled devices while maintaining
the familiar ESPHome configuration syntax and component compatibility.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;esp-now-communication&quot;&gt;ESP-NOW Communication&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The new &lt;a href=&quot;https://esphome.io/components/espnow/&quot;&gt;Espnow&lt;/a&gt; component brings device-to-device communication to ESP32 platforms without
requiring WiFi infrastructure. ESP-NOW enables direct communication between ESP32 devices using the 2.4GHz
band with minimal power consumption.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Applications:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mesh sensor networks&lt;/strong&gt; - Sensors can communicate directly without WiFi routers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote control systems&lt;/strong&gt; - Direct device control with low latency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup communication&lt;/strong&gt; - Fallback when WiFi is unavailable&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Battery-powered devices&lt;/strong&gt; - Efficient communication for power-constrained applications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This protocol is particularly valuable for distributed sensor networks and scenarios where traditional
WiFi infrastructure is impractical or unavailable.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;mipi-dsi-display-support&quot;&gt;MIPI DSI Display Support&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome now supports high-performance MIPI DSI displays through the new &lt;a href=&quot;https://esphome.io/components/display/mipi_dsi/&quot;&gt;Mipi Dsi&lt;/a&gt;
component, specifically designed for ESP32-P4 processors with DSI interfaces.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;High-resolution displays&lt;/strong&gt; with excellent performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware acceleration&lt;/strong&gt; through dedicated DSI controllers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced CPU overhead&lt;/strong&gt; compared to traditional SPI displays&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Professional display quality&lt;/strong&gt; for advanced applications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This addition significantly expands ESPHome’s display capabilities, enabling professional-grade user interfaces
and high-resolution graphics applications.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;memory--performance-optimizations&quot;&gt;Memory &amp;#x26; Performance Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.8.0 includes extensive optimizations focused on reducing memory usage and improving performance:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flash Memory Savings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conditional compilation removes unused API features (thousands of bytes saved)&lt;/li&gt;
&lt;li&gt;Optimized protobuf implementations with zero-copy techniques&lt;/li&gt;
&lt;li&gt;Reduced code duplication across components&lt;/li&gt;
&lt;li&gt;Streamlined error handling and logging systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Runtime Performance:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;10x faster string encoding with optimized memcpy operations&lt;/li&gt;
&lt;li&gt;Enhanced scheduler with reduced millis() calls&lt;/li&gt;
&lt;li&gt;Improved BLE scanning with batched processing&lt;/li&gt;
&lt;li&gt;Zero-copy protobuf fields for reduced memory allocations&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;python-3-11-requirement&quot;&gt;Python 3.11+ Requirement&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Starting with ESPHome 2025.8.0, &lt;strong&gt;Python 3.11 or higher is required&lt;/strong&gt; to run ESPHome. This change enables us to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utilize modern Python features and improvements&lt;/li&gt;
&lt;li&gt;Remove legacy compatibility code that was needed for older Python versions&lt;/li&gt;
&lt;li&gt;Maintain a more secure and efficient codebase&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;why-this-change&quot;&gt;Why This Change?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Python 3.10 reaches its &lt;a href=&quot;https://devguide.python.org/versions/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;end of life in October 2026&lt;/a&gt;. This
upgrade is necessary for the project to move forward with modern development practices and maintain
long-term security and maintainability.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;what-you-need-to-do&quot;&gt;What You Need to Do&lt;/h3&gt;&lt;/div&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Installation Method&lt;/th&gt;&lt;th&gt;Action Required&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Home Assistant Add-on&lt;/td&gt;&lt;td&gt;&lt;strong&gt;No action needed&lt;/strong&gt; - Already uses Python 3.12&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Container Images (Docker)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;No action needed&lt;/strong&gt; - Already uses Python 3.12&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Direct Installation (pip)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Upgrade Python to 3.11+&lt;/strong&gt; before updating ESPHome&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;WARNING&lt;/p&gt;
&lt;p&gt;If you’re running ESPHome directly on your machine with Python 3.10 or older, running &lt;code dir=&quot;auto&quot;&gt;pip install -U esphome&lt;/code&gt;
will not upgrade beyond version 2025.7.x. You must upgrade your Python installation first.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.8.0 includes several breaking changes that may require action on your part:&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;bluetooth-and-ble-changes&quot;&gt;Bluetooth and BLE Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Bluetooth Proxy: Parsed advertisement support and V1 connection support removed to save memory&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;BLE: Conditional compilation for advertising and service classes may reduce available features if not
explicitly enabled&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;May affect older components using deprecated Bluetooth features&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;api-optimizations&quot;&gt;API Optimizations&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Deprecated protobuf fields removed (reduces flash usage)&lt;/li&gt;
&lt;li&gt;Conditional compilation for Home Assistant state/service subscriptions&lt;/li&gt;
&lt;li&gt;May affect custom API clients using deprecated fields&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;component-filter-changes&quot;&gt;Component Filter Changes&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://esphome.io/components/sensor/ld2410/&quot;&gt;LD2410&lt;/a&gt; and &lt;a href=&quot;https://esphome.io/components/sensor/ld2450/&quot;&gt;LD2450&lt;/a&gt;
components now use native filters instead of &lt;code dir=&quot;auto&quot;&gt;throttle&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;See the component documentation for updated filter configuration&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;esp32-touch-sensor&quot;&gt;ESP32 Touch Sensor&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Workaround implemented for ESP-IDF v5.4 regression&lt;/li&gt;
&lt;li&gt;May affect touch sensor behavior on newer ESP-IDF versions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most of these changes are automatic optimizations that shouldn’t affect typical usage, but custom components
or advanced configurations may need updates.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;release-2025-8-1---august-25&quot;&gt;Release 2025.8.1 - August 25&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[api] Add zero-copy StringRef methods for compilation_time and effect_name &lt;a href=&quot;https://github.com/esphome/esphome/pull/10257&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10257&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_client] Add log helper functions to reduce flash usage by 120 bytes &lt;a href=&quot;https://github.com/esphome/esphome/pull/10243&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10243&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Add &lt;code dir=&quot;auto&quot;&gt;USE_API_HOMEASSISTANT_SERVICES&lt;/code&gt; if using &lt;code dir=&quot;auto&quot;&gt;tag_scanned&lt;/code&gt; action &lt;a href=&quot;https://github.com/esphome/esphome/pull/10316&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10316&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[http_request] Fix for host after ArduinoJson library bump &lt;a href=&quot;https://github.com/esphome/esphome/pull/10348&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10348&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Improve error reporting for entity name conflicts with non-ASCII characters &lt;a href=&quot;https://github.com/esphome/esphome/pull/10329&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10329&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[pvvx_mithermometer] Fix race condition with BLE authentication &lt;a href=&quot;https://github.com/esphome/esphome/pull/10327&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10327&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_client] Optimize BLE connection parameters for different connection types &lt;a href=&quot;https://github.com/esphome/esphome/pull/10356&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10356&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble] Increase GATT connection retry count to use full timeout window &lt;a href=&quot;https://github.com/esphome/esphome/pull/10376&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10376&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[script] Fix parallel mode scripts with delays cancelling each other &lt;a href=&quot;https://github.com/esphome/esphome/pull/10324&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10324&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[deep_sleep] Fix ESP32-C6 compilation error with gpio_deep_sleep_hold_en() &lt;a href=&quot;https://github.com/esphome/esphome/pull/10345&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10345&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_client] Reduce log level for harmless BLE timeout race conditions &lt;a href=&quot;https://github.com/esphome/esphome/pull/10339&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10339&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix meter rotation &lt;a href=&quot;https://github.com/esphome/esphome/pull/10342&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10342&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_ble_tracker] Fix on_scan_end trigger compilation without USE_ESP32_BLE_DEVICE &lt;a href=&quot;https://github.com/esphome/esphome/pull/10399&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10399&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[test] Add integration test for light effect memory corruption fix &lt;a href=&quot;https://github.com/esphome/esphome/pull/10417&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10417&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[web_server] Use oi.esphome.io for css and js assets &lt;a href=&quot;https://github.com/esphome/esphome/pull/10296&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10296&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-8-2---august-29&quot;&gt;Release 2025.8.2 - August 29&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[wifi] Fix reconnection failures after adapter restart by not clearing netif pointers &lt;a href=&quot;https://github.com/esphome/esphome/pull/10458&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10458&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_spi] Fix dimensions &lt;a href=&quot;https://github.com/esphome/esphome/pull/10443&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10443&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[i2c] Perform register reads as single transactions &lt;a href=&quot;https://github.com/esphome/esphome/pull/10389&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10389&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wifi] Fix retry with hidden networks. &lt;a href=&quot;https://github.com/esphome/esphome/pull/10445&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10445&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix AttributeError when uploading OTA to offline OpenThread devices &lt;a href=&quot;https://github.com/esphome/esphome/pull/10459&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10459&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[rtttl] Fix RTTTL for speakers &lt;a href=&quot;https://github.com/esphome/esphome/pull/10381&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10381&lt;/a&gt; by &lt;a href=&quot;https://github.com/fortuna&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@fortuna&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esphome] Fix OTA watchdog resets by validating all magic bytes before blocking &lt;a href=&quot;https://github.com/esphome/esphome/pull/10401&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10401&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-8-3---september-4&quot;&gt;Release 2025.8.3 - September 4&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[mcp4461] Fix reading level &lt;a href=&quot;https://github.com/esphome/esphome/pull/10479&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10479&lt;/a&gt; by &lt;a href=&quot;https://github.com/p1ngb4ck&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@p1ngb4ck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix incorrect entity count due to undefined execution order with globals &lt;a href=&quot;https://github.com/esphome/esphome/pull/10497&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10497&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mipi_dsi] Fix config for Guition screen &lt;a href=&quot;https://github.com/esphome/esphome/pull/10464&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10464&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[mcp4461] Fix read transaction &lt;a href=&quot;https://github.com/esphome/esphome/pull/10465&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10465&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Rebuild when idf_component.yml changes &lt;a href=&quot;https://github.com/esphome/esphome/pull/10540&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10540&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[i2c] Fix bug in write_register16 &lt;a href=&quot;https://github.com/esphome/esphome/pull/10547&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10547&lt;/a&gt; by &lt;a href=&quot;https://github.com/latonita&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@latonita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Clear IDF environment variables &lt;a href=&quot;https://github.com/esphome/esphome/pull/10527&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10527&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fix VERY_VERBOSE logging compilation error with bool arrays &lt;a href=&quot;https://github.com/esphome/esphome/pull/10539&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10539&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-8-4---september-10&quot;&gt;Release 2025.8.4 - September 10&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[sen5x] Fix initialization &lt;a href=&quot;https://github.com/esphome/esphome/pull/10603&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10603&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[kmeteriso] Fix i2c call &lt;a href=&quot;https://github.com/esphome/esphome/pull/10618&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10618&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[light] add missing header &lt;a href=&quot;https://github.com/esphome/esphome/pull/10590&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10590&lt;/a&gt; by &lt;a href=&quot;https://github.com/tomaszduda23&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tomaszduda23&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2025.8.0/&quot;&gt;full 2025.8.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item><item><title>ESPHome 2025.7.0: Web server OTA, LoRa, and sub-devices</title><link>https://esphome.io/blog/2025/07/16/esphome-2025-7/</link><guid isPermaLink="true">https://esphome.io/blog/2025/07/16/esphome-2025-7/</guid><description>ESPHome 2025.7.0 moves web server OTA to its own platform, removes ESP-IDF 4.x support, adds sub-device support and Jinja2 template expressions, and introduces LoRa hardware support.</description><pubDate>Wed, 16 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/one_wire/ds2484/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ds2484.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;DS2​4​8​4​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/esp32_hosted/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/network-wifi.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;ESP3​2​ ​Hosted&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/gl_r01/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/gl_r01.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;GL-​R0​1​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/libretiny/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/ln882x.svg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LN8​8​2​x&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/lps22/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/lps22.webp&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;LPS2​2​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/opt3001/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/opt3001.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;OPT3​0​0​1​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/pi4ioe5v6408/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/pca9554a.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;PI4​IOE5​V6​4​0​8​&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sx126x/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/sx126x.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;SX1​2​6​x&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sx127x/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/sx127x.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;SX1​2​7​x&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://esphome.io/components/sensor/xiaomi_ble/&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://esphome.io/images/xiaomi_mijia_logo.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;&lt;div&gt;XMWSDJ0​4​MMC&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;release-overview&quot;&gt;Release Overview&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.7.0 is a major release featuring significant architectural improvements, new hardware support,
and important platform updates. This release modernizes the codebase while expanding hardware compatibility
and introducing powerful new features for advanced users.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Major Changes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Web Server OTA&lt;/strong&gt; moved to dedicated platform (breaking change - migration required)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP-IDF 4.x support removed&lt;/strong&gt; - ESP-IDF 5.3.2+ now required&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 Arduino updated to 3.1.3&lt;/strong&gt; for better compatibility and performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sub-device support&lt;/strong&gt; for logical entity grouping in Home Assistant&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jinja2 template expressions&lt;/strong&gt; for dynamic configuration generation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New Hardware:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LoRa communication (SX126x/SX127x), ESP32 Hosted WiFi, LN882X SoCs&lt;/li&gt;
&lt;li&gt;New sensors: OPT3001 light, LPS22 pressure, GL-R01 ToF, Xiaomi BLE&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extensive memory optimizations (up to 40% reduction in component memory usage)&lt;/li&gt;
&lt;li&gt;Enhanced performance through C++20 support and optimized algorithms&lt;/li&gt;
&lt;li&gt;Improved interrupt handling and scheduler efficiency&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;web-server-ota-platform&quot;&gt;Web Server OTA Platform&lt;/h2&gt;&lt;/div&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;WARNING&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Breaking Change:&lt;/strong&gt; Read this carefully! If your only OTA method is &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt; and you don’t have it explicitly
enabled, you will lose the ability to update devices OTA after updating to 2025.7.0. You must add the &lt;code dir=&quot;auto&quot;&gt;web_server&lt;/code&gt;
OTA platform to your configuration to maintain OTA functionality.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://esphome.io/components/web_server/&quot;&gt;Web Server&lt;/a&gt; component has undergone a significant architectural change. Previously,
OTA functionality was built directly into the web server component. This has now been extracted into a dedicated
OTA platform: &lt;a href=&quot;https://esphome.io/components/ota/web_server/&quot;&gt;Web Server&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Migration Required:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you were relying on the web server’s built-in OTA functionality, you now need to explicitly configure the web
server OTA platform:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Before (implicit OTA in web server)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;web_server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# After (explicit OTA platform required)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;web_server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ota&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Your existing OTA method&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;web_server&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Add this for web-based OTA uploads&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Benefits of this change:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cleaner separation of concerns&lt;/strong&gt; - Web server focuses on serving content, OTA platform handles updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;More flexible OTA configuration&lt;/strong&gt; - Better control over OTA methods and security&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved maintainability&lt;/strong&gt; - Dedicated OTA platform allows for better features and bug fixes&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;esp-idf-4-x-end-of-life&quot;&gt;ESP-IDF 4.x End of Life&lt;/h2&gt;&lt;/div&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Major Platform Change:&lt;/strong&gt; This release completely removes support for ESP-IDF 4.x versions, marking the end of life
for these older framework versions.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;ESPHome 2025.7.0 removes all support for ESP-IDF 4.x versions as part of our commitment to supporting modern,
secure, and well-maintained development frameworks. Please see our
&lt;a href=&quot;https://developers.esphome.io/blog/2025/06/18/sunsetting-support-for-idf-4x/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;developer blog post&lt;/a&gt; for detailed
background and technical reasons behind this decision.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What this means for users:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Most users are unaffected&lt;/strong&gt; - We automatically set the recommended ESP-IDF version (currently 5.3.2) as the default&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Explicit version users must update&lt;/strong&gt; - If you’re explicitly setting the ESP-IDF version in your configuration,
you must update to version 5.3.2 or later&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Legacy projects may need updates&lt;/strong&gt; - Older projects might require minor configuration adjustments&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Required action if you explicitly set ESP-IDF version:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Remove or update old explicit versions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esp32&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;board&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp32dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;framework&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp-idf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;4.4.7&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# ❌ No longer supported&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Update to supported version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esp32&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;board&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp32dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;framework&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;esp-idf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;5.3.2&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# ✅ Supported (or omit for latest recommended)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Benefits of ESP-IDF 5.x:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enhanced security&lt;/strong&gt; - Latest security patches and improvements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better performance&lt;/strong&gt; - Optimized code generation and runtime performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modern C++ support&lt;/strong&gt; - Full C++20 support with improved standard library&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expanded hardware support&lt;/strong&gt; - Better support for newer ESP32 variants (S2, S3, C3, C6, H2)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Active maintenance&lt;/strong&gt; - Continued updates and bug fixes from Espressif&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;esp32-arduino-framework-3-x&quot;&gt;ESP32 Arduino Framework 3.x&lt;/h2&gt;&lt;/div&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Framework Update:&lt;/strong&gt; Arduino for ESP32 has been upgraded to version 3.1.3, bringing significant improvements
and maintaining compatibility with ESP-IDF 5.3.2.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To maintain alignment and compatibility with the current ESP-IDF version of 5.3.2, the Arduino framework for ESP32
has been updated to version 3.1.3. This represents a major version jump from Arduino 2.x.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key improvements in Arduino 3.1.3:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP-IDF 5.3.2 compatibility&lt;/strong&gt; - Full integration with the latest ESP-IDF features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved stability&lt;/strong&gt; - Better memory management and reduced crashes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced WiFi performance&lt;/strong&gt; - More reliable connections and better power management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Updated libraries&lt;/strong&gt; - Latest versions of core Arduino libraries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bug fixes&lt;/strong&gt; - Numerous fixes for issues present in earlier versions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Potential compatibility considerations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some third-party Arduino libraries may need updates for Arduino 3.x compatibility&lt;/li&gt;
&lt;li&gt;Timing-sensitive code might behave slightly differently due to framework optimizations&lt;/li&gt;
&lt;li&gt;Memory usage patterns may change slightly due to framework improvements&lt;/li&gt;
&lt;/ul&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flash Usage Warning:&lt;/strong&gt; Arduino 3.x can use more flash memory than Arduino 2.x, which may cause some projects
with many components to exceed available flash space. If you encounter flash size issues, consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Switching to ESP-IDF framework (recommended for large projects)&lt;/li&gt;
&lt;li&gt;Reducing the number of enabled components&lt;/li&gt;
&lt;li&gt;Using a board with more flash memory&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Most users will see this as a transparent improvement with better performance and reliability.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;sub-device-support&quot;&gt;Sub-Device Support&lt;/h2&gt;&lt;/div&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Feature:&lt;/strong&gt; Entities can now be organized into logical sub-devices, enabling better organization
and area management in Home Assistant.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;ESPHome now supports &lt;strong&gt;sub-devices&lt;/strong&gt;, a powerful new feature that allows you to logically group entities from a single
physical ESPHome device into multiple virtual devices within Home Assistant. This is particularly useful for complex
setups where one ESP32 controls sensors or actuators in different areas of your home.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use cases and benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Multi-room sensors&lt;/strong&gt; - One ESP32 with temperature sensors in different rooms can appear as separate devices per room&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Complex automation hubs&lt;/strong&gt; - A single ESP32 controlling lights, fans, and sensors across multiple areas&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Better Home Assistant organization&lt;/strong&gt; - Entities automatically appear in the correct areas and can be managed
independently&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cleaner dashboards&lt;/strong&gt; - Related entities are grouped together logically rather than by physical device&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can assign entities to sub-devices using the new &lt;code dir=&quot;auto&quot;&gt;device_id&lt;/code&gt; configuration option. First, define your devices
in the &lt;code dir=&quot;auto&quot;&gt;devices&lt;/code&gt; section under &lt;code dir=&quot;auto&quot;&gt;esphome:&lt;/code&gt;, then reference them in individual entities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example configuration:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;esphome&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;multi_room_controller&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Define areas (optional)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;areas&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;living_room_area&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Living Room&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;bedroom_area&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Bedroom&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Define devices&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;devices&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;living_room_device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Living Room Sensors&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;area_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;living_room_area&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;bedroom_device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Bedroom Sensors&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;area_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;bedroom_area&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Assign sensors to different devices&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sensor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;dht&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pin&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;GPIO4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;temperature&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Living Room Temperature&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;device_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;living_room_device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;humidity&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Living Room Humidity&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;device_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;living_room_device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;dht&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pin&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;GPIO5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;temperature&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Bedroom Temperature&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;device_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;bedroom_device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;humidity&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Bedroom Humidity&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;device_id&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;bedroom_device&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In this example, Home Assistant will see two separate sensor devices (one for living room, one for bedroom)
even though they’re controlled by a single ESPHome device.&lt;/p&gt;
&lt;p&gt;This feature enhances the logical organization of your smart home while maintaining the efficiency of
centralized ESPHome device management.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;new-hardware-support-highlights&quot;&gt;New Hardware Support Highlights&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This release brings support for exciting new hardware platforms and components:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Wireless Communication:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SX126x &amp;#x26; SX127x LoRa modules&lt;/strong&gt; - Long-range, low-power communication for remote sensors and IoT applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESP32 Hosted WiFi&lt;/strong&gt; - Use an ESP32 as a WiFi adapter for other microcontrollers, expanding connectivity options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New Sensors &amp;#x26; Measurement:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OPT3001&lt;/strong&gt; - High-precision ambient light sensor with excellent low-light sensitivity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LPS22&lt;/strong&gt; - Accurate barometric pressure sensor for weather monitoring and altitude measurement&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GL-R01&lt;/strong&gt; - Time-of-flight distance sensor for precise proximity and ranging applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Xiaomi XMWSDJ04MMC&lt;/strong&gt; - Support for popular Xiaomi Bluetooth temperature/humidity sensors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Expanded Platform Support:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LN882X SoC Family&lt;/strong&gt; - New LibreTiny support extends ESPHome to additional low-cost WiFi microcontrollers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PI4IOE5V6408&lt;/strong&gt; - New I2C GPIO expander for applications requiring additional digital I/O pins&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DS2484&lt;/strong&gt; - Advanced 1-Wire bus master for improved reliability in complex 1-Wire networks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Camera Framework&lt;/strong&gt; - New base camera class enables support for alternative camera implementations&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;memory-and-performance-optimizations&quot;&gt;Memory and Performance Optimizations&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;ESPHome 2025.7.0 includes extensive memory and performance optimizations, particularly beneficial for
resource-constrained devices:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Memory Usage Reductions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Component memory reduced&lt;/strong&gt; (8 bytes per component) - Significant savings for devices with many components&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensor entities optimized&lt;/strong&gt; - Reduced memory footprint for devices with numerous sensors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API and networking optimizations&lt;/strong&gt; - Lower RAM usage for WiFi and API communication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Color constant storage optimization&lt;/strong&gt; - More efficient handling of color data in displays and lighting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Performance Improvements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Faster loop processing&lt;/strong&gt; - Components can now disable their loop() method when not needed, reducing CPU overhead&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimized API communication&lt;/strong&gt; - Improved batching and reduced redundant operations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced logging performance&lt;/strong&gt; - More efficient message processing and reduced CPU impact&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bluetooth proxy optimizations&lt;/strong&gt; - Better performance for ESP32 devices acting as Bluetooth proxies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Code Quality Enhancements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;C++20 support&lt;/strong&gt; - Modern C++ features for better performance and developer experience&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved interrupt handling&lt;/strong&gt; - More reliable GPIO interrupt processing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced scheduler&lt;/strong&gt; - Better task management with comprehensive test coverage&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;jinja2-template-expressions-in-substitutions&quot;&gt;Jinja2 Template Expressions in Substitutions&lt;/h2&gt;&lt;/div&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Feature:&lt;/strong&gt; ESPHome now supports Jinja2 template expressions within substitutions,
enabling more advanced and dynamic value generation.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;ESPHome 2025.7.0 introduces support for Jinja2 template expressions within the existing substitutions system.
This enhancement extends the current &lt;code dir=&quot;auto&quot;&gt;${ }&lt;/code&gt; substitution syntax to support Jinja2 expressions, allowing for
more sophisticated value calculations and transformations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enhanced substitution capabilities:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mathematical operations&lt;/strong&gt; - Perform calculations using substitution variables&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conditional expressions&lt;/strong&gt; - Use ternary operators and conditional logic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String formatting&lt;/strong&gt; - Advanced string manipulation and formatting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type conversions&lt;/strong&gt; - Convert between strings, numbers, and other types&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filter operations&lt;/strong&gt; - Apply Jinja2 filters for data transformation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example usage:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;substitutions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;device_name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;living_room_sensors&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;num_sensors&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;base_pin&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;offset_voltage&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3.3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;enable_debugging&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;sensor_config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;update_interval&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;60s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;accuracy_decimals&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sensor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;adc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pin&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;GPIO${base_pin}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;${device_name} voltage&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;update_interval&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${sensor_config.update_interval}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;accuracy_decimals&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${sensor_config.accuracy_decimals}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;filters&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# Convert ADC reading to actual voltage&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;multiply&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${offset_voltage / 4095}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;adc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pin&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;GPIO${base_pin + 1}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;${device_name} sensor ${num_sensors &gt; 1 and &apos;secondary&apos; or &apos;primary&apos;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;accuracy_decimals&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${1 if num_sensors &amp;#x3C;= 2 else 2}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;update_interval&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${sensor_config.update_interval}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;binary_sensor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;platform&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;gpio&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pin&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;GPIO${base_pin + 2}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;${device_name} status ${enable_debugging and &apos;(debug)&apos; or &apos;&apos;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Works within existing substitutions&lt;/strong&gt; - Uses the familiar &lt;code dir=&quot;auto&quot;&gt;${ }&lt;/code&gt; syntax you already know&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access to substitution variables&lt;/strong&gt; - All defined substitutions are available as Jinja variables&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dictionary and list access&lt;/strong&gt; - Use dot notation (&lt;code dir=&quot;auto&quot;&gt;device.name&lt;/code&gt;  ) or indexing (&lt;code dir=&quot;auto&quot;&gt;pins[0]&lt;/code&gt;  )&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mathematical functions&lt;/strong&gt; - Access to Python’s math library (&lt;code dir=&quot;auto&quot;&gt;math.sqrt&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;math.pi&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conditional logic&lt;/strong&gt; - Ternary operators and boolean expressions for dynamic values&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;More powerful substitutions&lt;/strong&gt; - Calculate complex values instead of just simple replacements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced duplication&lt;/strong&gt; - Generate values programmatically based on other substitutions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better maintainability&lt;/strong&gt; - Change base values and have dependent values update automatically&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced flexibility&lt;/strong&gt; - Support for conditional values and complex transformations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This feature builds upon ESPHome’s existing substitutions system, making it more powerful while maintaining
backward compatibility. It’s particularly useful for responsive designs, calculated pin assignments,
and configurations that need to adapt based on device capabilities or user preferences.&lt;/p&gt;
&lt;p&gt;For complete documentation and more examples, see the &lt;a href=&quot;https://esphome.io/components/substitutions/&quot;&gt;Substitutions&lt;/a&gt; guide.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;arduinojson-library-7-x&quot;&gt;ArduinoJson Library 7.x&lt;/h2&gt;&lt;/div&gt;
&lt;div dir=&quot;auto&quot;&gt;
&lt;p dir=&quot;auto&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;WARNING&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Breaking Change:&lt;/strong&gt; The ArduinoJson library has been upgraded from version 6.x to 7.2.0, introducing
breaking changes that may affect custom components and external integrations.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;ESPHome 2025.7.0 upgrades the ArduinoJson library to version 7.2.0, bringing performance improvements and
reduced memory usage. Most users will not be affected as all standard ESPHome components have been updated.
However, if you have external components, or lambdas that directly use ArduinoJson, you may need
to update your code.&lt;/p&gt;
&lt;p&gt;For detailed migration information, see the &lt;a href=&quot;https://arduinojson.org/v7/how-to/upgrade-from-v6/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;ArduinoJson migration guide&lt;/a&gt;.&lt;/p&gt;

&lt;div&gt;&lt;h2 id=&quot;release-2025-7-1---july-17&quot;&gt;Release 2025.7.1 - July 17&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[lvgl]: fix missing await keyword in meter tick_style width processing &lt;a href=&quot;https://github.com/esphome/esphome/pull/9538&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9538&lt;/a&gt; by &lt;a href=&quot;https://github.com/theshut&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@theshut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix compilation error when using string lambdas with homeassistant services &lt;a href=&quot;https://github.com/esphome/esphome/pull/9543&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9543&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix format string warnings in Web Server OTA component &lt;a href=&quot;https://github.com/esphome/esphome/pull/9569&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9569&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add helpful error message when ESP32+Arduino runs out of flash space &lt;a href=&quot;https://github.com/esphome/esphome/pull/9580&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9580&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Allow disabling OTA for web_server while keeping it enabled for captive_portal &lt;a href=&quot;https://github.com/esphome/esphome/pull/9583&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9583&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32] Add missing include for helpers &lt;a href=&quot;https://github.com/esphome/esphome/pull/9579&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9579&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix lwIP thread safety assertion failures on ESP32 &lt;a href=&quot;https://github.com/esphome/esphome/pull/9570&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9570&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-7-2---july-19&quot;&gt;Release 2025.7.2 - July 19&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Fix template event web_server crash &lt;a href=&quot;https://github.com/esphome/esphome/pull/9618&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9618&lt;/a&gt; by &lt;a href=&quot;https://github.com/AzonInc&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@AzonInc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fix compilation error with char* lambdas in HomeAssistant services &lt;a href=&quot;https://github.com/esphome/esphome/pull/9638&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9638&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[wireguard] Fix boot loop when CONFIG_LWIP_TCPIP_CORE_LOCKING is enabled &lt;a href=&quot;https://github.com/esphome/esphome/pull/9637&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9637&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[scheduler] Fix cancellation of timers with empty string names &lt;a href=&quot;https://github.com/esphome/esphome/pull/9641&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9641&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[logger] fix on_message &lt;a href=&quot;https://github.com/esphome/esphome/pull/9642&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9642&lt;/a&gt; by &lt;a href=&quot;https://github.com/ssieb&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@ssieb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;esp32_camera: deprecate i2c_pins; throw error if combined with i2c: block &lt;a href=&quot;https://github.com/esphome/esphome/pull/9615&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9615&lt;/a&gt; by &lt;a href=&quot;https://github.com/RubenKelevra&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@RubenKelevra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[scheduler] Fix DelayAction cancellation in restart mode scripts &lt;a href=&quot;https://github.com/esphome/esphome/pull/9646&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9646&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Fix meter rotation &lt;a href=&quot;https://github.com/esphome/esphome/pull/9605&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9605&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[libretiny] Remove unsupported lock-free queue and event pool implementations &lt;a href=&quot;https://github.com/esphome/esphome/pull/9653&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9653&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[lvgl] Prevent keyerror on min/max value widgets with no default &lt;a href=&quot;https://github.com/esphome/esphome/pull/9660&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9660&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix AsyncTCP version mismatch between platformio.ini and async_tcp component &lt;a href=&quot;https://github.com/esphome/esphome/pull/9676&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9676&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[speaker] Media player’s pipeline properly returns playing state near end of file &lt;a href=&quot;https://github.com/esphome/esphome/pull/9668&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9668&lt;/a&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[voice_assistant] Use media player callbacks to track TTS response status &lt;a href=&quot;https://github.com/esphome/esphome/pull/9670&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9670&lt;/a&gt; by &lt;a href=&quot;https://github.com/kahrendt&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kahrendt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[gpio] Disable interrupt mode by default for LibreTiny platforms &lt;a href=&quot;https://github.com/esphome/esphome/pull/9687&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9687&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-7-3---july-23&quot;&gt;Release 2025.7.3 - July 23&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[gpio] Auto-disable interrupts for shared GPIO pins in binary sensors &lt;a href=&quot;https://github.com/esphome/esphome/pull/9701&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9701&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fix format string error in ota_web_server.cpp &lt;a href=&quot;https://github.com/esphome/esphome/pull/9711&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9711&lt;/a&gt; by &lt;a href=&quot;https://github.com/tmpeh&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@tmpeh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[sdl][mipi_spi] Respect clipping when drawing &lt;a href=&quot;https://github.com/esphome/esphome/pull/9722&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9722&lt;/a&gt; by &lt;a href=&quot;https://github.com/JonasB2497&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@JonasB2497&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[esp32_touch] Fix setup mode in v1 driver &lt;a href=&quot;https://github.com/esphome/esphome/pull/9725&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9725&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[tuya] Update use of fan_schema &lt;a href=&quot;https://github.com/esphome/esphome/pull/9762&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9762&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[config_validation] Add support for suggesting alternate component/platform &lt;a href=&quot;https://github.com/esphome/esphome/pull/9757&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9757&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[core] Process pending loop enables during setup blocking phase &lt;a href=&quot;https://github.com/esphome/esphome/pull/9787&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9787&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[fastled_clockless, fastled_spi] Add suggested alternate when using IDF &lt;a href=&quot;https://github.com/esphome/esphome/pull/9784&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9784&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[neopixelbus] Add suggested alternate when using IDF &lt;a href=&quot;https://github.com/esphome/esphome/pull/9783&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9783&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[bme680_bsec] Add suggested alternate when using IDF &lt;a href=&quot;https://github.com/esphome/esphome/pull/9785&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9785&lt;/a&gt; by &lt;a href=&quot;https://github.com/kbx81&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@kbx81&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-7-4---july-28&quot;&gt;Release 2025.7.4 - July 28&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[remote_receiver] Fix idle validation &lt;a href=&quot;https://github.com/esphome/esphome/pull/9819&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9819&lt;/a&gt; by &lt;a href=&quot;https://github.com/swoboda1337&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@swoboda1337&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[gt911] i2c fixes &lt;a href=&quot;https://github.com/esphome/esphome/pull/9822&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9822&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;fix: non-optional x/y target calculation for ld2450 &lt;a href=&quot;https://github.com/esphome/esphome/pull/9849&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9849&lt;/a&gt; by &lt;a href=&quot;https://github.com/Hofferic&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@Hofferic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[logger] Don’t allow &lt;code dir=&quot;auto&quot;&gt;logger.log&lt;/code&gt; actions without configuring the &lt;code dir=&quot;auto&quot;&gt;logger&lt;/code&gt; &lt;a href=&quot;https://github.com/esphome/esphome/pull/9821&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9821&lt;/a&gt; by &lt;a href=&quot;https://github.com/jesserockz&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@jesserockz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add seed flag when running setup with uv present &lt;a href=&quot;https://github.com/esphome/esphome/pull/9932&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9932&lt;/a&gt; by &lt;a href=&quot;https://github.com/cryptk&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@cryptk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fail with old lerp &lt;a href=&quot;https://github.com/esphome/esphome/pull/9914&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9914&lt;/a&gt; by &lt;a href=&quot;https://github.com/HeMan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@HeMan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;release-2025-7-5---august-5&quot;&gt;Release 2025.7.5 - August 5&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[lvgl] Bugfix for tileview &lt;a href=&quot;https://github.com/esphome/esphome/pull/9938&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#9938&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[api] Fix OTA progress updates not being sent when main loop is blocked &lt;a href=&quot;https://github.com/esphome/esphome/pull/10049&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10049&lt;/a&gt; by &lt;a href=&quot;https://github.com/bdraco&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@bdraco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[font] Catch file load exception &lt;a href=&quot;https://github.com/esphome/esphome/pull/10058&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10058&lt;/a&gt; by &lt;a href=&quot;https://github.com/clydebarrow&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@clydebarrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[i2s_audio] Use high-pass filter for dc offset correction &lt;a href=&quot;https://github.com/esphome/esphome/pull/10005&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;esphome#10005&lt;/a&gt; by &lt;a href=&quot;https://github.com/doobry&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;@doobry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;&lt;h2 id=&quot;full-list-of-changes&quot;&gt;Full List of Changes&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For the complete list of every merged pull request in this release, see the
&lt;a href=&quot;https://esphome.io/changelog/2025.7.0/&quot;&gt;full 2025.7.0 changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Releases</category></item></channel></rss>