<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Home Assistant Developer Docs Blog</title>
        <link>https://developers.home-assistant.io/blog</link>
        <description>Home Assistant Developer Docs Blog</description>
        <lastBuildDate>Mon, 27 Apr 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Serious about serial: migrating from pyserial to serialx]]></title>
            <link>https://developers.home-assistant.io/blog/2026/04/27/pyserial-to-serialx</link>
            <guid>https://developers.home-assistant.io/blog/2026/04/27/pyserial-to-serialx</guid>
            <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Existing integrations and libraries communicating with serial ports should migrate from pyserial, pyserial-asyncio, and pyserial-asyncio-fast to serialx. This new library features native asyncio support on all platforms and will allow your integrations and libraries to take advantage of ESPHome serial proxies in Home Assistant, and includes critical fixes for asyncio event loop stability.]]></description>
            <content:encoded><![CDATA[<p>Existing integrations and libraries communicating with serial ports should migrate from <code>pyserial</code>, <code>pyserial-asyncio</code>, and <code>pyserial-asyncio-fast</code> to <a href="https://github.com/puddly/serialx" target="_blank" rel="noopener noreferrer" class=""><code>serialx</code></a>. This new library features native asyncio support on all platforms and will allow your integrations and libraries to take advantage of <a href="https://esphome.io/components/serial_proxy/" target="_blank" rel="noopener noreferrer" class="">ESPHome serial proxies</a> in Home Assistant, and includes critical fixes for asyncio event loop stability.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="background">Background<a href="https://developers.home-assistant.io/blog/2026/04/27/pyserial-to-serialx#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background" translate="no">​</a></h2>
<p><code>pyserial</code> has been the de facto serial library in Python for many years and has broad support for all popular platforms. Its API, however, predates asyncio in Python and is sync-only. The <code>pyserial-asyncio</code> package was eventually released to bridge <code>pyserial</code> with asyncio. Unfortunately, <code>pyserial-asyncio</code> development never reached 1.0 stability or cross-platform support, and neither <code>pyserial</code> nor <code>pyserial-asyncio</code> have had PyPI releases in almost five years. We forked <code>pyserial-asyncio</code> and released <a href="https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast/" target="_blank" rel="noopener noreferrer" class=""><code>pyserial-asyncio-fast</code></a> to fix outstanding issues affecting Core event loop stability.</p>
<p>We developed <code>serialx</code> from the ground up as a modern Python serial library with native sync and async APIs. It is import-compatible with the <code>serial</code>, <code>serial_asyncio</code>, and <code>serial_asyncio_fast</code> modules and allows existing packages to migrate with very minimal changes, if any.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration">Migration<a href="https://developers.home-assistant.io/blog/2026/04/27/pyserial-to-serialx#migration" class="hash-link" aria-label="Direct link to Migration" title="Direct link to Migration" translate="no">​</a></h2>
<p>The <code>serialx</code> documentation has <a href="https://puddly.github.io/serialx/how-to/pyserial-migration.html" target="_blank" rel="noopener noreferrer" class="">an extensive migration guide</a> that goes into more detail.</p>
<p>Most packages just need to replace <code>pyserial</code>, <code>pyserial-asyncio</code>, and <code>pyserial-asyncio-fast</code> with <code>serialx</code> in their <code>setup.py</code> or <code>pyproject.toml</code> file and update exception handling to replace broad catching of <code>SerialException</code> with more granular error handling (such as <code>OSError</code> and <code>TimeoutError</code>).</p>
<p>Packages directly constructing a sync <code>serial.Serial()</code> object should migrate to using the <code>serialx.serial_for_url()</code> helper to ensure automatic compatibility with all supported protocols.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="prompt-for-your-agent">Prompt for your agent<a href="https://developers.home-assistant.io/blog/2026/04/27/pyserial-to-serialx#prompt-for-your-agent" class="hash-link" aria-label="Direct link to Prompt for your agent" title="Direct link to Prompt for your agent" translate="no">​</a></h3>
<p>The migration itself is mechanical, paste the following instructions into your agent of choice:</p>
<blockquote>
<p>Migrate my code from pyserial, pyserial-asyncio, and pyserial-asyncio-fast to serialx using
<a href="https://raw.githubusercontent.com/puddly/serialx/refs/heads/dev/docs/how-to/pyserial-migration.md" target="_blank" rel="noopener noreferrer" class="">https://raw.githubusercontent.com/puddly/serialx/refs/heads/dev/docs/how-to/pyserial-migration.md</a></p>
</blockquote>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New radio frequency entity platform for RF device integrations]]></title>
            <link>https://developers.home-assistant.io/blog/2026/04/24/radio-frequency-entity-platform</link>
            <guid>https://developers.home-assistant.io/blog/2026/04/24/radio-frequency-entity-platform</guid>
            <pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Home Assistant now has a radio_frequency entity platform that decouples RF transceiver hardware from the devices it controls. Instead of each device integration talking directly to specific RF hardware, transmitter integrations (like esphome) expose RadioFrequencyTransmitterEntity instances, and device integrations send commands through them via helper functions.]]></description>
            <content:encoded><![CDATA[<p>Home Assistant now has a <code>radio_frequency</code> entity platform that decouples RF transceiver hardware from the devices it controls. Instead of each device integration talking directly to specific RF hardware, transmitter integrations (like <code>esphome</code>) expose <code>RadioFrequencyTransmitterEntity</code> instances, and device integrations send commands through them via helper functions.</p>
<p>This mirrors the <a class="" href="https://developers.home-assistant.io/blog/2026/03/30/infrared-entity-platform"><code>infrared</code> entity platform</a> and was approved in <a href="https://github.com/home-assistant/architecture/discussions/1365" target="_blank" rel="noopener noreferrer" class="">architecture discussion #1365</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="architecture">Architecture<a href="https://developers.home-assistant.io/blog/2026/04/24/radio-frequency-entity-platform#architecture" class="hash-link" aria-label="Direct link to Architecture" title="Direct link to Architecture" translate="no">​</a></h2>
<p>The <code>radio_frequency</code> domain sits between two types of integrations:</p>
<ul>
<li class=""><strong>Transmitter integrations</strong> (ESPHome, Broadlink, …) implement the <code>RadioFrequencyTransmitterEntity</code> base class to provide hardware-specific RF transmission.</li>
<li class=""><strong>Consumer integrations</strong> (garage door openers, RF remotes, wireless switches, …) use helper functions to send device-specific RF commands through available transmitters.</li>
</ul>
<p>Users select which transmitter to use during the consumer integration's config flow, filtered by the frequency the device operates on.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="implementing-a-transmitter-integration">Implementing a transmitter integration<a href="https://developers.home-assistant.io/blog/2026/04/24/radio-frequency-entity-platform#implementing-a-transmitter-integration" class="hash-link" aria-label="Direct link to Implementing a transmitter integration" title="Direct link to Implementing a transmitter integration" translate="no">​</a></h2>
<p>Transmitter integrations provide the <code>radio_frequency</code> platform by subclassing <code>RadioFrequencyTransmitterEntity</code>, declaring their <code>supported_frequency_ranges</code>, and implementing <code>async_send_command</code>:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> rf_protocols </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> RadioFrequencyCommand</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">radio_frequency </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> RadioFrequencyTransmitterEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyRadioFrequencyTransmitterEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">RadioFrequencyTransmitterEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""My RF transmitter."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">@property</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">supported_frequency_ranges</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">list</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token builtin" style="color:rgb(130, 170, 255)">tuple</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token builtin" style="color:rgb(130, 170, 255)">int</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">int</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Return the list of (min_hz, max_hz) ranges this hardware can transmit on."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">300_000_000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">348_000_000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">433_050_000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">434_790_000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">async_send_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> RadioFrequencyCommand</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Send an RF command."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_device</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">transmit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            frequency</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">frequency</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            modulation</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">modulation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            timings</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get_raw_timings</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>The base class tracks the timestamp of the last sent command as the entity state, so transmitter integrations only need to handle the actual transmission.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="building-a-consumer-integration">Building a consumer integration<a href="https://developers.home-assistant.io/blog/2026/04/24/radio-frequency-entity-platform#building-a-consumer-integration" class="hash-link" aria-label="Direct link to Building a consumer integration" title="Direct link to Building a consumer integration" translate="no">​</a></h2>
<p>Consumer integrations control RF devices by sending commands through a transmitter entity. They don't interact with RF hardware directly. The snippets below are adapted from the <a href="https://github.com/home-assistant/core/pull/168450" target="_blank" rel="noopener noreferrer" class=""><code>honeywell_string_lights</code></a> integration, which uses the platform to drive a Honeywell String Lights set.</p>
<p><strong>1. Declare the dependency</strong> in <code>manifest.json</code>:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  "dependencies": ["radio_frequency"]</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></div></code></pre></div></div>
<p><strong>2. Load the device's commands</strong> from the <a href="https://github.com/home-assistant-libs/rf-protocols" target="_blank" rel="noopener noreferrer" class=""><code>rf-protocols</code></a> library:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> rf_protocols </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> get_codes</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">COMMANDS </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> get_codes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"honeywell/string_lights"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>Each loaded command exposes the frequency and modulation the device uses, which the config flow needs to filter transmitters.</p>
<p><strong>3. Let the user pick a transmitter</strong> in the config flow, using a sample command to filter by the frequency and modulation the device requires:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> rf_protocols </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> RadioFrequencyCommand</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">radio_frequency </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> async_get_transmitters</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">exceptions </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> HomeAssistantError</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">sample_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> RadioFrequencyCommand </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_add_executor_job</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    COMMANDS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">load_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"turn_on"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">try</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    transmitters </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> async_get_transmitters</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> sample_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">frequency</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> sample_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">modulation</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">except</span><span class="token plain"> HomeAssistantError</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_abort</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">reason</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"no_transmitters"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">not</span><span class="token plain"> transmitters</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_abort</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">reason</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"no_compatible_transmitters"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>Only <code>ModulationType.OOK</code> (on-off keying) is supported right now; later releases can add other modulation types.</p>
<p><strong>4. Send RF commands</strong> using the helper function and the stored transmitter entity ID:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">radio_frequency </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> async_send_command</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">async_turn_on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">**</span><span class="token plain">kwargs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Any</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Turn on the light."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    command </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_add_executor_job</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        COMMANDS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">load_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"turn_on"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> async_send_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_transmitter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_attr_is_on </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">True</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_write_ha_state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rf-protocols-and-codes">RF protocols and codes<a href="https://developers.home-assistant.io/blog/2026/04/24/radio-frequency-entity-platform#rf-protocols-and-codes" class="hash-link" aria-label="Direct link to RF protocols and codes" title="Direct link to RF protocols and codes" translate="no">​</a></h2>
<p>RF protocol encoders and device code sets live outside Home Assistant in the <a href="https://github.com/home-assistant-libs/rf-protocols" target="_blank" rel="noopener noreferrer" class=""><code>rf-protocols</code></a> library. Common protocols and well-known device codes should be contributed there. For niche or proprietary protocols, a separate third-party library can also be used.</p>
<p>For full details, see the <a class="" href="https://developers.home-assistant.io/docs/core/entity/radio-frequency">radio frequency entity documentation</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Registering custom dashboard strategies]]></title>
            <link>https://developers.home-assistant.io/blog/2026/04/21/registering-custom-dashboard-strategies</link>
            <guid>https://developers.home-assistant.io/blog/2026/04/21/registering-custom-dashboard-strategies</guid>
            <pubDate>Tue, 21 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[As of Home Assistant 2026.5, you can now register custom dashboard strategies, just as you can with custom cards, making them easier to discover and add using the new dashboard dialog under the Community dashboards section.]]></description>
            <content:encoded><![CDATA[<p>As of Home Assistant 2026.5, you can now register custom dashboard strategies, just as you can with <a class="" href="https://developers.home-assistant.io/docs/frontend/custom-ui/custom-card">custom cards</a>, making them easier to discover and add using the <strong>new dashboard</strong> dialog under the <strong>Community dashboards</strong> section.</p>
<p>Previously, you had to send users to create a blank dashboard, edit in YAML mode, and paste in your custom strategy. Now you can register a friendly name, description, and documentation.</p>
<p>To register your strategy, call <code>window.customStrategies.push()</code> with an object containing the following keys:</p>
<ul>
<li class=""><code>type</code>: The strategy type without the <code>custom:</code> prefix, for example <code>"my-demo"</code>.</li>
<li class=""><code>strategyType</code>: Set to <code>"dashboard"</code> to register a dashboard strategy.</li>
<li class=""><code>name</code>: The friendly name of the strategy.</li>
<li class=""><code>description</code> (<code>optional</code>): A short description of the strategy.</li>
<li class=""><code>documentationURL</code> (<code>optional</code>): A URL to the documentation for the strategy. This is not shown in the strategy UI yet but may in the future.</li>
</ul>
<p>Example:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token dom variable" style="color:rgb(191, 199, 213)">window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">customStrategies</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(191, 199, 213)">window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">customStrategies</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">||</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token dom variable" style="color:rgb(191, 199, 213)">window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">customStrategies</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">push</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"my-demo"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">strategyType</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"dashboard"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"My demo dashboard"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">description</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"A starter dashboard generated from JavaScript."</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">documentationURL</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"https://example.com/my-demo-dashboard"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>This metadata is separate from the custom element itself. Your strategy still needs to be registered with a tag like <code>ll-strategy-dashboard-my-demo</code>, and users still need the resource loaded before Home Assistant can discover it. You can use HACS for this as other resources can be added, like custom cards.</p>
<p>Take a look at the updated <a class="" href="https://developers.home-assistant.io/docs/frontend/custom-ui/custom-strategy">custom strategies</a> documentation with example code and further details.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deprecation of legacy device tracker platform API]]></title>
            <link>https://developers.home-assistant.io/blog/2026/04/20/legacy-device-tracker-deprecation</link>
            <guid>https://developers.home-assistant.io/blog/2026/04/20/legacy-device-tracker-deprecation</guid>
            <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Summary]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://developers.home-assistant.io/blog/2026/04/20/legacy-device-tracker-deprecation#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>The legacy (non-config-entry) device tracker platform API is deprecated and will be removed in the Home Assistant 2027.5 release.
