ESPHome 2026.11.0: Lighter builds and tougher updates

NOTE
This is a beta release. Details on this page may change before the stable release is published.
ESPHome publishes a release like this each month, so you can see what’s new, what’s fixed and anything to be aware of before you update.
Short on time? Here’s the quick version
Section titled “Short on time? Here’s the quick version”This is the short, plain-language version for anyone short on time or still finding their way around ESPHome. The full technical post continues below.
- Sub-devices: every entry under
esphome: devices:now needs arelation:field –viafor a separate physical device reached through this node,childfor a logical part of this node. - HTTP requests in scripts:
http_request.get,.postand.sendno longer pause the script, so addmode: queuedormode: parallelwhere repeated runs must not be skipped. - ESP-IDF minimum version: if your ESP32 build pins the ESP-IDF framework to a 5.0 version, move it to 5.1 or newer (or remove the pin).
New features: ESPHome uses less memory on every supported chip, especially the ESP8266, and the way automations are built now produces smaller, faster code.
Also in this release: over thirty new components plus many smaller fixes and improvements.
If you’re running a typical config, there’s nothing else you need to check before updating – aside from the items above.
For the full release overview and technical detail – including anything that affects custom lambdas, external components or non-standard setups – keep reading below.
Components added in this release
Section titled “Components added in this release”Release overview
Section titled “Release overview”ESPHome 2026.11.0 is a framework release. Another large sweep of entity names, filter tables and lookup strings leaves RAM on ESP8266 and lives in flash on every platform. Scheduler timers lose their string names, cover, fan, valve and lock traits pack into one byte, and several components switch from heap vectors to fixed buffers. The generated code for automations now compiles to plain C++ control flow, saving about 1.6 KB of RAM on ESP8266 and ESP32 IDF for a modest configuration.
Codegen gets a wave of shared helpers, so new components and migrations need less boilerplate: new Apply entity
classes for hub-forwarding buttons, switches, numbers and selects, SUB_* and PUBLISH_STATE macros for child
entities, and byte, I2C, UART, BLE and modbus helpers that roll out across dozens of drivers. The minimum ESP-IDF rises
to 5.1, LibreTiny goes to 1.14.0 with BDK 3.0.78 on Beken chips, and esp_hosted moves to 3.0.10. Native ESPHome OTA
now falls back to UDP when the link is lossy, so uploads finish on Wi-Fi that would stall the previous TCP data phase.
wifi: ap: with web_server: now serves the interface as a captive portal, the DHCP lease is cached across reboots
and Wi-Fi Easy Connect lands on ESP32.
OpenThread on ESP32 gains an experimental border router that bridges Thread to Wi-Fi. nRF52 picks up a crash coredump, a native toolchain entry, a dongle board, BLE OTA through the Adafruit bootloader and SMP-over-UDP. HTTP requests from automations no longer block the main loop, the logger buffers early boot lines for later replay over the API, and the web server stops exposing internal entities over REST. This release also adds over thirty new components, including Daikin Madoka BLE, USB audio and keyboard, an RTSP server, a VNC client, BLE MIDI, HDMI-CEC and the ESP32 ULP coprocessor, twelve new climate IR platforms, and many new sensors, radars and expanders. A short codebase-correctness sweep closes memory, event-decoding and REST-visibility bugs.
Upgrade checklist
Section titled “Upgrade checklist”- If you use
esphome: devices:for sub-devices, addrelation: via(separate physical device) orrelation: child(logical part of this node) to every entry. - If you use OpenThread on ESP32, make sure your build uses ESP-IDF 5.5.5 or newer; remove any pinned
esp32.framework.versionolder than that. - If you target the ESP32 with ESP-IDF, remove any pin to ESP-IDF 5.0.x; the minimum is now 5.1.
- If you use
esp32_hosted, require ESP-IDF 5.5 or newer, addd1_pinon a 1-bit SDIO setup, and removeactive_high: false(use the default;active_high: trueworks with a deprecation warning). - If you use OpenThread on ESP32 without anything else that needs IPv4, add
network: enable_ipv4: trueto keep IPv4 on. - If you use
http_requestactions inside a script, setmode: queuedormode: parallelwhere repeated runs must not be skipped; actions no longer block the script. - If you have
clk_mode:on theethernet:component, move it to theclk:block withmode:andpin:. - If you have
provider:ondlms_meter:, drop it; forprovider: netznoeadd the twocustom_patternsfrom the release notes. - If you have DLMS meter sensors using predefined keys such as
voltage_l1ortimestamp, replace each with its own entity usingobis_code. - If you have
update_on_release:on an LVGL number, replace it withtrigger: on_release. - If you have
dump_device_info:onnextion:, delete it; device info is always logged. - If you have
platform: qspi_amoled, change it toplatform: qspi_dbi. - If you use
delay,wait_untilorscript.waitinside emonTxon_json/on_data, MQTTon_json_message, or Haieron_status_message, copy the values you need into globals first and defer from a separate script. - If you drive internal entities through the web server REST API by URL, add
include_internal: trueunderweb_server:. - If you have NEC
remote_transmitter.transmit_necactions withcommand_repeatsabove 10 or equal to 0, change them to a value between 1 and 10. - If you have
on_neclambdas comparingx.command_repeats, update them - the value is always 1 now and the check no longer works. - If you have Panasonic IR configs captured from a 56-bit remote, run the dumper again and update
address_2andcommand. - If you have MagiQuest
on_magiquestlambdas comparingx.wand_idorx.magnitude, re-dump and use the new values. - If you have a
canbus.sendwith a constant payload longer than 8 bytes, shorten it to at most 8 bytes. - If you use
esp32_rmt_led_strip,remote_transmitterorremote_receiverwith a customrmt_symbolsor multiple components, re-run validation; conflicts and invalid sizes now fail at config time. - If you use
color_bwre-paper panels (WeAct 3C, Waveshare B, Waveshare BWR, Inkplate 2), expect color mapping to change; the test card and lambdas on WeAct 3C or Waveshare 7.5” V2 BWR also change because they now reportDISPLAY_TYPE_COLOR. - If you use the CB3S board (LN-CB3S V1.0) with the
D12alias, update your pin toD13orPA11;D12now drives PA10.
ESP8266 RAM diet and framework-wide flash tables
Section titled “ESP8266 RAM diet and framework-wide flash tables”ESP8266 keeps on a strict RAM budget, and this release shaves another large chunk off it by moving constant tables and
strings into flash. Entity names, device classes, icons, log tags, filter tables, effect lists, enum option lookups
and action payloads now live in flash on every build, and are only copied into RAM when a component actually uses them.
Led by @bdraco, close to a hundred PRs touch this area, across core helpers like
ConstVector, PROGMEM_STRING_TABLE, cg.extern_progmem_array and ESPHOME_LOG_TAG, and the component rollouts
that use them.
- Entity names and icons in flash -
name:,icon:and device class strings are read straight from flash on ESP8266, and the native API sends them straight from flash too (#20423, #21106, #21111). - Filter, effect and lookup tables moved to flash - sensor filter tables, light effect lists, climate presets, alarm codes, switch and button payloads, remote IR codes, radar settings and dozens of per-driver lookup tables now sit in flash and are shared across instances (#20071, #20074, #20076, #20078, #20080, #20082, #20083, #20204, #20222, #20394).
- Web server strings off RAM - the remaining ESP8266 web server strings, resource tables and entity domain names move to flash (#20300, #21113, #21115).
- Manual IP settings in flash - manual Wi-Fi and Ethernet IP settings are stored in flash on ESP8266 too (#21708, #21712).
- Shared switch lookup tables - ESP8266 switch lookup tables leave RAM (#20398).
Lower RAM for every component instance
Section titled “Lower RAM for every component instance”RAM savings continue beyond ESP8266. Scheduler timers no longer carry a per-component name string, several trait flag bytes are packed, and the big automation code generation rewrite below shrinks the framework object graph. Numbers below are from the PR measurements against the current release line.
- Numeric scheduler IDs - scheduler timers now match components by small integer IDs rather than string literals, so lookups become integer compares. The change rolls through core, climate, select, Tuya, Dallas, Modbus, speaker, Zigbee, voice_assistant and many sensor drivers (#20361, #20365, #20367, #20368, #20374, #20375, #20376, #20377, #20378, #20380, #20381).
- Trait flag packing - Cover, fan, valve and lock traits pack their boolean flags into single bytes, and
esp32_rmt_led_stripreshuffles members to fit base class padding (#21339, #21340, #21343, #21344, #21838). - No duplicated storage - MQTT rebuilds subscription topics on demand instead of storing them, and components such as
bedjet,nfc,thermopro_ble,graph,mqtt_subscribe,key_collector,display_menu_base,bme680_bsecandtuyastop copying strings they only read (#20762, #21204, #21205, #21206, #21207, #21208, #21209, #21210, #21211, #21212). - Fixed-size buffers replace heap allocations - radar components, GPS listeners, speaker pipelines, usb_uart buffers and the Weikai UART driver use fixed-size storage and ring buffers instead of growing heap vectors (#20379, #21201, #21203, #21347, #21476, #21478).
Automations compile to C++ control flow
Section titled “Automations compile to C++ control flow”Led by @clydebarrow, the code generator for automations has been rebuilt. if, choose, while, repeat and runs of simple actions no longer need an action object per step; they compile straight into the generated function as C++ control flow. On a test config with eight automations of three actions each, the stack of changes saves 1632 bytes of RAM and 1216 bytes of flash on ESP8266, and 1632 bytes of RAM and 1628 bytes of flash on ESP32 IDF. Lambda and script.execute chains no longer grow the stack along the way.
- Adjacent actions merge - runs of
register_apply_actionandlambda:actions become one generated function and one object (#21978). - Inline callback automations run directly - a trigger whose actions are all inline calls the generated function straight from the callback, with no automation object (#21979).
- Control flow turns into C++ -
if,choose,whileandrepeatwith inline bodies becomeif,switch,whileandforin the generated function. The change also fixes a bug where a false condition inside a nestedwhilecould stop its outerparallelscript (#21980).
Codegen helpers for component authors
Section titled “Codegen helpers for component authors”A second large framework effort, driven mostly by @bdraco, standardises how components are described in Python. Nine helpers do work that was previously hand-written per component: new_i2c_component, new_uart_component, new_spi_component, options() for enum keys, cg.add_pin, cg.add_variable, cg.add_optional, assign_bits and register_parented. The SUB_* macros declare child entities with one line and the PUBLISH_STATE macro publishes them with one more, so hub drivers no longer repeat if (pointer) pointer->publish_state(value) for each sub-entity. A new Apply entity family lets a hub forwarding button, switch, number or select ship as a single Python line and no C++ class at all. Component authors can see the new helpers in AGENTS.md; these are migration tracks that touch dozens of components and shrink the codebase without changing behaviour.
- Apply entities - new
ApplyButton,ApplySwitch,ApplyNumber,ApplySelect,ApplyBytesandApplyOutputclasses, plus their roll-out across LD2410, LD2420, LD2450, DFRobot SEN0395/SEN0609, Airton, Haier, Tuya, Micronova and the core safety switches (#20935, #20937, #20964, #20965, #20966, #20967, #21146, #21147, #21148, #21158, #21162, #21163, #21251, #21252, #21253, #21262, #21263, #21519, #21659, #21662, #21673, #21675, #21677). - Shared I2C, UART and BLE helpers -
update_register,write_registers,check_chip_id,read_available,discard_available,LineReader,FrameReader,encode_uint16/24,put_be/put_le,sum_bytes,xor_bytes,sum16_bytes,sign_extend, the shared BCD and color helpers andnew_ble_component/new_modbus_componentmigrate 20+ I2C drivers, the whole UART component set, BCD and byte-order code in many RTC and sensor drivers (#20507, #20855, #20861, #20907, #20909, #20911, #20919, #20920, #20922, #20934, #20938, #20939, #20941, #20943, #20945, #20946, #20948, #20956, #21026, #21080, #21082, #21083, #21084, #22212). - Follow entities from codegen - the
copy,switch,numberandtextfollow-entity publishers are now built from codegen expressions instead of hand-formatted strings (#22103, #21610, #21612). - SUB_ and PUBLISH_STATE rollout* - child entities across ~150 components declare their pointers with
SUB_*macros and publish throughPUBLISH_STATEin a single call (#21726, #21770 through #21777, #21808 through #21810, #21848 through #21852).
ESP-IDF 5.1 floor and library refresh
Section titled “ESP-IDF 5.1 floor and library refresh”The minimum ESP-IDF rises to 5.1 and three major vendor libraries are refreshed, so builds stop configuring with deprecated symbols and devices built on them stop hitting the known bugs. LibreTiny now defaults to 1.14.0 with Beken BDK 3.0.78 on BK7231N and BK7231T, which fixes WPA3 support on those chips, stops the BK7231T captive portal from losing saved credentials and fixes a watchdog trip during web OTA (#21531). esp_hosted on the ESP32-P4 and Tab5 jumps to 3.0.10, which repairs 1-bit SDIO and no longer erases the co-processor partition at OTA begin (#21394). esp-zigbee-sdk rises to 2.0.5 and esp-audio-libs to 4.1.0 (#20998, #20754). The GCC 12 toolchain that ships with ESP-IDF 5.1 also lets ESPHome drop its 5.0-specific workarounds, so basename debug flags apply everywhere and CONFIG_SW_COEXIST_ENABLE is written under its current name (#21398). espressif/esp-adf-libs and espressif/esp-hosted binaries are now downloaded and cached rather than carried in the repository (#20065).
OTA uploads that finish on bad Wi-Fi
Section titled “OTA uploads that finish on bad Wi-Fi”Led by @bdraco, the native ESPHome OTA protocol now falls back to UDP when the TCP handshake shows the link is lossy. The full TCP handshake still runs first, and the data phase moves to UDP only when it is worth it; everything stays encrypted when Noise is configured. On an ESP32 next to the laptop, a clean upload takes 13 to 16 seconds on UDP against 36 to 70 seconds on TCP, and an upload with 65% loss added finishes in just over three minutes where TCP fails every time (#20498). The companion client adds a few patience changes to match: handshake timeouts rise from 20 to 60 seconds, up to five attempts for a first connection and nine once the device is reached, so a slow Wi-Fi recovery no longer gives up early. --prompt-ota-key and old_key options let an upload retry with a fresh or previous OTA key when the device has already moved on (#19397, #19398).
Networking and provisioning without the cloud
Section titled “Networking and provisioning without the cloud”A set of connectivity features make setting up a device easier when there is no router or internet involved. Led by @bdraco, configuring wifi: ap: together with web_server: now serves the embedded web interface as a captive portal, with a DNS server that redirects every name to the AP address, so a phone opens the page automatically like a hotel sign-in (#18517). The WISP feature introduced last cycle adds ap_mode: ALWAYS_ON, a captive portal option and ESP32 Arduino support (#20077, #21410), and the WISP AP can be bridged to Ethernet or to a cellular modem link (#7147, #21584).
- Wi-Fi Easy Connect (DPP) - QR-code provisioning for ESP32 devices (#17934).
- DHCP lease cache - keeps the previous lease across reboots to reconnect faster (#17767).
- IPv4 and IPv6 on demand -
network: enable_ipv4andenable_ipv6default from what components actually need; an OpenThread-only ESP32 builds without the IPv4 stack now (#14526). - IPv6 for Zephyr and UDP - UDP gets IPv6 unicast and multicast across platforms, and nRF52 gains IPv6 support (#17838, #20590).
OpenThread border router on ESP32
Section titled “OpenThread border router on ESP32”Led by @pputerla, the openthread component gains an ESP32 border router mode. An ESP32-C5 or C6 bridges its native 802.15.4 radio to Wi-Fi, and the other Wi-Fi ESP32 variants bridge an external radio co-processor over UART. Thread starts at boot, border routing starts once Wi-Fi has an address, and the SDK is driven from a single OpenThread task under one lock so clean reboots work. OpenThread on ESP32 now needs ESP-IDF 5.5.5 or newer, which has been the default for a few releases (#18104). The feature is marked experimental: the native radio ran for two weeks without a restart in testing, while the external RCP mode hung occasionally during a three-week soak.
nRF52 catches up
Section titled “nRF52 catches up”nRF52 devices gain several platform-level features. Led by @tomaszduda23, the new zephyr_coredump component stores a crash dump in flash and prints it hex-encoded once a log reader connects; Zephyr’s tooling then turns the log into a GDB backtrace. @swoboda1337 moves sdk-nrf into the native toolchain list, so nRF52 builds no longer write an unused platformio.ini, esphome idedata works, memory analysis has one less code path and platformio_options behave like on ESP-IDF (#21704). The nRF52840 dongle is a supported board (#19009), nRF52 can now be flashed and updated over BLE with the Adafruit bootloader in addition to MCUboot (#20481), zephyr_mcumgr adds an SMP-over-UDP OTA transport (#17245), the logger adds CDC UART through usb_cdc_acm on nRF52 (#11634) and debug logs per-thread CPU usage (#13938). The esp32_ble_server gets secure connections with numeric comparison (#17562).
Developer infrastructure
Section titled “Developer infrastructure”Several changes make ESPHome itself easier to build and debug. CodSpeed benchmarks ride along with the Python code, so component import time, entity validation, image and runtime image decoding, and sensor platform setup are all tracked over time (#20603, #20637, #20648, #20649, #20763). The CI’s hardware-test skill picks up new flows that cover SEN0395, LD2412, LD2450, LD24xx variants, Xiaomi BLE, MQTT TLS and WebSocket, GPIO hold, BLE light sleep, HTTP-request OTA, manual IP, web OTA, LD2450 zones and more (#21160, #21229, #21264, #21356, #21414, #21549, #21636, #21724). Each build path ESPHome ships is now compiled on a Windows runner and an ESP8266 native config also builds on Windows (#20467, #21791). esphome upload works without a configuration file, so a prebuilt image can be flashed from the CLI (#21738). clang-tidy 23 is clean across the tree after a cleanup pass by @swoboda1337 (#21301, #21334, #21335, #21336, #21338).
Non-blocking HTTP requests and boot log replay
Section titled “Non-blocking HTTP requests and boot log replay”Two automation-side features let devices do more work in the background. @clydebarrow reworked http_request.get, .post and .send into asynchronous actions driven by the component’s loop(). On an ESP32-S3, the main loop stall for a plain HTTPS GET drops from 2.4 to 3.6 seconds to about 0.3 seconds, and for a 70 KB LAN download from 3.6 seconds to tens of milliseconds. Up to four extra requests queue, so overlapping triggers no longer run back to back. A script containing one of these actions is still running while the request is in flight, so a mode: single script that used to fit inside execute() now has to use mode: queued or mode: parallel when it needs to overlap (#21486). A per-request timeout: option lands in the same area (#20821).
The logger also gains an optional boot_log_buffer_size: and a matching logger.replay_boot_logs: action. Lines captured from the moment the logger starts are replayed over the native API when the first client connects, so a warning that fired before Wi-Fi came up is still visible later (#17666). The buffer is a compile-time member, nothing allocates on the heap, and the option compiles out entirely when unset. boot_log_level: and per-tag boot_logs: tune what is kept, and dropped lines are counted so the summary says how much was lost.
New components: sensors and GPIO expanders
Section titled “New components: sensors and GPIO expanders”Many new sensor and expander components ship this release. All are listed with short notes; configuration lives in their own documentation.
- Aranet BLE sensor by @patrickod - passive Bluetooth LE advertisement reader for Aranet4, Aranet2, Aranet Radiation, Aranet Radon Plus and Aranet Radon One monitors.
- APDS9930 by @iyesin - Broadcom ambient-light and proximity I2C sensor.
- APC1 by @ademuri - ScioSense APC1 air-quality sensor on UART.
- AS734x spectral hub by @latonita - AS7341, AS7343 and TCS3448 spectral sensors in one driver, with counts, illuminance, PAR, PPFD, colour temperature and RGB.
- BH1745 by @latonita - ROHM colour sensor with illuminance and colour-temperature output and an LED driver output.
- BQ25186 by @Rapsssito - TI 1-cell linear battery charger with status sensors, buttons, a PG/GPO switch and a watchdog option.
- BQ27220 fuel gauge by @rggammon - TI single-cell Li-Ion fuel gauge with eight optional sensors.
- BQ76972 BMS monitor by @limpkin - TI monitor for cell voltages, pack voltage and thermistor temperatures.
- CW2017 fuel gauge by @exciton - CellWise fuel gauge; a
battery_profiledescribes the cell. - DFRobot SEN0465 by @tzabbi - DFRobot SEN0465 to SEN0476 electrochemical gas probes with I2C and UART.
- DFRobot SEN0609 radar by @remcom - C4001-based 25 m and 12 m mmWave radars (SEN0609 and SEN0610) with presence and speed-and-distance modes.
- Delta AC wallbox by @epicRE - BLE driver reading model, state, power and energy and starting or stopping charging sessions; max charging current configurable at runtime.
- DS3231 RTC by @linkedupbits and @miloit - Maxim real-time clock with time platform, alarms, 32 kHz/square-wave outputs and temperature sensor.
- FUSB302B PD sink by @remcom - full USB Power Delivery sink with state, contract and automations.
- HUSB238 PD controller by @latonita - Hynetek USB PD sink controller hub with binary sensors for attach and CC direction.
- ICM-20689 by @lboue - TDK InvenSense 6-axis accelerometer and gyroscope over SPI, with on-chip temperature.
- LD2410S radar by @NovakIrs - HI-LINK LD2410S presence radar with distance sensor and firmware version.
- LD2460 radar by @jesusvallejo - Hi-Link multi-target tracking 24 GHz radar.
- LD6004 radar by @wolph - Hi-Link 60 GHz presence radar on the new shared
ld600xbase. - LIS2DW12 by @latonita - ST 3-axis accelerometer with tap, double-tap, free-fall, activity and 6D orientation events.
- LIS3DH by @Zebble - ST 3-axis accelerometer built on the shared
motionplatform. - MAX17048 fuel gauge by @B48D81EFCC and the shared
max170xxhelper by @ryansch - Analog Devices Li-ion fuel gauge. - MAX31888 by @JiriPrchal - Analog Devices 1-Wire temperature sensor.
- MICS-5524 by @nliaudat - DFRobot MEMS multi-gas module that converts an existing ADC sampler into gas concentrations.
- MT6701 by @slimcdk - MagnTek magnetic encoder over I2C or SPI.
- NS2009 by @tchilov - Nsiway resistive touchscreen controller.
- PCA9505 expander by @ajfriesen - NXP PCA9505 and PCA9506 40-channel GPIO expander with optional interrupt pin.
- Renogy inverter BLE by @emilioaray-dev - reads a Renogy inverter with built-in Bluetooth over
ble_clientand publishes AC and battery values. - RX8111CE RTC by @techdregs - Epson I2C real-time clock as a
timeplatform, with alarm and wake-up timer, FOUT and EVIN events, binary sensors and a backup-power status text sensor. - ST25R3916 NFC reader by @JohnMcLear - ISO 14443A tag reader over SPI, firing the shared
on_tagandon_tag_removedautomations. - TCA8418 keypad by @Zebble - TI I2C keypad scanner with matrix and direct inputs.
- TMC2209 stepper driver by @remcom - Trinamic UART stepper driver with current and chopper tuning actions and stall detection.
- TMP102 by @techdregs - TI digital temperature sensor with thermostat thresholds, alert pin and diagnostics text sensor.
- VEML6040 by @aalaei - Vishay RGBW colour sensor.
- VL53L1X by @will-tm - ST time-of-flight distance sensor with ROI and multiple-sensor support.
- M5Stack units by @KoenBreeman and @lboue - M5Stack 4-Relay, the Seeed Grove multi-channel relay boards and the M5Stack M5Unit-BLDC brushless DC motor driver.
New major components
Section titled “New major components”Beyond new sensors, several components open up new capabilities.
- Daikin Madoka BRC1H climate by @Petapton - BLE control of the Daikin BRC1H (Madoka) wall controller: modes, setpoint, fan speed and reported temperatures, with MITM pairing and TLV response decoding.
- HDMI-CEC bus by @JosVanEijndhoven - puts an ESPHome device on the HDMI-CEC bus of a TV, with
on_messageautomations and ahdmi_cec.sendaction. - USB audio by @ab-tools - USB Audio Class host for ESP32 chips with USB OTG; plays audio on USB sound cards and DACs through
speaker: platform: usb_audioand captures from USB mics throughmicrophone: platform: usb_audio. - TinyUSB keyboard by @FrederikBolding - ESP32 with USB OTG appears as a HID keyboard with media keys.
- Cellular modem networking by @oarcher - PPPoS over a UART cellular modem on ESP32, so
api,mqttandotawork on LTE; signal sensors and a network-type text sensor land alongside (#6721, #14683). - RTSP server by @max246 - streams the
esp32_camerapicture as Motion JPEG over RTSP, playable in VLC, ffplay, go2rtc and Frigate without anything ESPHome-specific. - VNC client by @MindFreeze - shows a VNC server’s screen on an ESPHome display, with Hextile encoding, password authentication, input actions and touchscreen forwarding.
- BLE MIDI by @bogdanr - connects to a BLE MIDI device such as a pad controller, keyboard or foot switch, surfaces note, control-change and SysEx events as automations and can send MIDI back.
- ESP32 ULP coprocessor by @swoboda1337 - builds a user C program for the ESP32-S2/S3 RISC-V ULP or the C5/C6/P4 LP core, embeds it in the firmware and exposes its globals to lambdas as
ulp_<name>. - OpenThread border router - covered in its own section above.
- Zigbee improvements by @luar123 - sleepy end device (SED) support on ESP32, a
zigbee.reportaction and a configurable basic cluster with manufacturer and application version (#20487, #20488, #20519). - Power management by @rwrozelle - new
power_managementdomain with an ESP-IDF dynamic frequency scaling platform and optional automatic light sleep. - Haier water heater by @TheLexus - controls Haier hOn water heaters such as the VH3W over UART in place of the original Wi-Fi module.
- Fantini Cosmi Ecocomfort 2.0 VMC by @gledian - BLE control of Fantini Cosmi Aspirvelo Air Ecocomfort 2.0 Smart ventilation units, as a hub with a fan platform, read-only sensors and configuration entities (#17092, #15447, #20783).
- Duco heat recovery ventilation by @kokx - Duco Energy Comfort D325 ventilation system with mode select, serial, CO2 and flow sensors.
- Modbus monitor by @Bascht74 -
on_requestandon_responsetriggers for Modbus server and client hubs. - packet_interface by @clydebarrow - a layered packet framework with UART and UDP links, HDLC reliability, session and XXTEA encryption layers.
- New climate IR platforms - Airton by @Procsiab, Friedrich MW12Y3H by @rwrozelle, Haier Tundra by @fauxpark, Islandaire PTAC by @ipopov, Midea PortaSplit by @Fexiven, Mistral MHFE1126A by @lerhum, Panasonic by @Duckle29, Pioneer mini-split by @martinsah, Remko AR-715 by @naKruul, Samsung by @jorofi, Siemens IRA211 by @fonix232, plus a separate Airton serial platform by @guiguid.
- New display controllers - SH1122 OLED by @pl4nkton, ST7305 reflective LCD by @clydebarrow, HT16K33 character displays by @ilikecake, the SPD2010 touchscreen by @grischard and many new epaper_spi panels (GDEY0213F51, GDEY029Z95, GDEY029T94, Waveshare 2.13” G/B V3, Xteink X4 Pro, UC8151D, XSRUPB-7.5in-bwr) by various contributors.
- New LED strip drivers -
i2s_clockless_led_stripfor WS281x/SK6812 strips via I2S DMA by @j9brown, andln882x_spi_led_stripfor LN882x chips by @sebo-b. - Other new components - APC Proteous gate motors by @clydebarrow, the
ezsp_proxy_tapcomponent by @puddly, the Vevor DTX weather station by @Bofr5555, the LP5562 4-channel LED driver by @DennisGaida, and afilter_lifetimesensor by @tuct.
Other notable features
Section titled “Other notable features”- Switch initial state -
initial_state:andrestore_state:work with flash or RTC storage for platforms whose switches do not have their own restore (#20978). - Light initial effect -
initial_state:can now name aneffect:, so a strip boots into its startup animation (#18795). - Globals in RTC memory - a persistent
globalcan live in RTC RAM instead of flash, preserved across deep sleep without wearing out the flash (#13954). - Addressable light power estimation - LED strips can report the estimated current draw and limit it on the fly (#15348).
- Sendspin as a source - the
sendspinspeaker protocol gains a source role, so a device can stream a microphone to a Music Assistant server (#21696). i2s_audiofull duplex - single-chip speakers and microphones can share one bus (#19959).- ESP32 OTA security - new
signed_ota_verificationand NVS encryption options in theesp32block prepare devices for stronger OTA signing (#17562). - MQTT over WebSocket - WebSocket transport on ESP32 IDF and TLS option expansion (#14318, #16056), plus MQTT session persistence and a crash reporting channel (#12426, #17935).
- Online image progressive decode - decode a JPEG as it downloads, with download start and progress triggers (#21342, #21355).
- Runtime image speed-ups by @clydebarrow - JPEG decoding writes opaque RGB565 frames straight into the buffer, uses integer maths for grayscale and resize, and decodes at the smallest JPEGDEC scale that fits (#19454, #21386, #21387, #21390, #21393, #21784).
- ESP32 RMT seat check - ESPHome checks at compile time that every
esp32_rmt_led_strip,remote_transmitterandremote_receiverfits the chip’s RMT channels together, so a second strip no longer silently fails to start at boot (#22172).
Codebase correctness
Section titled “Codebase correctness”Alongside the memory and codegen work, this cycle closes several real correctness gaps.
- Deferring actions rejected where they would read freed memory -
emontx,mqtton_json_messageandhaieron_status_messagenow reject automations that containdelay,wait_untilorscript.wait. The received frame is only valid while the automation runs, so a deferring action used to read freed memory at runtime; configs now fail validation with a message pointing at the fix. esp32_hostedco-processor update - updates size their OTA chunks from the host’s per-RPC limit, so the previous fixed 1500-byte chunk no longer fails every co-processor update (#21394).libretinycrash reports - BK7238, BK7231N, LN882H and RTL8710B report the previous boot’s crash on reboot, following the ESP32 and ESP8266 crash handlers (#21007, #21012, #21648, #21728, #21752).- Remote protocol frame boundaries - NEC
command_repeatsnow sends real NEC repeat frames, MagiQuest reads the full 56 bit frame and checks its checksum, and 56 bit Panasonic frames are decoded in full (#17663, #10622, #20260). - Web server numbers without state - a number that has not published a state yet is reported as unknown instead of
0, so the web UI matches what Home Assistant already shows (#20973). web_serverinternal entities - the REST endpoints match the page and the API: an internal entity is no longer reachable by a guessed URL unlessinclude_internal: trueis set (#20883).
Thank you, contributors
Section titled “Thank you, contributors”This release includes 1357 pull requests from over 230 contributors. A huge thank you to everyone who made 2026.11.0 possible:
- @bdraco - 697 PRs including the self-contained AP mode web interface served as a captive portal, OTA key rotation and a UDP fallback for lossy links, crash reports on five more LibreTiny chips, a boot log buffer replayed over the API, moving strings and lookup tables across hundreds of components into flash, numeric scheduler ids, new shared bus, codegen and Apply entity helpers rolled out across the component tree, and a large expansion of codegen, unit and integration test coverage
- @swoboda1337 - 88 PRs including the clang-tidy 23 sweep, ESP-IDF 6 preparation, native Windows build support, and a broad fill-in of component test coverage
- @clydebarrow - 52 PRs including the new
runtime_imagestreaming JPEG decoder, the LVGL 9.6 migration with the color picker and menu widgets, the newpacket_interfacecomponent and XXTEA/HDLC layers, and merging simple actions into inline control flow - @jesserockz - 21 PRs including the component
DOMAINconstants rollout, newmipi_spiandepaper_spipanel models, and the move togh actions-lockfor workflow pinning - @FredM67 - 21 PRs including the deferring-action validators and their adoption across
modbus_client,mqtt,haierandnextion, and theemontxreboot lock and firmware-version read - @remcom - 17 PRs including the new
tmc2209stepper driver, thefusb302bUSB PD sink, the DFRobot SEN0609/SEN0610 radar andi2s_audiofull duplex - @Bascht74 - 14 PRs including the new
modbus_monitorcomponent, KeeLoq suffix bits and the Jarolift TDEF group frame, and theTcpClientLinkidle timeout - @luar123 - 12 PRs including zigbee sleepy-end-device support on ESP32, the zigbee report action, and GPIO hold during (deep) sleep
- @albert-canfield - 12 PRs including power-loss handling and weekday conversion fixes across
pcf8563,pcf85063andbm8563, dry-only thermostat support and better compile-error line numbers for lambdas - @kahrendt - 12 PRs including the new
sendspinsource role that streams a microphone to the server, theAudioCapturemicrophone buffer rework and the original-ESP32 i2s playback fixes - @rwrozelle - 10 PRs including the new
friedrichclimate IR component, thepower_managementdomain withesp32_power_management, UDP IPv6 unicast and multicast, and the Thread-sized UDP OTA - @tomaszduda23 - 10 PRs including CDC-UART on nRF52, the
zephyr_coredumpflash store and LVGL build fixes on nRF52 - @wolph - 10 PRs including the new Hi-Link LD6004 radar across every platform and the shared
LD600Xbase used by ld6002b - @exciton - 10 PRs including SSD1681 differential partial refresh and other
epaper_spiperformance work, and the newcw2017battery fuel gauge - @bharvey88 - 9 PRs including the
sen6xCO2, temperature compensation, PM number concentration, actions and status sensors, and user-defined API action variables with defaults - @techdregs - 9 PRs including the new
rx8111real-time clock with alarms, wake-up timer and event timestamps, andtmp102hardware configuration and alert entities - @fallenmi - 9 PRs including correctness fixes across the HLK radar family (
ld2410,ld2410s,ld2420,ld2450,ld2460),tflunaanddfrobot_sen0395 - @huangkongsheng - 8 PRs including a config-validator sweep across cron ranges,
cv.entity_id,cv.dimensions,cv.percentage_intand UTF-8 SSID length - @MindFreeze - 7 PRs including the new
vncclient component with Hextile encoding, password authentication and touchscreen input forwarding - @kbx81 - 7 PRs including
esp-idf-sbommanifest emission withesphome.project.sbomsupplier info, and interface-change notifications for network listeners - @latonita - 6 PRs including the new
bh1745colour sensor,lis2dw12accelerometer,husb238USB PD controller and the three-partas734xspectral sensor - @Rapsssito - 5 PRs including MQTT session persistence and expanded TLS options, the new
bq25186charger and RTC memory forglobals - @j9brown - 5 PRs including the new
i2s_clockless_led_stripDMA driver and theESPColorView/ addressable-light refactor - @mrtoy-me - 5 PRs including the
tas58xxfault, activate and mixer-mode options and support for multiple audio DACs on one speaker - @oarcher - 4 PRs including the new
modemPPPoS cellular networking component with signal sensors and the WiFi-to-ethernet WISP bridge - @ab-tools - 4 PRs including the new
usb_audioUAC host support and USB host FIFO sizing on ESP32-S2/S3 - @gledian - 4 PRs building the new
ecocomfort2component for Fantini Cosmi VMC units over BLE - @n-IA-hane - 4 PRs including a configurable TTS playback start timeout and the
micro_wake_wordinference core selection - @nliaudat - 4 PRs including the new
mics_5524gas sensor, WiFiap_mode: ALWAYS_ONandesp32_cameradigital zoom - @epicRE - 4 PRs including the new
delta_wallboxAC wallbox component with current-set support - @dcb - 4 PRs including
ld2450polygon-zone flash writes, lost-radar-link detection and multicast-bit MAC reporting - @fornellas - 3 PRs including on-device
ld2450polygon zones with per-target position text sensor and extracse7761sensors - @RaHehl - 3 PRs including
esp32_camerasingle-imagecapture_delayand triggers, and the hoermann_hcp actuator-error binary sensor - @puddly - 3 PRs including the new
ezsp_proxy_tapSiLabs EZSP auto-ACK bridge andusb_uartmodem pin control with hardware flow control - @porelli - 3 PRs including switch
initial_statewith flash or RTC storage, per-entity preference storage selection and LibreTiny RTC preferences on BK7231/BK7238 - @KoenBreeman - 2 PRs: the new Seeed Studio Grove multi-channel relay and M5Stack 4-relay switches
- @NovakIrs - 2 PRs building the new HLK-LD2410S presence radar
- @ilikecake - 2 PRs: the new
ht16k33_charcharacter display and the pca9554 device-option expansion - @egormanga - 2 PRs: the new
homeassistantlight platform and WiFi Easy Connect (DPP) provisioning - @zigboi - 2 PRs: Mitsubishi multi-vane control and fahrenheit_compatibility mode
- @felipecrs - 2 PRs: WiFi access-point WISP mode and cover-toggle support in the native API
- @tuct - 2 PRs: the new
filter_lifetimecomponent andpmsx003Luftmy LD15 support - @CircuitSetup - 2 PRs: configurable
atm90e32thresholds and gain-calibration write verification - @mvoss96 - 2 PRs: addressable LED strip power estimation / current limiting and
cse7766low-load power behaviour - @bughaver - 2 PRs:
heatpumpirEco and Boost presets and the ZMP IR receiver - @PolarGoose - 2 PRs:
dlms_meterLandis+Gyr E450 HDLC Cyprus support and a parser refresh - @Ardumine - 2 PRs: the new
zephyr_mcumgrSMP UDP OTA transport for nRF52 and Zephyr/nRF52 UDP IPv6 - @Zebble - 2 PRs: the new
lis3dhaccelerometer andtca8418keypad components - @david-collett - 2 PRs:
esp32_ble_serversecure connection support - @lboue - 2 PRs: the new M5Unit-BLDC and ICM-20689 components
- @aalaei - 2 PRs: nRF52 hardware SPI support and the new
veml6040RGBW colour sensor - @eoleedi - 2 PRs:
hitachi_ac344quiet, vertical swing and mildew-proof modes - @juriyivanov - 2 PRs: gree IR receiver support and YX1FF/YAC frame fixes
- @DennisGaida - 2 PRs:
bmi270BMM150 magnetometer aux support and the newlp5562LED driver output - @ikruglov - 2 PRs:
bl0939internal temperature sensor andpcf8574output preservation across MCU reboots - @Gunni - 2 PRs: clearer
yaml_utilpackage errors and cachedesp32_hostedfirmware downloads - @candrews - 2 PRs: new
epaper_spipanels (XSRUPB-7.5in-bwr and Good Display GDEY029Z95) - @bboe - 2 PRs: media_player constant bitrate and shared
CONF_BITRATE - @guillempages - 2 PRs: image RGB111 format and a Pillow deprecation fix
- @piitaya - 2 PRs: cover stop-tilt in the core and MQTT
- @Mat931 - 2 PRs: the
systa_bustext_sensor and anesp32_cameracompile warning - @mbrudka - 2 PRs:
micro_wake_wordinternal RAM placement and configurable capture buffer duration - @jeroen85 - 2 PRs: four-decimal fast value formatting and a bigger
web_server_idftask stack - @sebo-b - 2 PRs:
web_serverinternal-entity URL handling and the newln882x_spi_led_strip - @gongloo - 2 PRs:
mipi_rgbdirect-to-PSRAM rotated blitting and HA state-subscription vector reservation - @labodj - 2 PRs: vbus P1 telegram checksum handling and shared
CONF_VALUE_TYPE - @andytrofimov - 2 PRs: audio HTTP partial-read release and reduced speaker announcement buffering
- @Kubuxu - 2 PRs:
ledchardware duty dithering and a PWM duty-scaling fix - @javitonino - 2 PRs: voice_assistant microphone stop handling at STT_END and before speech
- @randybb - 2 PRs: OTA and voice_assistant builds with IPv4 disabled
- @GiorgioAresu - 2 PRs: the new
mipi_rgbGC9503V and ZX3D95CE01S-TR-4848 panel support - @adamsthws - 2 PRs: an api responding-action array-arg compile fix and
cse7766verbose power-factor logging - @crnjan - 2 PRs:
mitsubishi_cn105horizontal vane direction control - @chunckus-aurelius - 2 PRs: shared tap and double-tap support via the new
motioncomponent - @iskyguy - 2 PRs: the
sht4xserial-number text sensor with a longer response wait
Also thank you to @Petapton, @Procsiab, @mick96, @kokx, @jorofi, @CzBiX, @JosVanEijndhoven, @peter-valkov, @jzucker2, @GilDev, @DAVe3283, @tchilov, @ificator, @patagonaa, @marshn, @iyesin, @endemics, @AchilleGR, @amateescu, @JiriPrchal, @philpem, @B48D81EFCC, @will-tm, @tjhorner, @mrene, @wiiaam, @minorOffense, @GioMez, @t2bottom, @fonix232, @AnilDaoud, @pl4nkton, @joshuaboniface, @nullable-eth, @JohnMcLear, @ankur-paan, @FrederikBolding, @paveldn, @rwalker777, @cociweb, @dmik, @e28eta, @RobertH1993, @emilioaray-dev, @functionpointer, @naKruul, @mikesmitty, @Bofr5555, @mkhrulov, @arpena, @SebiGo, @MatiasFernandez, @RuedigerMueller, @slimcdk, @Siddharthsinghkumar, @martinsah, @rggammon, @limpkin, @happydasch, @bootc, @sourabhjaiswal, @lerhum, @longerCZE, @opcod3, @AndreKR, @max246, @profplump, @Fexiven, @jrvd007, @pputerla, @fredkotze, @Aptimex, @ptr727, @patrickod, @damib, @polyfloyd, @bogdanr, @bkbartk, @ryansch, @c0nsumer, @MayorBug, @andreuSignes, @mfishma, @mkucharek, @backcountrymountains, @linkedupbits, @ljungqvist, @matt123p, @danepowell, @jesusvallejo, @adminy, @jlmeredith, @PeterLinuxOSS, @grischard, @ademuri, @Chorty, @pleasantone, @willumpie82, @jcianci12, @Marvinthebored, @zerafachris, @cosmicDustOfLightLength, @ipopov, @rupayon123, @dbuezas, @toups, @CReimer, @Firat17aze, @fauxpark, @omersiar, @TheZoc, @k7hpn, @jaaviercr, @ajfriesen, @steamEngineer, @KD5RYN, @jhenkens, @TheLexus, @DavidWAbrahams, @p1ngb4ck, @tzabbi, @HugoPeters1024, @r3wretrhy, @nagisa, @dhoeben, @daeho-ro, @miloit, @elpollodiablo, @Cat-Ion, @tommat01, @thomasfw, @bbbert, @Komzpa, @ishai-levy, @magnusoverli, @samsonovss, @bhuveshm29, @christophmertins, @cpruijsen, @glmnet, @manuelm, @FuNK3Y, @Korkuttum, @JoHoenk, @Duckle29, @kboone, @AdamVig, @chbgdn, @heythisisnate, @Doridian, @lobo67, @b84330808, @rusitschka, @arthurkomatsu, @gcormier, @guiguid, @abmantis, @koszoaron, @syssi, @kVinsom, @francescopace, @zeroflow for their contributions, and to everyone who reported issues, tested pre-releases, and helped in the community.
Breaking changes
Section titled “Breaking changes”Component changes
Section titled “Component changes”- MagiQuest: The decoder now reads the full 56-bit frame and checks its checksum, so
x.wand_idandx.magnitudeinon_magiquestlambdas change. Old binary sensor matches still work; run the dumper again for lambda values. #10622 - NEC remote:
command_repeatsnow sends real NEC repeat frames and is clamped to 1 to 10. Receivedx.command_repeatsis always 1; detect a held button from the frame cadence. #17663 - Panasonic remote: Frames of 56 bits or more now decode as
nbits: 56with the newaddress_2byte. Update configs captured from 56-bit remotes with a fresh dump. #20260 - CAN bus: A constant
canbus.sendpayload longer than 8 bytes now fails validation instead of being silently truncated. Fix also stops sending the wrong length for lambda payloads of 256 bytes or more. #20309 - Ethernet: Removed the deprecated
clk_modeoption. Use theclk:block withmode:andpin:. #20384 - DLMS meter: Removed the deprecated
provideroption. Most configs can drop the key;provider: netznoeusers add the twocustom_patternsit used to inject. #20385 - DLMS meter: Removed the deprecated predefined sensor and text_sensor keys such as
voltage_l1andtimestamp. Each value is now its own entity withobis_code. #20386 - LVGL: Removed the deprecated number
update_on_releaseoption. Usetrigger: on_release. #20387 - Nextion: Removed the deprecated
dump_device_infooption. Device info is always logged; delete the key. #20388 - QSPI AMOLED: Removed the legacy renamed component stub. Use
platform: qspi_dbi. #20396 - emonTx:
on_jsonandon_datareject deferring actions (delay,wait_until,script.wait) at validation. Copy the values you need into globals first, then defer from a separate script.dataandraw_jsonare nowStringRefinstead ofstd::string. #20516 - MQTT:
on_json_messagerejects deferring actions at validation. Copy the values you need into globals first, then defer from a separate script. #20538 - Haier:
on_status_messagerejects deferring actions at validation. Copy the values you need into globals first, then defer from a separate script. #20539 - Web server: REST endpoints no longer match
internalentities by URL unlessinclude_internal: trueis set. This matches the native API and MQTT behaviour. #20883 - Web server: A number entity that has not published a state yet is now reported as unknown instead of
0. In the REST and event-stream JSON it is sent as"state":"NA","value":"NaN". #20973 - E-paper SPI: Refactored
color_bwrhandling; WeAct 3C, Waveshare B, Waveshare BWR and Inkplate 2 panels now map colors to the nearest of black, white or red in RGB space. Waveshare 7.5” V2 BWR and WeAct 3C panels now reportDISPLAY_TYPE_COLORinstead ofBINARY, so the test card andget_display_type()lambdas change. #19654 - HTTP request:
http_request.get,postandsendactions are now asynchronous and run from the component loop. Scripts containing these actions keep running until the response arrives; setmode: queuedormode: parallelwhere repeated runs must not be skipped. Newmax_concurrent_requestsoption (1 to 4) allows more than one request in flight. #21486 - API sub-devices:
relation:is now required on every entry underesphome: devices:. Addrelation: viato keep today’s behaviour for a physical device reached through this node, orrelation: childfor a logical part of this node. #21232
Platform changes
Section titled “Platform changes”- Network: Added
network: enable_ipv4(defaulttrue). Anopenthreadconfig onesp32without anything else requiring IPv4 now defaults IPv4 off; addnetwork: enable_ipv4: trueto opt back in.enable_ipv6now resolves automatically when a component requires it, soopenthreadno longer needsenable_ipv6: true. #14526 - OpenThread: Added Border Router support on ESP32. Requires ESP-IDF 5.5.5 or newer, for plain Thread devices as
well as border routers. Remove a pinned
esp32.framework.versionor raise it to 5.5.5. #18104 - esp32_hosted: Moved to
esp_hosted3.0.10. Requires ESP-IDF 5.5 or newer. A 1-bit SDIO setup must now setd1_pin(the pin wired to DAT1).active_high: falseis no longer accepted;active_high: trueworks with a deprecation warning. #21394 - ESP32: Minimum ESP-IDF version is now 5.1. A build pinned to 5.0.x fails validation. #21398
- LibreTiny: Bumped to 1.14.0 with BK7231N and BK7231T built on Beken BDK 3.0.78. Fixes STA+AP captive portal
credential saving, OTA watchdog resets and Wi-Fi-less reboot loops. LN-CB3S V1.0 configs that use the
D12alias now drive PA10 instead of PA11; the old pin isD13orPA11. ADC readings on BK7231N and BK7231T are now correct (they previously read about half the true voltage). #21531 - ESP32 RMT: ESPHome now checks at validation that
esp32_rmt_led_strip,remote_transmitterandremote_receiverfit the chip’s RMT channels together. Configs with too many components, with more than oneuse_dmain a direction, or with an invalidrmt_symbolsvalue now fail validation instead of failing at boot. #22172
Undocumented API changes
Section titled “Undocumented API changes”Many components reorganized internal C++ APIs this release. These changes are not covered by the formal breaking change policy, but lambda users and external component maintainers may need to adjust. Grouped by theme:
Entity names and strings moved to flash
Section titled “Entity names and strings moved to flash”-
EntityBase names:
EntityBase::name_is now aProgmemStringRefon ESP8266.get_name()is deprecated and returns aconst StringRef &with a RAM copy made on first use (removal in 2027.5.0). Useget_log_name()for log lines andget_name_to(buffer)orname_equals(other)where you need the value.// BeforeESP_LOGD(TAG, "'%s' updated", this->name_.c_str());// AfterESP_LOGD(TAG, "'%s' updated", LOG_STR_ARG(this->get_log_name())); -
API action strings: The
(progmem)proto option now also applies to string fields.HomeassistantActionRequest.serviceandHomeassistantServiceMap.key/valuecarryProgmemStringRefvalues. Code that fills aHomeassistantActionRequestassignsProgmemStringRef, for exampleresp.service = ProgmemStringRef(StringRef(name));. #20425
Component names and payloads kept in fixed buffers or StringRef
Section titled “Component names and payloads kept in fixed buffers or StringRef”-
BedJet:
BedJetHub::get_name()now returnsconst char *from a fixed 24-byte buffer instead ofstd::string. Pass it directly to%slog arguments. #21204 -
NFC binary sensor:
set_ndef_match_string()/set_tag_name()now takeconst char *.match_string_is stored as aStringRef. #21208 -
key_collector: The five key lists (
start_keys,end_keys,back_keys,clear_keys,allowed_keys) are stored asStringRefviews of the YAML literals; the setters takeconst char *. #21210 -
graph:
GraphTrace::get_name()now returnsStringRefinstead ofstd::string. Lambdas comparing with==, calling.c_str(), or assigning tostd::stringkeep working. #21211
Flash tables for internal lookup strings
Section titled “Flash tables for internal lookup strings”-
Haier: The hOn alarm message table (
HON_ALARM_MESSAGES,HON_ALARM_COUNT) is removed fromhon_packet.hand kept as aPROGMEM_STRING_TABLE. On ESP8266, themessagepassed toon_alarm_start/on_alarm_endis a static buffer overwritten by the next alarm change; usecodeinstead if an automation waits. #20641 -
Nextion:
get_queue_type_string()is no longer virtual and returnsconst LogString *instead ofconst char *. Wrap withLOG_STR_ARG()to pass it to%slog arguments. #20658 -
NFC URI prefixes:
PAYLOAD_IDENTIFIERSandPAYLOAD_IDENTIFIERS_COUNTare removed fromndef_record_uri.h. The table is now aPROGMEM_STRING_TABLEinndef_record_uri.cpp. #20709
Hub forwarding entities (Apply pattern)
Section titled “Hub forwarding entities (Apply pattern)”Many hub components replaced their per-entity C++ classes with codegen-only Apply* entities. The hub gains a
public method that takes the state, index or value. External code that inherited from the removed classes should
switch to ApplyButton / ApplyNumber / ApplySelect / ApplySwitch / ApplyFloatOutput / ApplyBinaryOutput.
The generated entity’s auto-generated id changes; entity names and object ids do not.
-
Hub buttons: ld2410, ld2412, ld2420, ld2450, seeed_mr24hpc1, seeed_mr60fda2, haier, hoermann_hcp, dfrobot_sen0609, bq25186, espectre, tfluna. #20964
-
Hub numbers: ld2410, ld2412, ld2450, seeed_mr24hpc1, dfrobot_sen0609.
set_gate_thresholdon ld2410 now takes the number entity itself. #20965 -
Hub selects: ld2410, ld2412, ld2420, ld2450, seeed_mr24hpc1, seeed_mr60fda2, haier, es8388, espectre. #20966
-
Hub switches: ld2410, ld2412, ld2450, seeed_mr24hpc1, at581x. #20967
-
Hub channel outputs: tlc59208f, dac7678, gp8403, my9231, sm2135, sm2235, sm2335, bp1658cj, lp5562, mcp4728, pca9685, sm16716, tlc5947, tlc5971, tm1638, bh1745, emc2101, waveshare_io_ch32v003. The hubs gain
write_channel(channel, state)instead of per-channel classes. #21257 -
pipsolar:
PipsolarSwitchclass removed; switches use Apply entities.Pipsolar::queue_commandnow takesconst char *(astd::stringoverload remains for lambdas). #21659 -
sendspin:
SendspinEnabledSwitchclass removed. #21673 -
bq25186:
BQ25186PgGpoSwitchclass removed; the generated code usespublish="on_success". #21675 -
pcm5122:
PCM5122PowerSwitchclass removed; the generated body callsset_standby(state)orset_powerdown(state)directly. #21677 -
mitsubishi_cn105:
MitsubishiCN105VerticalVaneDirectionSelectreplaced withselect::ApplySelect. Both vane direction selects now live in oneselect:entry per hub.WideVaneModeenumerators renamed fromFAR_LEFTtoPOSITION_1etc. #21863
Copy / follow entity platforms
Section titled “Copy / follow entity platforms”- copy, switch, number, text:
copy::CopySensor,copy::CopyTextSensor,switch_::SwitchBinarySensor,number::NumberSensorandtext::TextTextSensorare removed. The entities are now plainsensor::Sensor,binary_sensor::BinarySensorandtext_sensor::TextSensorthat follow a source through a callback registered beforesetup().setup_priorityis no longer accepted on these entities. #21610 #21612
Remote transmitter actions
Section titled “Remote transmitter actions”-
Per-protocol action classes removed:
NECAction,SonyAction,PanasonicAction,KeeloqAction,MagiQuestAction,HaierAction,MideaAction,MirageAction,AEHAAction,ABBWelcomeAction,ProntoAction,RC6Actionand 20+ others. Codegen now produces stateless functions throughregister_protocol_action. External protocols still work through the unchanged Pythonregister_action. #20549 #20564 #20568 -
Byte payload actions:
uart.write,udp.write,sx127x,sx126xandcc1101send-packet actions useApplyBytesinstead of per-componentTEMPLATABLE_BYTESaction classes.SendPacketAction,UDPWriteActionandUARTWriteActionare removed. #21263 -
UART switch and button payloads: Payload setters now take a pointer and a length. The vector and initializer list overloads used by codegen are removed. #20082
Triggers built from callbacks
Section titled “Triggers built from callbacks”-
display
on_page_change:DisplayOnPageChangeTriggeris removed andDisplay::add_on_page_change_triggerno longer exists. The storage is compiled out when noon_page_changeis configured. The generatedtrigger_idkey is gone. #20456 -
graphical_display_menu
on_redraw:GraphicalDisplayMenuOnRedrawTriggerremoved.add_on_redraw_callback()now passesconst GraphicalDisplayMenu *. #20452 -
Callback automations with inline actions: When every action in a callback automation is inline, no
Automationor action object is generated.ScriptExecuteActionandScript::execute_tupleare removed; usescript.executethrough the apply path. #21979
Numeric scheduler ids and heap-free command queues
Section titled “Numeric scheduler ids and heap-free command queues”-
dallas_temp / one_wire:
OneWireDevice::get_address_name()is removed. Format the address withformat_hex_prefixed_to(buf, this->address_)for log lines;LOG_ONE_WIRE_DEVICEstill works.// Beforethis->set_timeout(this->get_address_name().c_str(), 750, [this] { ... });// Afterstatic constexpr uint32_t CONVERSION_TIMEOUT_ID = 0;this->set_timeout(CONVERSION_TIMEOUT_ID, 750, [this] { ... }); -
dfrobot_sen0395: The
Commandclass hierarchy andenqueue(std::unique_ptr<Command>)are gone; commands are now 2-byte values in aStaticRingBuffer. The documenteddfrobot_sen0395.resetanddfrobot_sen0395.settingsactions and the switches are unchanged. #20906
Other API changes
Section titled “Other API changes”-
Light HSV on addressable strips:
ESPColorSettable::set_hsv()now also clears the white channel. A lambda that relied on a previous white value being kept must set it explicitly afterset_hsv(). #20265 -
AddressableLight refactor:
ESPColorViewand related types were refactored.ESPColorSettable::set(ESPHSVColor)andESPColorRange::set(ESPHSVColor)are deprecated; useset_hsv(). ExternalAddressableLightsubclasses need small changes - see the developer blog post. #21577 -
I2C little-endian helpers: 36 sensor components now use the shared
read_byte_16_le,write_byte_16_le,read_bytes_16_le,encode_value_le<>helpers. External components can follow suit; see the helper PR #20938. #20939 -
heatpumpir:
set_protocol()is gone. The climate is constructed with aProtocolTag<P>so only the configured protocol’s class is linked. #20707 -
atm90e32: The public
using_saved_calibrations_field, theOffsetRestoreStatetype,resolve_offset_restore_stateandprepare_offset_rollbackhelpers are removed. Gain, offset and power offset calibration share one save/rollback path. #18731 -
ld6002b / ld600x:
LD6002BComponentis now a thin subclass ofld600x::LD600XComponent. The twelve per-axis area sensor setters collapse intoset_area_sensor(kind, area, axis, sensor). #19837 -
pulse_counter: The software interrupt is now attached to the counted edges only when
internal_filter: 0us. Edge mode setters log an error and ignore a change made aftersetup(). #21271 -
micro_wake_word: Internal RAM placement is now opt-in through
prefer_internal_ram: true; disabled models release their arena and weight copy. #20529 -
speaker:
AudioPipeline::start_url()andstart_file()take an optional announcement boolean. Existing one-argument calls remain valid. Announcements start once the raw buffer has not changed for 1.5 s, in addition to the normal startup threshold. #21091
Breaking changes for developers
Section titled “Breaking changes for developers”- Entity names in flash on ESP8266:
EntityBase::name_is now aProgmemStringRef. Itsc_str()is deprecated andget_name()is deprecated; useget_log_name()withLOG_STR_ARG()for log calls andget_name_to(buffer)orname_equals()where you need the value. Removal in 2027.5.0. #20423 #20615 - API action strings:
(progmem)proto option now applies to string fields.HomeassistantActionRequest.serviceandHomeassistantServiceMap.key/valuetake aProgmemStringRef. The 384 byte user-action text limit is gone. #20425 - ESPColorView refactor:
AddressableLightand related types were refactored.ESPColorSettable::set(ESPHSVColor)andESPColorRange::set(ESPHSVColor)are deprecated; useset_hsv(). ExternalAddressableLightsubclasses need small changes - see the developer blog post. #21577 - AddressableLight HSV:
ESPColorSettable::set_hsv()now clears the white channel. #20265 - Display color order:
draw_pixels_at()andColorUtilno longer take a color order argument; RGB 888 pixel blocks are alwaysb, g, rin memory. #20884 - InternalGPIOPin: Now binds to the platform pin class instead of a virtual base. #20455
- RingBuffer alias: Removed the deprecated
esphome::RingBufferalias. #20390 - alloc_helpers.h:
helpers.hno longer re-exportsalloc_helpers.h; include it directly. #20389 - Numeric scheduler ids: Many components moved from string scheduler ids to numeric ids. External components
using
set_timeout()/set_interval()with strings should migrate toconstexpr uint32_tids. #20361 - Component DOMAIN constants: Every component now has a
DOMAINconstant used instead of name literals in code generation. - LVGL 9.6.0: Internal LVGL bump may affect external components calling LVGL APIs directly. #20257
- Light effect list: Light effect list is kept in a flash
ConstVector. #20204 - Climate/Fan traits:
custom_fan_modes,custom_presetsandpreset_modesare kept inConstVector; deprecated traits setters removed. #20213 #20214 - Event types: Kept in a shared flash table. #20217
- BedJet/Xiaomi:
BedJetHub::get_name()returnsconst char *instead ofstd::string. #21204 Xiaomi sensors share a newXiaomiDevicebase. #21483 - Remote transmitter actions: Per-protocol
...ActionC++ classes (NECAction, PanasonicAction, HaierAction, MideaAction and many more) removed; codegen now produces stateless functions throughregister_protocol_action. #20549 #20564 #20568 - Remote dumpers: Stateless dumpers kept in flash. #21563
- Callback automations:
build_callback_automation/build_trigger_callbacknow run directly withoutAutomationor action objects when every action is inline.ScriptExecuteActionandScript::execute_tupleare removed; usescript.executethrough the apply path. #21979 - ApplyEntity helpers: Many hub buttons, numbers, selects, switches and outputs moved to codegen-only
Apply*entities. Per-component entity classes such asPipsolarSwitch,PCM5122PowerSwitch,TLC59208FChannel,BQ25186PgGpoSwitchare removed; the hubs gain public methods that take the state or channel. #20964 #20965 #20966 #20967 #21257 - Copy entity platforms:
copy::CopySensor,copy::CopyTextSensor,switch_::SwitchBinarySensor,number::NumberSensorandtext::TextTextSensorare removed; entities are now plain base-class entities with a follow callback. #21610 #21612 - Weikai: Base classes marked
final. #17292
For detailed migration guides and API documentation, see the ESPHome Developers Documentation.
Full list of changes
Section titled “Full list of changes”For the complete list of every merged pull request in this release, see the full 2026.11.0 changelog.


