By the end of the 12-month deprecation period, all remaining legacy device tracker platforms will be removed from the core repository, and custom integrations implementing the legacy API will stop working.</p>
<p>Integrations authors need to update integrations to implement the <a href="https://developers.home-assistant.io/docs/core/entity/device-tracker" target="_blank" rel="noopener noreferrer" class="">modern device tracker platform API</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="background">Background<a href="https://developers.home-assistant.io/blog/2026/04/20/legacy-device-tracker-deprecation#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background" translate="no">​</a></h2>
<p>Config entry device trackers were introduced in May 2019, which means integration authors have had 8 years to migrate integrations when support is removed in May 2027.</p>
<p>As of today (April 2026) most widely used core device tracker integrations have already been migrated.</p>
<p>Note that the most popular integration that has not yet been migrated, xiaomi_miio, has a wide mix of functionality including other things than device tracker.</p>
<p>The proposal to deprecate the legacy device tracker API was approved in <a href="https://github.com/home-assistant/architecture/discussions/1375" target="_blank" rel="noopener noreferrer" class="">architecture proposal 1375</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="list-of-core-integrations-sorted-by-reported-use">List of core integrations, sorted by reported use<a href="https://developers.home-assistant.io/blog/2026/04/20/legacy-device-tracker-deprecation#list-of-core-integrations-sorted-by-reported-use" class="hash-link" aria-label="Direct link to List of core integrations, sorted by reported use" title="Direct link to List of core integrations, sorted by reported use" translate="no">​</a></h3>
<p>The list was generated from <a href="https://analytics.home-assistant.io/" target="_blank" rel="noopener noreferrer" class="">https://analytics.home-assistant.io/</a> in March 2026</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">Integration                    Installations  API      Type               Details</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">----------------------------------------------------------------------------------------------------</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">mobile_app                           415,204  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">mqtt                                 233,161  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">zha                                  126,903  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ibeacon                               89,099  modern   unknown            BaseTrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">fritz                                 42,934  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ping                                  33,439  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">unifi                                 33,136  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">xiaomi_miio                           12,866  legacy   scanner            async_scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">nmap_tracker                           7,397  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">icloud                                 5,772  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">freebox                                5,312  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">asuswrt                                4,686  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">tile                                   4,212  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">renault                                3,646  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">private_ble_device                     3,231  modern   unknown            BaseTrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">keenetic_ndms2                         3,080  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">owntracks                              3,022  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">snmp                                   2,923  legacy   scanner            async_scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">devolo_home_network                    2,910  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">tesla_fleet                            2,798  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">netgear                                2,782  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">mikrotik                               2,761  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">tplink_omada                           2,708  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">starlink                               2,250  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">tractive                               2,144  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">volvo                                  2,077  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">husqvarna_automower                    1,924  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">tessie                                 1,562  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bluetooth_le_tracker                   1,011  legacy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">traccar_server                           978  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">huawei_lte                               827  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">gpslogger                                813  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">teslemetry                               720  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">traccar                                  609  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">luci                                     590  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">subaru                                   502  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">mysensors                                474  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">starline                                 460  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">geofency                                 443  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">google_maps                              389  legacy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">locative                                 378  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">opnsense                                 355  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">fing                                     266  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ruckus_unleashed                         232  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">synology_srm                             193  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">unifi_direct                             190  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">mqtt_json                                182  legacy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">vodafone_station                         166  modern   scanner            ScannerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">xiaomi                                   143  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">demo                                     141  legacy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ubus                                     111  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bt_smarthub                               95  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">aprs                                      93  legacy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">nrgkick                                   81  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ddwrt                                     79  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">fressnapf_tracker                         74  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">linksys_smart                             69  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">fortios                                   53  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">swisscom                                  51  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">tomato                                    45  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">quantum_gateway                           42  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">aruba                                     24  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">meraki                                    24  legacy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">sky_hub                                   22  legacy   scanner            async_scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">ituran                                    19  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">cisco_ios                                 10  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">upc_connect                               10  legacy   scanner            async_scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">cisco_mobility_express                     6  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">arris_tg2492lg                             2  legacy   scanner            async_scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bbox                                       1  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">actiontec                                  0  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">autoskope                                  0  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">bt_home_hub_5                              0  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">cppm_tracker                               0  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">fleetgo                                    0  legacy</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">hitron_coda                                0  legacy   scanner            scan_devices</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">lojack                                     0  modern   tracker            TrackerEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">thomson                                    0  legacy   scanner            scan_devices</span><br></div></code></pre></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Standard event type for doorbell event entities]]></title>
            <link>https://developers.home-assistant.io/blog/2026/04/15/doorbell-standard-event-type</link>
            <guid>https://developers.home-assistant.io/blog/2026/04/15/doorbell-standard-event-type</guid>
            <pubDate>Wed, 15 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Doorbell event entities now have a standard ring event type. Integrations that use EventDeviceClass.DOORBELL must include DoorbellEventType.RING in their event_types list.]]></description>
            <content:encoded><![CDATA[<p>Doorbell event entities now have a standard <code>ring</code> event type. Integrations that use <code>EventDeviceClass.DOORBELL</code> must include <code>DoorbellEventType.RING</code> in their <code>event_types</code> list.</p>
<p>See the <a href="https://github.com/home-assistant/architecture/discussions/1363" target="_blank" rel="noopener noreferrer" class="">architecture discussion</a> for the full background.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why">Why<a href="https://developers.home-assistant.io/blog/2026/04/15/doorbell-standard-event-type#why" class="hash-link" aria-label="Direct link to Why" title="Direct link to Why" translate="no">​</a></h2>
<p>Previously, each integration used its own string for the "doorbell was pressed" event — <code>ding</code>, <code>ring</code>, <code>doorbell_chime</code>, <code>single_press</code>, etc. This inconsistency made it impossible to build generic doorbell automations that work across all integrations.</p>
<p>The new <code>DoorbellEventType.RING</code> standard event type solves this by ensuring every doorbell integration fires a common <code>ring</code> event when the doorbell is pressed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-to-do">What to do<a href="https://developers.home-assistant.io/blog/2026/04/15/doorbell-standard-event-type#what-to-do" class="hash-link" aria-label="Direct link to What to do" title="Direct link to What to do" translate="no">​</a></h2>
<p>Import <code>DoorbellEventType</code> from <code>homeassistant.components.event</code> and include <code>DoorbellEventType.RING</code> in your doorbell entity's <code>event_types</code>. Fire it whenever the doorbell is pressed:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">event </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> DoorbellEventType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> EventDeviceClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> EventEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyDoorbellEvent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">EventEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _attr_device_class </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> EventDeviceClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">DOORBELL</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _attr_event_types </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">DoorbellEventType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">RING</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">@callback</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">_async_handle_event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Handle the doorbell press event."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_trigger_event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">DoorbellEventType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">RING</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_write_ha_state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>Additional custom event types (e.g., <code>double_press</code>, <code>long_press</code>) are still allowed alongside the standard <code>ring</code> type.</p>
<p>Doorbell entities that do not include <code>DoorbellEventType.RING</code> will log a deprecation warning and will <strong>stop working in Home Assistant 2027.4</strong>.</p>
<p>For full details, see the <a class="" href="https://developers.home-assistant.io/docs/core/entity/event">event entity documentation</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Entity IDs with mismatched domains are deprecated]]></title>
            <link>https://developers.home-assistant.io/blog/2026/04/07/entity-id-mismatched-domain-deprecated</link>
            <guid>https://developers.home-assistant.io/blog/2026/04/07/entity-id-mismatched-domain-deprecated</guid>
            <pubDate>Tue, 07 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Integrations that set entity_id directly on an entity will now be validated]]></description>
            <content:encoded><![CDATA[<p>Integrations that set <code>entity_id</code> directly on an entity will now be validated
to ensure the domain portion matches the platform's domain. For example,
a <code>light</code> entity must use <code>light.my_light</code>, not <code>cover.my_light</code>.</p>
<p>Setting an entity ID with the wrong domain will log a deprecation warning
and will <strong>stop working in Home Assistant 2027.5</strong>.</p>
<p>In most cases, integrations should not set <code>entity_id</code> at all — Home Assistant
will generate it automatically.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Migrating app builds to Docker BuildKit]]></title>
            <link>https://developers.home-assistant.io/blog/2026/04/02/builder-migration</link>
            <guid>https://developers.home-assistant.io/blog/2026/04/02/builder-migration</guid>
            <pubDate>Thu, 02 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The legacy home-assistant/builder container and the old home-assistant/builder GitHub Action have been retired. We recommend migrating all GitHub workflows and Dockerfiles for apps (formerly add-ons) as described in this post.]]></description>
            <content:encoded><![CDATA[<p>The legacy <code>home-assistant/builder</code> container and the old <code>home-assistant/builder</code> GitHub Action have been retired. We recommend migrating all GitHub workflows and Dockerfiles for apps (formerly add-ons) as described in this post.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-changed-and-why">What changed and why<a href="https://developers.home-assistant.io/blog/2026/04/02/builder-migration#what-changed-and-why" class="hash-link" aria-label="Direct link to What changed and why" title="Direct link to What changed and why" translate="no">​</a></h2>
<p>The old builder ran every architecture build inside a single privileged Docker-in-Docker container using QEMU emulation. This was slow, required elevated privileges, and those who were already familiar with Docker needed to learn how to use the custom Home Assistant's builder container. The old builder also had unnecessary maintenance overhead. Today, what the builder does can be fully replaced with Docker BuildKit, which is natively supported on GitHub Actions runners and has built-in multi-arch support with QEMU emulation if needed.</p>
<p>For your CI, the replacement is a set of focused <a href="https://github.com/home-assistant/builder" target="_blank" rel="noopener noreferrer" class="">composite GitHub Actions</a> that delegate building to the runner's native Docker with Docker BuildKit. Outside the CI, the migration means that your <code>Dockerfile</code> is now the single source of truth for building your app image, and you can use <code>docker build</code> directly to build and test your app locally without needing to use the builder container.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-process">Migration process<a href="https://developers.home-assistant.io/blog/2026/04/02/builder-migration#migration-process" class="hash-link" aria-label="Direct link to Migration process" title="Direct link to Migration process" translate="no">​</a></h2>
<p>The migration has two parts: updating your Dockerfiles and updating your GitHub Actions workflows.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="update-dockerfiles">Update Dockerfiles<a href="https://developers.home-assistant.io/blog/2026/04/02/builder-migration#update-dockerfiles" class="hash-link" aria-label="Direct link to Update Dockerfiles" title="Direct link to Update Dockerfiles" translate="no">​</a></h3>
<p>The new build workflow doesn't use <code>build.yaml</code> anymore. Move the content into your <code>Dockerfile</code> as follows:</p>
<ul>
<li class="">
<p><strong><code>build_from</code></strong> - replace the <code>build_from</code> key in <code>build.yaml</code> with a <code>FROM</code> statement in your <code>Dockerfile</code>:</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">FROM ghcr.io/home-assistant/base:latest</span><br></div></code></pre></div></div>
<p>As the base images are now published as multi-platform manifests, there is usually no need to define per-arch base images anymore. The <code>build-image</code> action still supplies <code>BUILD_ARCH</code> as a build argument though, so you can use that in your <code>Dockerfile</code> if you need to use it in the template for the base image name.</p>
</li>
<li class="">
<p><strong><code>labels</code></strong> - move any custom Docker labels directly into your <code>Dockerfile</code> with a <code>LABEL</code> statement:</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">LABEL \</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    org.opencontainers.image.title="Your awesome app" \</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    org.opencontainers.image.description="Description of your app." \</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    org.opencontainers.image.source="https://github.com/your/repo" \</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    org.opencontainers.image.licenses="Apache License 2.0"</span><br></div></code></pre></div></div>
<p>If you are creating a custom workflow, note that the legacy builder used to add the <code>io.hass.type</code>, <code>io.hass.name</code>, <code>io.hass.description</code>, and <code>io.hass.url</code> labels automatically. The new actions do not infer these values, so add them explicitly via the <code>labels</code> input of the <code>build-image</code> (or similar) action.</p>
</li>
<li class="">
<p><strong><code>args</code></strong> - move custom build arguments into your <code>Dockerfile</code> as <code>ARG</code> definitions with default values:</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">ARG MY_BUILD_ARG="default-value"</span><br></div></code></pre></div></div>
<p>Default values in <code>ARG</code> replace what was previously supplied via <code>build.yaml</code>'s <code>args</code> dictionary. They can still be overridden at build time with <code>--build-arg</code> if needed.</p>
</li>
</ul>
<p>With the content of <code>build.yaml</code> migrated, you can delete the file from your repository.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="update-github-actions-workflows">Update GitHub Actions workflows<a href="https://developers.home-assistant.io/blog/2026/04/02/builder-migration#update-github-actions-workflows" class="hash-link" aria-label="Direct link to Update GitHub Actions workflows" title="Direct link to Update GitHub Actions workflows" translate="no">​</a></h3>
<p>Remove any workflow steps using <code>home-assistant/builder@master</code> and replace them with the new composite actions. See the <a href="https://github.com/home-assistant/apps-example/blob/main/.github/workflows/builder.yaml" target="_blank" rel="noopener noreferrer" class="">example workflow</a> in our example app repository for a complete working example. Alternatively, use the <a href="https://github.com/home-assistant/builder?tab=readme-ov-file#example-workflow" target="_blank" rel="noopener noreferrer" class="">individual actions</a> in a more custom workflow as needed.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="image-naming">Image naming<a href="https://developers.home-assistant.io/blog/2026/04/02/builder-migration#image-naming" class="hash-link" aria-label="Direct link to Image naming" title="Direct link to Image naming" translate="no">​</a></h3>
<p>The preferred way to reference a published app image is now the <strong>generic (multi-arch) name</strong> without an architecture prefix:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># config.yaml</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"ghcr.io/my-org/my-app"</span><br></div></code></pre></div></div>
<p>The <code>{arch}</code> placeholder (e.g. <code>ghcr.io/my-org/{arch}-my-app</code>) is still supported as a compatibility fallback, but it's encouraged to use the generic name and let the manifest handle the platform resolution.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-builds">Local builds<a href="https://developers.home-assistant.io/blog/2026/04/02/builder-migration#local-builds" class="hash-link" aria-label="Direct link to Local builds" title="Direct link to Local builds" translate="no">​</a></h3>
<p>After updating your <code>Dockerfile</code>, you can use <code>docker build</code> to build the app image directly - you can refer to <a class="" href="https://developers.home-assistant.io/docs/apps/testing">Local app testing</a> for more details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="apps-built-locally-by-supervisor">Apps built locally by Supervisor<a href="https://developers.home-assistant.io/blog/2026/04/02/builder-migration#apps-built-locally-by-supervisor" class="hash-link" aria-label="Direct link to Apps built locally by Supervisor" title="Direct link to Apps built locally by Supervisor" translate="no">​</a></h2>
<p>For backward compatibility, Supervisor still reads <code>build.yaml</code> file if it's present and populates the image build arguments with values read from this file. This will produce warnings and eventually be removed in the future, so it's recommended to migrate to the new Dockerfile-based approach as described above.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New infrared entity platform for IR device integrations]]></title>
            <link>https://developers.home-assistant.io/blog/2026/03/30/infrared-entity-platform</link>
            <guid>https://developers.home-assistant.io/blog/2026/03/30/infrared-entity-platform</guid>
            <pubDate>Mon, 30 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Home Assistant now has an infrared entity platform that decouples IR emitter hardware from the devices they control. Instead of each device integration talking directly to specific IR hardware, emitter integrations (like esphome) expose InfraredEntity instances, and device integrations (like lg_infrared) send commands through them via helper functions.]]></description>
            <content:encoded><![CDATA[<p>Home Assistant now has an <code>infrared</code> entity platform that decouples IR emitter hardware from the devices they control. Instead of each device integration talking directly to specific IR hardware, emitter integrations (like <code>esphome</code>) expose <code>InfraredEntity</code> instances, and device integrations (like <code>lg_infrared</code>) send commands through them via helper functions.</p>
<p>See the <a href="https://github.com/home-assistant/architecture/discussions/1316" target="_blank" rel="noopener noreferrer" class="">architecture discussion</a> for the full background.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="architecture">Architecture<a href="https://developers.home-assistant.io/blog/2026/03/30/infrared-entity-platform#architecture" class="hash-link" aria-label="Direct link to Architecture" title="Direct link to Architecture" translate="no">​</a></h2>
<p>The infrared domain sits between two types of integrations:</p>
<ul>
<li class=""><strong>Emitter integrations</strong> (ESPHome, Broadlink, …) implement the <code>InfraredEntity</code> base class to provide hardware-specific IR transmission.</li>
<li class=""><strong>Consumer integrations</strong> (LG, Samsung, Daikin, …) use helper functions to send device-specific IR commands through available emitters.</li>
</ul>
<p>Users select which emitter to use during the consumer integration's config flow.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="implementing-an-emitter-integration">Implementing an emitter integration<a href="https://developers.home-assistant.io/blog/2026/03/30/infrared-entity-platform#implementing-an-emitter-integration" class="hash-link" aria-label="Direct link to Implementing an emitter integration" title="Direct link to Implementing an emitter integration" translate="no">​</a></h2>
<p>Emitter integrations provide the <code>infrared</code> platform by subclassing <code>InfraredEntity</code> and implementing <code>async_send_command</code>. The command's <code>get_raw_timings()</code> method returns protocol-agnostic timing data that the hardware can transmit:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">infrared </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> InfraredCommand</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> InfraredEntity</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyInfraredEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">InfraredEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""My IR transmitter."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">async_send_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> InfraredCommand</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Send an IR command."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        timings </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            interval</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> timing </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get_raw_timings</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> interval </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">timing</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">high_us</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain">timing</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">low_us</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_device</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">transmit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            carrier_frequency</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">modulation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            timings</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">timings</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>The raw protocol-agnostic timings should be converted to the specific format required by the hardware.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="building-a-consumer-integration">Building a consumer integration<a href="https://developers.home-assistant.io/blog/2026/03/30/infrared-entity-platform#building-a-consumer-integration" class="hash-link" aria-label="Direct link to Building a consumer integration" title="Direct link to Building a consumer integration" translate="no">​</a></h2>
<p>Consumer integrations control IR devices by sending commands through an emitter entity. They don't interact with IR hardware directly.</p>
<p><strong>1. Declare the dependency</strong> in <code>manifest.json</code>:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  "dependencies": ["infrared"]</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></div></code></pre></div></div>
<p><strong>2. Let the user pick an emitter</strong> in the config flow:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> infrared</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">emitters </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> infrared</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_get_emitters</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">not</span><span class="token plain"> emitters</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_abort</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">reason</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"no_emitters"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p><strong>3. Send IR commands</strong> using the helper function and the <a href="https://github.com/home-assistant-libs/infrared-protocols" target="_blank" rel="noopener noreferrer" class=""><code>infrared-protocols</code></a> library:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> infrared_protocols</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">codes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">lg</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">tv </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> LGTVCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> make_lg_tv_command</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> infrared</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> infrared</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_send_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_infrared_entity_id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    make_lg_tv_command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">LGTVCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">VOLUME_UP</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    context</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ir-protocols-and-codes">IR protocols and codes<a href="https://developers.home-assistant.io/blog/2026/03/30/infrared-entity-platform#ir-protocols-and-codes" class="hash-link" aria-label="Direct link to IR protocols and codes" title="Direct link to IR protocols and codes" translate="no">​</a></h2>
<p>IR protocol encoders and device code sets live outside Home Assistant in the <a href="https://github.com/home-assistant-libs/infrared-protocols" target="_blank" rel="noopener noreferrer" class=""><code>infrared-protocols</code></a> library. Common protocols (NEC, Samsung, etc.) and well-known device codes should be contributed there. For niche or proprietary protocols, a separate third-party library can also be used.</p>
<p>For full details, see the <a class="" href="https://developers.home-assistant.io/docs/core/entity/infrared">infrared entity documentation</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Frontend component updates 2026.4]]></title>
            <link>https://developers.home-assistant.io/blog/2026/03/25/frontend-component-updates-2026.4</link>
            <guid>https://developers.home-assistant.io/blog/2026/03/25/frontend-component-updates-2026.4</guid>
            <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[We do not officially support or encourage custom card developers to use our built in components. This component APIs can always change and you should build your card as independent component.]]></description>
            <content:encoded><![CDATA[<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>We do not officially support or encourage custom card developers to use our built in components. This component APIs can always change and you should build your card as independent component.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ha-input">ha-input<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-component-updates-2026.4#ha-input" class="hash-link" aria-label="Direct link to ha-input" title="Direct link to ha-input" translate="no">​</a></h2>
<p>We keep migrating our Material Design based components to Web Awesome based. This time we migrated the input components, which leads to an API change but the look and feel stays the same for now.</p>
<ul>
<li class=""><code>ha-input</code> is the successor of <code>ha-textfield</code>
<ul>
<li class=""><code>ha-textfield</code> API stays but the component is migrated to use <code>ha-input</code> internally and will be removed in 2026.5</li>
<li class="">Also replaces <code>ha-outlined-text-field</code></li>
</ul>
</li>
<li class=""><code>ha-input-search</code> replaces <code>search-input</code> and <code>search-input-outlined</code></li>
<li class=""><code>ha-input-multi</code> replaces <code>ha-multi-textfield</code></li>
<li class=""><code>ha-input-copy</code> replaces <code>copy-textfield</code></li>
</ul>
<p>This component also introduces new semantic theme variables for form backgrounds:</p>
<div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token variable" style="color:rgb(191, 199, 213)">--ha-color-form-background</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">var</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">--ha-color-neutral-95</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token variable" style="color:rgb(191, 199, 213)">--ha-color-form-background-hover</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">var</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">--ha-color-neutral-90</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token variable" style="color:rgb(191, 199, 213)">--ha-color-form-background-disabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">var</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token variable" style="color:rgb(191, 199, 213)">--ha-color-neutral-80</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="date-picker">Date picker<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-component-updates-2026.4#date-picker" class="hash-link" aria-label="Direct link to Date picker" title="Direct link to Date picker" translate="no">​</a></h2>
<p>We finally removed the Vue 2 dependency by replacing the date and date range picker with <a href="https://wicky.nillia.ms/cally/" target="_blank" rel="noopener noreferrer" class="">Cally</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Frontend new way of dialogs]]></title>
            <link>https://developers.home-assistant.io/blog/2026/03/25/frontend-dialogs</link>
            <guid>https://developers.home-assistant.io/blog/2026/03/25/frontend-dialogs</guid>
            <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The Problem]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-problem">The Problem<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-dialogs#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Each dialog managed by the dialog manager was only opened once and stayed in the DOM for the lifetime of the application. This causes:</p>
<ul>
<li class=""><strong>More memory usage</strong>: Dialogs accumulate in the DOM even when not visible</li>
<li class=""><strong>More bugs because of missing state reset</strong>: Dialog state persists between opens, leading to stale data or unexpected behavior</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution-dialogmixin">The Solution: DialogMixin<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-dialogs#the-solution-dialogmixin" class="hash-link" aria-label="Direct link to The Solution: DialogMixin" title="Direct link to The Solution: DialogMixin" translate="no">​</a></h2>
<p>We implemented a new way of handling dialogs using <code>DialogMixin</code>. With this approach:</p>
<ul>
<li class=""><strong>Dialogs are created when opened and destroyed when closed</strong>: No need to manually reset the state of the dialog when it is closed</li>
<li class=""><strong>Closed events are automatically handled</strong>: The dialog mixin takes care of cleanup</li>
<li class=""><strong>Subscribe mixin can now be used in dialogs</strong>: Since dialogs are properly destroyed, subscriptions are cleaned up automatically</li>
<li class=""><strong>Use normal Lit lifecycle methods</strong>: Use <code>connectedCallback</code> to initialize when the dialog is opened instead of relying on the <code>showDialog</code> method</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example">Example<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-dialogs#example" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no">​</a></h2>
<p>Check out <code>ha-dialog-date-picker</code> for a reference implementation. <code>DialogMixin</code> adds dialog params to <code>this.params</code> if available.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Frontend lazy context]]></title>
            <link>https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context</link>
            <guid>https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context</guid>
            <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[What is a context?]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-a-context">What is a context?<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context#what-is-a-context" class="hash-link" aria-label="Direct link to What is a context?" title="Direct link to What is a context?" translate="no">​</a></h2>
<p>In the Home Assistant frontend, a <a href="https://lit.dev/docs/data/context/" target="_blank" rel="noopener noreferrer" class="">Context</a> is a way to share data across the component tree without explicitly passing it through every level as a property. Instead of threading the <code>hass</code> object down through multiple layers of components, you can provide specific pieces of data via context and consume them only where needed.</p>
<p>The key benefits of using context over passing the entire <code>hass</code> object are:</p>
<ul>
<li class=""><strong>Easier usage</strong>: Components can directly consume the data they need without requiring parent components to pass it down. This reduces prop drilling and makes components more self-contained and reusable.</li>
<li class=""><strong>Reducing unnecessary component re-renders</strong>: When a component receives <code>hass</code> as a property, any change to <code>hass</code> triggers a re-render of that component and all its children—even if the component only cares about a small subset of the data. By using context to provide only the specific data a component needs, you ensure that components only re-render when their actual dependencies change, leading to better performance and a more responsive UI.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="introducing-lazycontext">Introducing LazyContext<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context#introducing-lazycontext" class="hash-link" aria-label="Direct link to Introducing LazyContext" title="Direct link to Introducing LazyContext" translate="no">​</a></h2>
<p>We've introduced a new <code>LazyContext</code> pattern that should replace the traditional subscription-based approach and the usage of the <code>SubscribeMixin</code>. Previously, components would subscribe to data sources and manage subscription lifecycles manually, often leading to boilerplate code and potential memory leaks if subscriptions weren't properly cleaned up.</p>
<p><code>LazyContext</code> simplifies this by:</p>
<ul>
<li class=""><strong>Lazy loading</strong>: Data is only fetched when a component actually consumes the context</li>
<li class=""><strong>Automatic cleanup</strong>: Subscriptions are managed automatically</li>
<li class=""><strong>Shared state</strong>: Multiple components consuming the same context share a single subscription</li>
<li class=""><strong>Optimized re-renders</strong>: Only components that consume the context re-render when data changes</li>
</ul>
<p>This approach centralizes data-fetching logic and makes it easier to reason about when and how data flows through your application.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="examples">Examples<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context#examples" class="hash-link" aria-label="Direct link to Examples" title="Direct link to Examples" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="defining-a-lazycontext">Defining a LazyContext<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context#defining-a-lazycontext" class="hash-link" aria-label="Direct link to Defining a LazyContext" title="Direct link to Defining a LazyContext" translate="no">​</a></h3>
<p>To define a lazy context, use <code>LazyContextProvider</code> and provide a fetch function:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">LazyContextProvider</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">this</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  context</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> labelsContext</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(130, 170, 255)">subscribeFn</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">connection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> setValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">subscribeLabelRegistry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">connection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> setValue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="consuming-a-context-with-lit">Consuming a context with lit<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context#consuming-a-context-with-lit" class="hash-link" aria-label="Direct link to Consuming a context with lit" title="Direct link to Consuming a context with lit" translate="no">​</a></h3>
<p>To consume a context in a component, use the <code>@consume</code> decorator:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token decorator at operator" style="color:rgb(137, 221, 255)">@</span><span class="token decorator function" style="color:rgb(130, 170, 255)">state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(137, 221, 255)">@</span><span class="token decorator function" style="color:rgb(130, 170, 255)">consume</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> context</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> labelsContext</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> subscribe</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> _labels</span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> LabelRegistryEntry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>Check out the updated custom card example to use it in vanilla JS: <a class="" href="https://developers.home-assistant.io/docs/frontend/custom-ui/custom-card#defining-your-card">Custom card example</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-transform-for-derived-data">Using @transform for derived Data<a href="https://developers.home-assistant.io/blog/2026/03/25/frontend-lazy-context#using-transform-for-derived-data" class="hash-link" aria-label="Direct link to Using @transform for derived Data" title="Direct link to Using @transform for derived Data" translate="no">​</a></h3>
<p><em>Only available within the home-assistant frontend codebase</em></p>
<p>The <code>@transform</code> decorator allows you to derive data from a context value, ensuring your component only re-renders when the transformed value actually changes.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token decorator at operator" style="color:rgb(137, 221, 255)">@</span><span class="token decorator function" style="color:rgb(130, 170, 255)">state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(137, 221, 255)">@</span><span class="token decorator function" style="color:rgb(130, 170, 255)">consume</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> context</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> statesContext</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> subscribe</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(137, 221, 255)">@</span><span class="token decorator function" style="color:rgb(130, 170, 255)">transform</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(130, 170, 255)">transformer</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">this</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> HuiButtonCard</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> entityStates</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> HassEntities</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">this</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_config</span><span class="token operator" style="color:rgb(137, 221, 255)">?.</span><span class="token plain">entity </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> entityStates</span><span class="token operator" style="color:rgb(137, 221, 255)">?.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token keyword" style="font-style:italic">this</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">_config</span><span class="token operator" style="color:rgb(137, 221, 255)">?.</span><span class="token plain">entity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">undefined</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  watch</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">"_config"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> _stateObj</span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> HassEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>With <code>@transform</code>, even if the full states object updates, your component will only re-render if the transformed result (<code>_stateObj</code>) actually changes. The <code>watch</code> option allows you to specify additional properties that should trigger re-evaluation of the transformer function—in this case, when <code>_config</code> changes, the transformer runs again to extract the correct entity state.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Backup agents can now report upload progress]]></title>
            <link>https://developers.home-assistant.io/blog/2026/03/11/backup-upload-progress</link>
            <guid>https://developers.home-assistant.io/blog/2026/03/11/backup-upload-progress</guid>
            <pubDate>Wed, 11 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The BackupAgent.asyncuploadbackup method now receives a new on_progress callback parameter. Backup agents can call this callback periodically during upload to report the number of bytes uploaded so far:]]></description>
            <content:encoded><![CDATA[<p>The <code>BackupAgent.async_upload_backup</code> method now receives a new <code>on_progress</code> callback parameter. Backup agents can call this callback periodically during upload to report the number of bytes uploaded so far:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ExampleBackupAgent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">BackupAgent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">async_upload_backup</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">*</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        open_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Callable</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Coroutine</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">Any</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Any</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> AsyncIterator</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token builtin" style="color:rgb(130, 170, 255)">bytes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        backup</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> AgentBackup</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        on_progress</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> OnProgressCallback</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">**</span><span class="token plain">kwargs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Any</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Upload a backup."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        bytes_uploaded </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> chunk </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> open_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> do_upload</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            bytes_uploaded </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">len</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            on_progress</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">bytes_uploaded</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">bytes_uploaded</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><br></div></code></pre></div></div>
<p>The backup manager uses these progress reports to fire <code>UploadBackupEvent</code> events, enabling the frontend to display real-time upload progress to the user.</p>
<p>Check the <a class="" href="https://developers.home-assistant.io/docs/core/platform/backup#backup-agents">backup agent documentation</a> for more details.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Custom integrations can now ship their own brand images]]></title>
            <link>https://developers.home-assistant.io/blog/2026/02/24/brands-proxy-api</link>
            <guid>https://developers.home-assistant.io/blog/2026/02/24/brands-proxy-api</guid>
            <pubDate>Tue, 24 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Starting with Home Assistant 2026.3, custom integrations can include their own brand images (icons and logos) directly in the integration directory. No more submitting to a separate repository — just drop your images in a brand/ folder and they show up in the UI.]]></description>
            <content:encoded><![CDATA[<p>Starting with Home Assistant 2026.3, custom integrations can include their own brand images (icons and logos) directly in the integration directory. No more submitting to a separate repository — just drop your images in a <code>brand/</code> folder and they show up in the UI.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-brand-images-for-custom-integrations">Local brand images for custom integrations<a href="https://developers.home-assistant.io/blog/2026/02/24/brands-proxy-api#local-brand-images-for-custom-integrations" class="hash-link" aria-label="Direct link to Local brand images for custom integrations" title="Direct link to Local brand images for custom integrations" translate="no">​</a></h2>
<p>Add a <code>brand/</code> directory to your custom integration with your icon and logo files:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">custom_components/my_integration/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── __init__.py</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">├── manifest.json</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">└── brand/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    ├── icon.png</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    └── logo.png</span><br></div></code></pre></div></div>
<p>The following image filenames are supported:</p>
<ul>
<li class=""><code>icon.png</code> / <code>dark_icon.png</code></li>
<li class=""><code>logo.png</code> / <code>dark_logo.png</code></li>
<li class=""><code>icon@2x.png</code> / <code>dark_icon@2x.png</code></li>
<li class=""><code>logo@2x.png</code> / <code>dark_logo@2x.png</code></li>
</ul>
<p>Local brand images automatically take priority over images from the brands CDN. That's it — no extra configuration needed.</p>
<p>For more details, see the <a class="" href="https://developers.home-assistant.io/docs/creating_integration_file_structure#local-brand-images-for-custom-integrations">integration file structure documentation</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="brand-images-now-served-through-a-local-api">Brand images now served through a local API<a href="https://developers.home-assistant.io/blog/2026/02/24/brands-proxy-api#brand-images-now-served-through-a-local-api" class="hash-link" aria-label="Direct link to Brand images now served through a local API" title="Direct link to Brand images now served through a local API" translate="no">​</a></h2>
<p>To make local brand images possible, all brand images are now served through the Home Assistant local API instead of being fetched directly from the CDN by the browser.</p>
<p>A new <code>brands</code> system integration proxies brand images through two endpoints:</p>
<ul>
<li class=""><code>/api/brands/integration/{domain}/{image}</code> — Integration icons and logos</li>
<li class=""><code>/api/brands/hardware/{category}/{image}</code> — Hardware images</li>
</ul>
<p>Images are cached locally on disk and served with a stale-while-revalidate strategy, so they remain available during internet outages.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="impact-on-the-frontend">Impact on the frontend<a href="https://developers.home-assistant.io/blog/2026/02/24/brands-proxy-api#impact-on-the-frontend" class="hash-link" aria-label="Direct link to Impact on the frontend" title="Direct link to Impact on the frontend" translate="no">​</a></h3>
<p>The <code>brandsUrl()</code> and <code>hardwareBrandsUrl()</code> helpers in <code>src/util/brands-url.ts</code> now return local API paths instead of CDN URLs. If your custom card or panel uses these helpers, no changes are needed.</p>
<p>If you are constructing brand image URLs manually, update them:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Old</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">https://brands.home-assistant.io/_/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string interpolation">domain</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string string" style="color:rgb(195, 232, 141)">/icon.png</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// New</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> brandsUrl </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"../util/brands-url"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">brandsUrl</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> domain</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> type</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"icon"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>These endpoints require authentication. The <code>brandsUrl()</code> helper handles this automatically by appending an access token. If you construct URLs manually, obtain a token via the <code>brands/access_token</code> WebSocket command and append it as a <code>token</code> query parameter.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Remove deprecated light features]]></title>
            <link>https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features</link>
            <guid>https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features</guid>
            <pubDate>Mon, 23 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Summary of changes]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary-of-changes">Summary of changes<a href="https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features#summary-of-changes" class="hash-link" aria-label="Direct link to Summary of changes" title="Direct link to Summary of changes" translate="no">​</a></h3>
<p>In October 2022, Home Assistant migrated the preferred color temperature unit from mired to kelvin.</p>
<p>In <a class="" href="https://developers.home-assistant.io/blog/2024/02/12/light-color-mode-mandatory">February 2024</a>, Home Assistant requested explicit <code>supported_color_modes</code> and <code>color_mode</code> properties (triggering deprecation of legacy fallback color mode support).</p>
<p>In <a class="" href="https://developers.home-assistant.io/blog/2024/12/14/kelvin-preferred-color-temperature-unit">December 2024</a>, Home Assistant requested explicit Kelvin support (triggering deprecation of mired support).</p>
<p>It is now time to clean up the legacy code and remove the corresponding attributes, constants and properties:</p>
<ul>
<li class="">Remove deprecated <code>ATTR_COLOR_TEMP</code>, <code>ATTR_MIN_MIREDS</code>, <code>ATTR_MAX_MIREDS</code>, <code>ATTR_KELVIN</code>, <code>COLOR_MODE_***</code>, and <code>SUPPORT_***</code> constants</li>
<li class="">Remove deprecated state attributes <code>ATTR_COLOR_TEMP</code>, <code>ATTR_MIN_MIREDS</code> and <code>ATTR_MAX_MIREDS</code></li>
<li class="">Remove deprecated support for <code>ATTR_KELVIN</code> and <code>ATTR_COLOR_TEMP</code> arguments from the <code>light.turn_on</code> service call</li>
<li class="">Remove deprecated support for <code>LightEntity.color_temp</code>, <code>LightEntity.min_mireds</code> and <code>LightEntity.max_mireds</code> properties from the entity</li>
<li class="">Remove deprecated support for <code>LightEntity._attr_color_temp</code>, <code>LightEntity._attr_min_mireds</code> and <code>LightEntity._attr_max_mireds</code> shorthand attributes from the entity</li>
</ul>
<p>Additionally, failing to provide valid <code>supported_color_modes</code> and <code>color_mode</code> properties no longer works and will raise an error.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="examples">Examples<a href="https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features#examples" class="hash-link" aria-label="Direct link to Examples" title="Direct link to Examples" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="custom-minimummaximum-color-temperature">Custom minimum/maximum color temperature<a href="https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features#custom-minimummaximum-color-temperature" class="hash-link" aria-label="Direct link to Custom minimum/maximum color temperature" title="Direct link to Custom minimum/maximum color temperature" translate="no">​</a></h4>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyLight</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">LightEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Representation of a light."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Old</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># _attr_min_mireds = 200 # 5000K</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># _attr_max_mireds = 400 # 2500K</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># New</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _attr_min_color_temp_kelvin </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2500</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># 400 mireds</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _attr_max_color_temp_kelvin </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">5000</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># 200 mireds</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="default-minimummaximum-color-temperature">Default minimum/maximum color temperature<a href="https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features#default-minimummaximum-color-temperature" class="hash-link" aria-label="Direct link to Default minimum/maximum color temperature" title="Direct link to Default minimum/maximum color temperature" translate="no">​</a></h4>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">light </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> DEFAULT_MAX_KELVIN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> DEFAULT_MIN_KELVIN</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyLight</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">LightEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Representation of a light."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Old did not need to have _attr_min_mireds / _attr_max_mireds set</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># New needs to set the default explicitly</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _attr_min_color_temp_kelvin </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> DEFAULT_MIN_KELVIN</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    _attr_max_color_temp_kelvin </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> DEFAULT_MAX_KELVIN</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="dynamic-minimummaximum-color-temperature">Dynamic minimum/maximum color temperature<a href="https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features#dynamic-minimummaximum-color-temperature" class="hash-link" aria-label="Direct link to Dynamic minimum/maximum color temperature" title="Direct link to Dynamic minimum/maximum color temperature" translate="no">​</a></h4>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">util </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> color </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> color_util</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyLight</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">LightEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Representation of a light."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Old</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># def min_mireds(self) -&gt; int:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     """Return the coldest color_temp that this light supports."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     return device.coldest_temperature</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># def max_mireds(self) -&gt; int:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     """Return the warmest color_temp that this light supports."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     return device.warmest_temperature</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># New</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">min_color_temp_kelvin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">int</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Return the warmest color_temp that this light supports."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> color_util</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">color_temperature_mired_to_kelvin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">device</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">warmest_temperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">max_color_temp_kelvin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">int</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Return the coldest color_temp that this light supports."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> color_util</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">color_temperature_mired_to_kelvin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">device</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">coldest_temperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="checking-color-temperature-in-service-call">Checking color temperature in service call<a href="https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features#checking-color-temperature-in-service-call" class="hash-link" aria-label="Direct link to Checking color temperature in service call" title="Direct link to Checking color temperature in service call" translate="no">​</a></h4>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">light </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> ATTR_COLOR_TEMP_KELVIN</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">util </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> color </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> color_util</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyLight</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">LightEntity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Representation of a light."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">turn_on</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">**</span><span class="token plain">kwargs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Any</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Turn on the light."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Old</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># if ATTR_COLOR_TEMP in kwargs:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     color_temp_mired = kwargs[ATTR_COLOR_TEMP]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     color_temp_kelvin = color_util.color_temperature_mired_to_kelvin(color_temp_mired)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Old</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># if ATTR_KELVIN in kwargs:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     color_temp_kelvin = kwargs[ATTR_KELVIN]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#     color_temp_mired = color_util.color_temperature_kelvin_to_mired(color_temp_kelvin)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># New</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> ATTR_COLOR_TEMP_KELVIN </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> kwargs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            color_temp_kelvin </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> kwargs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">ATTR_COLOR_TEMP_KELVIN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            color_temp_mired </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> color_util</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">color_temperature_kelvin_to_mired</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">color_temp_kelvin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="background-information">Background information<a href="https://developers.home-assistant.io/blog/2026/02/23/remove-deprecate-light-features#background-information" class="hash-link" aria-label="Direct link to Background information" title="Direct link to Background information" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://community.home-assistant.io/t/wth-is-light-temperature-not-in-kelvin/467449/6" target="_blank" rel="noopener noreferrer" class="">Community discussion about Kelvin temperature</a></li>
<li class=""><a href="https://github.com/home-assistant/core/pull/79591" target="_blank" rel="noopener noreferrer" class="">Core PR #79591: Migration to Kelvin</a></li>
<li class=""><a href="https://github.com/home-assistant/architecture/discussions/564" target="_blank" rel="noopener noreferrer" class="">Architecture discussion #564</a></li>
<li class=""><a class="" href="https://developers.home-assistant.io/docs/core/entity/light#color-modes">Color modes documentation</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Changes in OAuth 2.0 helper error handling]]></title>
            <link>https://developers.home-assistant.io/blog/2026/02/19/oauth-token-request-error-handling</link>
            <guid>https://developers.home-assistant.io/blog/2026/02/19/oauth-token-request-error-handling</guid>
            <pubDate>Thu, 19 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Summary of changes]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary-of-changes">Summary of changes<a href="https://developers.home-assistant.io/blog/2026/02/19/oauth-token-request-error-handling#summary-of-changes" class="hash-link" aria-label="Direct link to Summary of changes" title="Direct link to Summary of changes" translate="no">​</a></h2>
<p>Starting as of <code>2026.3</code>, we're enhancing how the OAuth 2.0 helper handles token request and refresh token failures. This change makes error handling more robust, decoupled from the aiohttp library and helps integrations, that utilize the <a href="https://developers.home-assistant.io/docs/integration_fetching_data/#coordinated-single-api-poll-for-data-for-all-entities" target="_blank" rel="noopener noreferrer" class="">Data Update Coordinator</a>, to automatically trigger the right error handling.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-changes">What changes<a href="https://developers.home-assistant.io/blog/2026/02/19/oauth-token-request-error-handling#what-changes" class="hash-link" aria-label="Direct link to What changes" title="Direct link to What changes" translate="no">​</a></h2>
<p>When an OAuth 2.0 token request or token refresh failed, Home Assistant would allow the underlying <code>aiohttp.ClientResponseError</code> to propagate directly to the integration. This behavior is being changed and enhanced.</p>
<p>We're introducing three new exceptions that provide clearer semantics:</p>
<ul>
<li class=""><code>OAuth2TokenRequestTransientError</code> - Recoverable errors, that can be retried.</li>
<li class=""><code>OAuth2TokenRequestReauthError</code> - Non-recoverable errors, that require a reauthentication.</li>
<li class=""><code>OAuth2TokenRequestError</code> - Base exception for when the above two criteria aren't met or to enable the integration to catch all token request exceptions.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="data-update-coordinator">Data Update Coordinator<a href="https://developers.home-assistant.io/blog/2026/02/19/oauth-token-request-error-handling#data-update-coordinator" class="hash-link" aria-label="Direct link to Data Update Coordinator" title="Direct link to Data Update Coordinator" translate="no">​</a></h3>
<p>Most integrations that use the OAuth 2.0 helper, also use the Data Update Coordinator. When a token request or refresh token fails, the exceptions will bubble up in the Data Update Coordinator and now triggers the following error handling:</p>
<p>For unrecoverable errors (400+, except 429 (rate limit)):</p>
<ul>
<li class=""><code>OAuth2TokenRequestReauthError</code>: Data Update Coordinator raises <code>ConfigEntryAuthFailed</code> if exceptions should be raised or starts a reauthentication flow.</li>
</ul>
<p>For transient errors (500+ and 429):</p>
<ul>
<li class=""><code>OAuth2TokenRequestTransientError</code>: Data Update Coordinator treats it as an <code>UpdateFailed</code> and the retry mechanism will be triggered.</li>
</ul>
<p>This means that integrations that use the OAuth 2.0 helper in combination with the Data Update Coordinator don’t need to do any special handling of the new exceptions.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration">Migration<a href="https://developers.home-assistant.io/blog/2026/02/19/oauth-token-request-error-handling#migration" class="hash-link" aria-label="Direct link to Migration" title="Direct link to Migration" translate="no">​</a></h3>
<p>Integrations that today use the OAuth 2.0 helper and handle <code>aiohttp.ClientResponseError</code> explicitly should adjust their error handling to deal with the new exceptions. To ease this transition, we have added a compatibility layer by having the new OAuth exceptions inherit from <code>aiohttp.ClientResponseError</code>. Existing code that catches this exception type should continue to work. It is however encouraged to refactor the code to use the new exceptions. See the code example for details.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="code-example-of-migration">Code example of migration<a href="https://developers.home-assistant.io/blog/2026/02/19/oauth-token-request-error-handling#code-example-of-migration" class="hash-link" aria-label="Direct link to Code example of migration" title="Direct link to Code example of migration" translate="no">​</a></h4>
<p>Update the exception handling and then continue to work out if it's a (non-)recoverable error in the integration. For example:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">try</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> auth</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_get_access_token</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">except</span><span class="token plain"> OAuth2TokenRequestReauthError </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> err</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">raise</span><span class="token plain"> ConfigEntryAuthFailed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            translation_domain</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">DOMAIN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> translation_key</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"reauth_required"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> err</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">except</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">OAuth2TokenRequestError</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> ClientError</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> err</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">raise</span><span class="token plain"> ConfigEntryNotReady</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            translation_domain</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">DOMAIN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> translation_key</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"auth_server_error"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> err</span><br></div></code></pre></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reconfiguration support for webhook helper]]></title>
            <link>https://developers.home-assistant.io/blog/2026/02/18/reconfiguration-support-for-webhook-helper</link>
            <guid>https://developers.home-assistant.io/blog/2026/02/18/reconfiguration-support-for-webhook-helper</guid>
            <pubDate>Wed, 18 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Integrations that use the webhook config flow helper (homeassistant.helpers.configentryflow.registerwebhookflow) now support reconfiguration. This allows the integration to retrieve the webhook again, or obtain an updated webhook when the Home Assistant instance URL changes.]]></description>
            <content:encoded><![CDATA[<p>Integrations that use the webhook config flow helper (<code>homeassistant.helpers.config_entry_flow.register_webhook_flow</code>) now support reconfiguration. This allows the integration to retrieve the webhook again, or obtain an updated webhook when the Home Assistant instance URL changes.</p>
<p>Custom integrations using the webhook config flow helper must add translation strings for the reconfiguration flow.</p>
<p><strong>Example translation strings for a reconfiguration flow:</strong></p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  "config": {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    "abort": {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      "reconfigure_successful": "**Reconfiguration was successful**\n\nIn Sleep as Android go to *Settings → Services → Automation → Webhooks* and update the webhook with the following URL:\n\n`{webhook_url}`"</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    },</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    "step": {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      "reconfigure": {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        "description": "Are you sure you want to re-configure the Sleep as Android integration?",</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        "title": "Reconfigure Sleep as Android"</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      }</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>For more details, see <a href="https://github.com/home-assistant/core/pull/151729" target="_blank" rel="noopener noreferrer" class="">core PR #151729</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[async_listen in Labs is deprecated]]></title>
            <link>https://developers.home-assistant.io/blog/2026/02/16/labs-async-listen-deprecation</link>
            <guid>https://developers.home-assistant.io/blog/2026/02/16/labs-async-listen-deprecation</guid>
            <pubDate>Mon, 16 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The asynclisten helper in the labs integration has been deprecated in favor of asyncsubscribepreviewfeature.]]></description>
            <content:encoded><![CDATA[<p>The <code>async_listen</code> helper in the <code>labs</code> integration has been deprecated in favor of <code>async_subscribe_preview_feature</code>.</p>
<p>The new <code>async_subscribe_preview_feature</code> function provides a more consistent API, where the listener callback receives an <code>EventLabsUpdatedData</code> parameter containing the updated feature state. This eliminates the need to separately call <code>async_is_preview_feature_enabled</code> inside the listener to check the current value.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="old-usage">Old usage<a href="https://developers.home-assistant.io/blog/2026/02/16/labs-async-listen-deprecation#old-usage" class="hash-link" aria-label="Direct link to Old usage" title="Direct link to Old usage" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">labs </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> async_is_preview_feature_enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> async_listen</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">my_listener</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> async_is_preview_feature_enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> DOMAIN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"my_feature"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># feature enabled</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">async_listen</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    domain</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">DOMAIN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    preview_feature</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"my_feature"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    listener</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">my_listener</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-usage">New usage<a href="https://developers.home-assistant.io/blog/2026/02/16/labs-async-listen-deprecation#new-usage" class="hash-link" aria-label="Direct link to New usage" title="Direct link to New usage" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> homeassistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">labs </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> EventLabsUpdatedData</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> async_subscribe_preview_feature</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">my_listener</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">event_data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> EventLabsUpdatedData</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> event_data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">"enabled"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># feature enabled</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">async_subscribe_preview_feature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    hass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    domain</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">DOMAIN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    preview_feature</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"my_feature"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    listener</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">my_listener</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>Note that the new listener is a coroutine function and receives <code>EventLabsUpdatedData</code> as a parameter.</p>
<p><code>async_listen</code> will be removed in Home Assistant 2027.3.</p>
<p>For more details, see <a href="https://github.com/home-assistant/core/pull/162648" target="_blank" rel="noopener noreferrer" class="">core PR #162648</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Replacing pre-commit with prek]]></title>
            <link>https://developers.home-assistant.io/blog/2026/01/13/replace-pre-commit-with-prek</link>
            <guid>https://developers.home-assistant.io/blog/2026/01/13/replace-pre-commit-with-prek</guid>
            <pubDate>Tue, 13 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[By replacing pre-commit with prek we can increase the performance of our checks. Prek uses the same .pre-commit-config.yaml as pre-commit and is a complete replacement. Due to the fact that prek is written in Rust and allows the execution of different jobs in parallel, we can check our code even faster.]]></description>
            <content:encoded><![CDATA[<p>By replacing <code>pre-commit</code> with <a href="https://prek.j178.dev/" target="_blank" rel="noopener noreferrer" class=""><code>prek</code></a> we can increase the performance of our checks. Prek uses the same <code>.pre-commit-config.yaml</code> as <code>pre-commit</code> and is a complete replacement. Due to the fact that <code>prek</code> is written in Rust and allows the execution of different jobs in parallel, we can check our code even faster.</p>
<p>New development environments will automatically install <code>prek</code> and for existing ones please just update the test requirements by running <code>uv pip install requirements_test.txt</code></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Solving pyserial-asyncio blocking the event loop]]></title>
            <link>https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast</link>
            <guid>https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast</guid>
            <pubDate>Mon, 05 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Summary of changes]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary-of-changes">Summary of changes<a href="https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast#summary-of-changes" class="hash-link" aria-label="Direct link to Summary of changes" title="Direct link to Summary of changes" translate="no">​</a></h3>
<p>Starting in <code>2026.7</code>, installation of <code>pyserial-asyncio</code> will be blocked in Home Assistant.</p>
<p>Library maintainers and custom integrations are advised to migrate to <code>pyserial-asyncio-fast</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="background">Background<a href="https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background" translate="no">​</a></h3>
<p><code>pyserial-asyncio</code> blocks the event loop because it does a blocking <code>sleep</code>. The library is also not maintained so efforts to improve the situation haven't been released.</p>
<p><code>pyserial-asyncio-fast</code> was created as a drop-in replacement (see <a href="https://github.com/home-assistant-libs/pyserial-asyncio-fast" target="_blank" rel="noopener noreferrer" class="">the repository</a>), and all core integrations have now been migrated.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration">Migration<a href="https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast#migration" class="hash-link" aria-label="Direct link to Migration" title="Direct link to Migration" translate="no">​</a></h3>
<p><code>pyserial-asyncio-fast</code> was designed as a drop-in replacement of <code>pyserial-asyncio</code>, and the necessary changes are trivial.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="requirements">Requirements<a href="https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast#requirements" class="hash-link" aria-label="Direct link to Requirements" title="Direct link to Requirements" translate="no">​</a></h4>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Old</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  install_requires</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"pyserial-asyncio"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># New</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  install_requires</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"pyserial-asyncio-fast"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="usage">Usage<a href="https://developers.home-assistant.io/blog/2026/01/05/pyserial-asyncio-fast#usage" class="hash-link" aria-label="Direct link to Usage" title="Direct link to Usage" translate="no">​</a></h4>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Old</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> serial_asyncio</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">connect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    conn </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> serial_asyncio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">open_serial_connection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">**</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">serial_settings</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># New</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> serial_asyncio_fast</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">connect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    conn </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">await</span><span class="token plain"> serial_asyncio_fast</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">open_serial_connection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">**</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">serial_settings</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></div></code></pre></div></div>
<p>More examples are available in <a href="https://github.com/home-assistant/core/pull/116635" target="_blank" rel="noopener noreferrer" class="">the tracking pull request</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing description placeholders for service action translations]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/27/service-translation-placeholders</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/27/service-translation-placeholders</guid>
            <pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[It is now possible to use translation placeholders for (custom) service actions.]]></description>
            <content:encoded><![CDATA[<p>It is now possible to use translation placeholders for (custom) service actions.</p>
<p>The <a class="" href="https://developers.home-assistant.io/docs/core/integration-quality-scale/rules/action-setup?_highlight=hass.services.async_register#example-implementation">service action example</a> now shows how to supply the available description placeholders during the registration of the service action.</p>
<p>Move URLs from service descriptions and translation strings into description placeholders.</p>]]></content:encoded>
        </item>
    </channel>
</rss>