<?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>Tue, 24 Feb 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[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"><span class="token-line" style="color:#bfc7d5"><span class="token plain">custom_components/my_integration/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├── __init__.py</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├── manifest.json</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">└── brand/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    ├── icon.png</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    └── logo.png</span><br></span></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"><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span></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"><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span></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"><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span></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"><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span></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"><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span></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"><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span></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"><span class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "config": {</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    "abort": {</span><br></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    "step": {</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "reconfigure": {</span><br></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        "title": "Reconfigure Sleep as Android"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      }</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></span></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"><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></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"><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></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"><span 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></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><br></span></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"><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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></span><span 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></span></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>
        <item>
            <title><![CDATA[Serialization of Store data in worker thread is now opt-in]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/25/storage-helper-opt-in-serialize-in-executor</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/25/storage-helper-opt-in-serialize-in-executor</guid>
            <pubDate>Tue, 25 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The Store class from homeassistant/helpers/storage.py accepts a new constructor argument serializeinevent_loop]]></description>
            <content:encoded><![CDATA[<p>The <code>Store</code> class from <code>homeassistant/helpers/storage.py</code> accepts a new constructor argument <code>serialize_in_event_loop</code></p>
<p>If <code>serialize_in_event_loop</code> is <code>True</code> (the default):</p>
<ul>
<li class="">The <code>data_func</code> passed to <code>Store.async_delay_save</code> is called from the event loop</li>
<li class="">Data produced by <code>data_func</code> passed to <code>Store.async_delay_save</code> is serialized to JSON in the event loop</li>
<li class="">Data passed to <code>Store.async_save</code> is serialized to JSON in the event loop</li>
</ul>
<p>If <code>serialize_in_event_loop</code> is <code>False</code>:</p>
<ul>
<li class="">The <code>data_func</code> passed to <code>Store.async_delay_save</code> is called from a separate thread, which means it must be thread safe and must not access the hass object</li>
<li class="">Data produced by <code>data_func</code> passed to <code>Store.async_delay_save</code> is serialized to JSON in a separate thread, which means it must be thread safe</li>
<li class="">Data passed to <code>Store.async_save</code> is serialized to JSON in a separate thread, which means it must be thread safe</li>
</ul>
<p>The behavior has changed; <code>data_func</code> passed to <code>Store.async_delay_save</code> was previously always called from a separate thread and data produced by it or data passed to <code>Store.async_save</code> was previously always serialized by a separate thread.</p>
<p>The reason for the change is that it was not documented that <code>data_func</code> would be called by a thread other than the event loop or that JSON serialization would happen in a thread other than the event loop, and the <code>data_func</code> and data produced by it or passed to <code>Store.async_save</code> was generally not thread safe.</p>
<p>For more details, see <a href="https://github.com/home-assistant/core/pull/157158" target="_blank" rel="noopener noreferrer" class="">core PR 157158</a> and <a href="https://github.com/home-assistant/core/pull/157263" target="_blank" rel="noopener noreferrer" class="">core PR 157263</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Add a status callback for MQTT subscriptions]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/23/mqtt-subscribe-wait</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/23/mqtt-subscribe-wait</guid>
            <pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Add a status callback for MQTT subscriptions]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="add-a-status-callback-for-mqtt-subscriptions">Add a status callback for MQTT subscriptions<a href="https://developers.home-assistant.io/blog/2025/11/23/mqtt-subscribe-wait#add-a-status-callback-for-mqtt-subscriptions" class="hash-link" aria-label="Direct link to Add a status callback for MQTT subscriptions" title="Direct link to Add a status callback for MQTT subscriptions" translate="no">​</a></h2>
<p>Integrations that use MQTT might need to wait for a subscription to complete before they initiate actions. The default behavior is that a subscription is queued and debounced, so callers usually do not wait for broker confirmation. Some integrations must guarantee that the broker finished the subscription.</p>
<p>The new <code>mqtt.async_on_subscribe_done</code> helper can be used to monitor MQTT subscriptions, to allow doing additional tasks.
Make sure the same QoS is used as in the MQTT subscription.</p>
<p>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"><span 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"> mqtt</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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_setup_entry</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"> HomeAssistant</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> entry</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> ConfigEntry</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)">bool</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">"""Setup integration MQTT subscription monitoring."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span 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)">_on_subscribe_status</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></span><span 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 subscription ready signal."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Do stuff</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Handle subscription ready status update</span><span class="token plain"></span><br></span><span 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"> mqtt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">async_on_subscribe_done</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">"myintegration/status"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        qos</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        on_subscribe_status</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">_on_subscribe_status</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span 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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Do stuff</span><br></span></code></pre></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Device identification buttons are now classified as diagnostic]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/21/identify-buttons-diagnostic-category</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/21/identify-buttons-diagnostic-category</guid>
            <pubDate>Fri, 21 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Button entities representing a device identification mechanism (using IDENTIFY device class) are now required to have their entity category set to DIAGNOSTIC.]]></description>
            <content:encoded><![CDATA[<p>Button entities representing a device identification mechanism (using <code>IDENTIFY</code> device class) are now required to have their entity category set to <code>DIAGNOSTIC</code>.</p>
<p>For more details on entity category, see <a class="" href="https://developers.home-assistant.io/docs/core/entity/#registry-properties">the documentation</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Labs: Preview features before they become standard]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features</guid>
            <pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[We're excited to announce a new system for shipping preview features in Home Assistant: Labs. Labs provides a standardized way for integrations to offer fully tested features that users can opt into before they become standard, allowing us to gather feedback and refine the design based on real-world usage.]]></description>
            <content:encoded><![CDATA[<p>We're excited to announce a new system for shipping preview features in Home Assistant: <strong>Labs</strong>. Labs provides a standardized way for integrations to offer fully tested features that users can opt into before they become standard, allowing us to gather feedback and refine the design based on real-world usage.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-are-labs-preview-features">What are Labs preview features?<a href="https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features#what-are-labs-preview-features" class="hash-link" aria-label="Direct link to What are Labs preview features?" title="Direct link to What are Labs preview features?" translate="no">​</a></h2>
<p>Labs preview features are different from beta testing. While beta testing evaluates the stability of upcoming Home Assistant releases, Labs is about refining user interfaces and design. Labs features are fully tested and functional, but their design and behavior may still change as we gather real-world usage and feedback. This means they might have breaking changes, be extended with new functionality, or even be removed if they don't work out.</p>
<p>Think of it this way:</p>
<ul>
<li class=""><strong>Beta</strong>: Evaluates the stability of upcoming Home Assistant releases</li>
<li class=""><strong>Labs</strong>: Fully tested features with evolving design and user interface, refined through real-world usage and feedback</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>Integrations declare preview features in their <code>manifest.json</code> with links for feedback, documentation, and issue reporting. Users can then enable these features in <strong>Settings</strong> → <strong>System</strong> → <strong>Labs</strong>, and they activate immediately without requiring a restart. The integration code checks whether a feature is enabled and responds accordingly.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-labs">Why Labs?<a href="https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features#why-labs" class="hash-link" aria-label="Direct link to Why Labs?" title="Direct link to Why Labs?" translate="no">​</a></h2>
<p>Many of our most significant improvements benefit from real-world testing before becoming standard. Labs provides:</p>
<ol>
<li class=""><strong>Structured feedback channels</strong>: Each feature has dedicated URLs for feedback, documentation, and issue reporting</li>
<li class=""><strong>Runtime activation</strong>: Features enable and disable instantly, no configuration updates or restart required</li>
<li class=""><strong>Clear expectations</strong>: Users know they're trying fully tested features whose design may change based on feedback</li>
<li class=""><strong>Iterative development</strong>: Integrate user feedback directly into the development process</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example-kitchen-sink-special-repair">Example: Kitchen Sink special repair<a href="https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features#example-kitchen-sink-special-repair" class="hash-link" aria-label="Direct link to Example: Kitchen Sink special repair" title="Direct link to Example: Kitchen Sink special repair" translate="no">​</a></h2>
<p>The <a href="https://www.home-assistant.io/integrations/kitchen_sink/" target="_blank" rel="noopener noreferrer" class="">Kitchen Sink</a> demo integration includes a working example. When enabled, the "special repair" feature creates a repair issue to demonstrate how Labs features can interact with other Home Assistant integrations. See the <a class="" href="https://developers.home-assistant.io/docs/development/labs#complete-example-kitchen-sink-special-repair">developer documentation</a> for the complete implementation.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-started">Getting started<a href="https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features#getting-started" class="hash-link" aria-label="Direct link to Getting started" title="Direct link to Getting started" translate="no">​</a></h2>
<p>Ready to add a Labs preview feature to your integration? Check out our <a class="" href="https://developers.home-assistant.io/docs/development/labs">comprehensive guide</a> which covers:</p>
<ul>
<li class="">When to use Labs (and when not to)</li>
<li class="">How to define features in your manifest</li>
<li class="">Implementation patterns for backend and frontend features</li>
<li class="">Runtime activation requirements</li>
<li class="">Testing approaches</li>
<li class="">Feature lifecycle (preview → standard or removal)</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-next">What's next?<a href="https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features#whats-next" class="hash-link" aria-label="Direct link to What's next?" title="Direct link to What's next?" translate="no">​</a></h2>
<p>We encourage integration developers to consider Labs for:</p>
<ul>
<li class="">Major UI changes or redesigns</li>
<li class="">Significant architectural changes that benefit from real-world testing</li>
<li class="">Features where user feedback will shape the final design</li>
</ul>
<p>Labs is <strong>not</strong> for:</p>
<ul>
<li class="">Permanent configuration options (use integration options instead)</li>
<li class="">Minor changes that can go directly into releases</li>
<li class="">Features with critical bugs or that are fundamentally incomplete</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it-yourself">Try it yourself<a href="https://developers.home-assistant.io/blog/2025/11/20/labs-preview-features#try-it-yourself" class="hash-link" aria-label="Direct link to Try it yourself" title="Direct link to Try it yourself" translate="no">​</a></h2>
<p>Want to see Labs in action? Install the Kitchen Sink demo integration and enable the "Special repair" feature in Settings → System → Labs. You'll see firsthand how preview features work.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Data Update Coordinator now supports Retry After]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/17/retry-after-update-failed</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/17/retry-after-update-failed</guid>
            <pubDate>Mon, 17 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Integrations using the Data Update Coordinator can enhance the UpdateFailed exception with a new parameter retry_after to defer the next scheduled refresh by a specified number of seconds and then resume the normal cadence once the API has recovered.]]></description>
            <content:encoded><![CDATA[<p>Integrations using 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> can enhance the <code>UpdateFailed</code> exception with a new parameter <code>retry_after</code> to defer the next scheduled refresh by a specified number of seconds and then resume the normal cadence once the API has recovered.</p>
<p>In situations where polling API's would return a sign of being overwhelmed, by throwing an HTTP 429 or providing a <code>Retry-After</code> in the response header, integrations can now honor these backoff signals.
The integration and API client must detect these backoff signals and sanitize the API's desired backoff period. The <code>UpdateFailed</code> exception accepts a <code>retry_after</code> parameter (a float in seconds) to delay the next scheduled refresh. Once the API recovers and <code>UpdateFailed</code> is no longer raised, the integration resumes its normal <code>update_interval</code>.</p>
<p>Example of the usage:</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"><span class="token-line" style="color:#bfc7d5"><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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    request </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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get_information</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></span><span 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"> APIClientRateLimited </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></span><span 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"> UpdateFailed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        retry_after</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">60</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># This can also be retrieved from the API response itself, or provide a default</span><span class="token plain"></span><br></span><span 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></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="configentrynotready">ConfigEntryNotReady<a href="https://developers.home-assistant.io/blog/2025/11/17/retry-after-update-failed#configentrynotready" class="hash-link" aria-label="Direct link to ConfigEntryNotReady" title="Direct link to ConfigEntryNotReady" translate="no">​</a></h4>
<p>The <code>retry_after</code> parameter is ignored during the Update Coordinator setup phase (<code>async_config_entry_first_refresh</code>). If the first refresh fails, Home Assistant raises a <code>ConfigEntryNotReady</code> exception, allowing config entry setup to retry automatically using the built-in retry. Once the coordinator setup succeeds, <code>retry_after</code> applies to following refreshes.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The capability_attributes field removed from CalculatedState]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/10/calculated-state-capability-attributes-removed</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/10/calculated-state-capability-attributes-removed</guid>
            <pubDate>Mon, 10 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The capability_attributes field has been removed from CalculatedState. Capability attributes are still included in all attributes, which remain available in CalculatedState.]]></description>
            <content:encoded><![CDATA[<p>The <code>capability_attributes</code> field has been removed from <code>CalculatedState</code>. Capability attributes are still included in all attributes, which remain available in <code>CalculatedState</code>.</p>
<p><code>CalculatedState</code> is the container with state and attributes returned by <code>Entity._async_calculate_state</code>.</p>
<p>For details, see <a href="https://github.com/home-assistant/core/pull/151672" target="_blank" rel="noopener noreferrer" class="">core PR 151672</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Improved error handling for oauth2 configuration without internet]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/05/config-entry-oauth2-error-handling</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/05/config-entry-oauth2-error-handling</guid>
            <pubDate>Wed, 05 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Integrations using Application Credentials and Configuration via OAuth2 need to update their error handling to correctly handle configuration when the internet is down.]]></description>
            <content:encoded><![CDATA[<p>Integrations using <a href="https://developers.home-assistant.io/docs/core/platform/application_credentials/" target="_blank" rel="noopener noreferrer" class="">Application Credentials</a> and <a href="https://developers.home-assistant.io/docs/config_entries_config_flow_handler/#configuration-via-oauth2" target="_blank" rel="noopener noreferrer" class="">Configuration via OAuth2</a> need to update their error handling to correctly handle configuration when the internet is down.</p>
<p>Currently integrations using configuration via OAuth2 call <code>config_entry_oauth2_flow.async_get_config_entry_implementation</code> in <code>async_setup_entry</code> in their <code>__init__.py</code>. Previously when there was no network, this would raise <code>ValueError: Implementation not available</code>, which was a non-retryable error, resulting in the integration needing to be manually reconfigured after internet was restored (see Issues <a href="https://github.com/home-assistant/core/issues/153956" target="_blank" rel="noopener noreferrer" class="">153956</a> and <a href="https://github.com/home-assistant/core/issues/144582" target="_blank" rel="noopener noreferrer" class="">144582</a>). <a href="https://github.com/home-assistant/core/pull/154579" target="_blank" rel="noopener noreferrer" class="">core PR 154579</a> added <code>config_entry_oauth2_flow.ImplementationUnavailableError</code> and raises it in <code>config_entry_oauth2_flow.async_get_config_entry_implementation</code> when OAuth2 configuration is unavailable because of missing internet. Integrations should catch this error and raise <code>ConfigEntryNotReady</code>.
The changed behavior with the new exception will be released in 2025.12.</p>
<p>Here is an example of the migration,</p>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">-    implementation = await async_get_config_entry_implementation(hass, entry)</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">+    try:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">+        implementation = await async_get_config_entry_implementation(hass, entry)</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">+    except ImplementationUnavailableError as err:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">+        raise ConfigEntryNotReady(</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">+            "OAuth2 implementation temporarily unavailable, will retry"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">+        ) from err</span><br></span></code></pre></div></div>
<p>New integrations will find the correct <code>try</code> / <code>except</code> block generated by <code>python3 -m script.scaffold config_flow_oauth2</code>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TemperatureConverter.convert_interval deprecation]]></title>
            <link>https://developers.home-assistant.io/blog/2025/11/04/convert-interval-deprecation</link>
            <guid>https://developers.home-assistant.io/blog/2025/11/04/convert-interval-deprecation</guid>
            <pubDate>Tue, 04 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The method convert_interval in TemperatureConverter (allowing conversions between °F and °C intervals) has been deprecated in favor of TemperatureDeltaConverter.convert.]]></description>
            <content:encoded><![CDATA[<p>The method <code>convert_interval</code> in <code>TemperatureConverter</code> (allowing conversions between °F and °C intervals) has been deprecated in favor of <code>TemperatureDeltaConverter.convert</code>.
The new converter and device class are now the preferred way to deal with temperature intervals.</p>
<p>For details, see <a href="https://github.com/home-assistant/core/pull/155689" target="_blank" rel="noopener noreferrer" class="">core PR 155689</a> and <a href="https://github.com/home-assistant/core/pull/147358" target="_blank" rel="noopener noreferrer" class="">core PR 147358</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Service translations removed from WebSocket get_services and REST /api/services]]></title>
            <link>https://developers.home-assistant.io/blog/2025/10/24/service-web-api-changes</link>
            <guid>https://developers.home-assistant.io/blog/2025/10/24/service-web-api-changes</guid>
            <pubDate>Fri, 24 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Action translations defined in strings.json are no longer included in responses from the WebSocket get_services command and the REST /api/services endpoint because they were incomplete and the Home Assistant frontend did not use them.]]></description>
            <content:encoded><![CDATA[<p>Action translations defined in <code>strings.json</code> are no longer included in responses from the WebSocket <code>get_services</code> command and the REST <code>/api/services</code> endpoint because they were incomplete and the Home Assistant frontend did not use them.</p>
<p>Legacy, untranslated action names and descriptions from <code>services.yaml</code> remain in both the WebSocket and REST responses.</p>
<p>Fetch complete action translations with the WebSocket command <code>frontend/get_translations</code>.</p>
<p>For details, see <a href="https://github.com/home-assistant/core/pull/147120" target="_blank" rel="noopener noreferrer" class="">core PR 147120</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Changes to the recorder statistics API]]></title>
            <link>https://developers.home-assistant.io/blog/2025/10/16/recorder-statistics-api-changes</link>
            <guid>https://developers.home-assistant.io/blog/2025/10/16/recorder-statistics-api-changes</guid>
            <pubDate>Thu, 16 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The Python and WS APIs for injecting and modifying statistics have changed.]]></description>
            <content:encoded><![CDATA[<p>The Python and WS APIs for injecting and modifying statistics have changed.</p>
<p>The following changes have been made to the WS API:</p>
<ul>
<li class="">The WS command <code>recorder/update_statistics_metadata</code> accepts a <code>unit_class</code> that points to the unit converter used for unit conversions. If there is no compatible unit converter, <code>unit_class</code> should be set to <code>null</code>. Not specifying the <code>unit_class</code> is deprecated and will stop working in Home Assistant Core 2026.11.</li>
<li class="">The <code>metadata</code> object included in the WS command <code>recorder/import_statistics</code> accepts a <code>unit_class</code> that points to the unit converter used for unit conversions. If there is no compatible unit converter, <code>unit_class</code> should be set to <code>null</code>. Not specifying the <code>unit_class</code> is deprecated and will stop working in Home Assistant Core 2026.11.</li>
<li class="">The <code>metadata</code> object included in the WS command <code>recorder/import_statistics</code> accepts a <code>mean_type</code> that specifies the type of mean (<code>0</code> for no mean, <code>1</code> for arithmetic mean, or <code>2</code> for circular mean). The <code>mean_type</code> replaces the bool flag <code>has_mean</code>. Not specifying the <code>mean_type</code> is deprecated and will stop working in Home Assistant Core 2026.11.</li>
<li class="">The items in the response to the WS commands <code>recorder/list_statistic_ids</code> and <code>recorder/get_statistics_metadata</code> have <code>mean_type</code> and <code>unit_class</code>.</li>
<li class="">The <code>has_mean</code> in the items in the response to the WS commands <code>recorder/list_statistic_ids</code> and <code>recorder/get_statistics_metadata</code> is deprecated and will be removed in Home Assistant Core 2026.11.</li>
</ul>
<p>The following changes have been made to the Python API:</p>
<ul>
<li class="">The function <code>async_update_statistics_metadata</code> accepts a <code>new_unit_class</code> that points to the unit converter used for unit conversions. If there is no compatible unit converter, <code>new_unit_class</code> should be set to <code>None</code>. Not specifying the <code>new_unit_class</code> is deprecated and will stop working in Home Assistant Core 2025.11.</li>
<li class="">The metadata object passed to the functions <code>async_import_statistics</code> and <code>async_add_external_statistics</code> accepts a <code>unit_class</code> that points to the unit converter used for unit conversions. If there is no compatible unit converter, <code>unit_class</code> should be set to <code>None</code>. Not specifying the <code>unit_class</code> is deprecated and will stop working in Home Assistant Core 2025.11.</li>
<li class="">The metadata object passed to the functions <code>async_import_statistics</code> and <code>async_add_external_statistics</code> accepts a <code>mean_type</code> of type <code>StatisticMeanType</code> that specifies the type of mean (<code>NONE</code>, <code>ARITHMETIC</code>, or <code>CIRCULAR</code>). The <code>mean_type</code> replaces the bool flag <code>has_mean</code>. Not specifying the <code>mean_type</code> is deprecated and will stop working in Home Assistant Core 2026.11.</li>
<li class="">The items in the return value of the function <code>async_list_statistic_ids</code> have <code>mean_type</code> and <code>unit_class</code>.</li>
<li class="">The <code>has_mean</code> in the items in the return value of the function <code>async_list_statistic_ids</code> is deprecated and will be removed in Home Assistant Core 2026.11.</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Device filter has been removed from target selector]]></title>
            <link>https://developers.home-assistant.io/blog/2025/10/14/device-filter-removed-from-target-selector</link>
            <guid>https://developers.home-assistant.io/blog/2025/10/14/device-filter-removed-from-target-selector</guid>
            <pubDate>Tue, 14 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The device filter option is no longer supported by the target selector and has been removed from the target selector documentation.]]></description>
            <content:encoded><![CDATA[<p>The device filter option is no longer supported by the target selector and has been removed from the <a href="https://www.home-assistant.io/docs/blueprint/selectors/#target-selector" target="_blank" rel="noopener noreferrer" class="">target selector documentation</a>.</p>
<p>Hassfest has been updated to <a href="https://github.com/home-assistant/core/pull/152794" target="_blank" rel="noopener noreferrer" class="">fail on services with device filter on targets</a>.</p>
<p>Validation of target selectors that specify a device filter will fail in Home Assistant Core 2026.11.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="background">Background<a href="https://developers.home-assistant.io/blog/2025/10/14/device-filter-removed-from-target-selector#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background" translate="no">​</a></h3>
<p>Core helpers that extract entities from targets did not support the device filter. When the user picked a floor, area, label, or category, the filter was ignored. The frontend also ignored the device filter when selecting entities for a target.</p>
<p>A review of all core integrations found no correct use of a device filter on target selectors. We removed the device filter from the target selector rather than implement support for it in Core and the frontend.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="impact-on-custom-integrations-and-blueprints">Impact on custom integrations and blueprints<a href="https://developers.home-assistant.io/blog/2025/10/14/device-filter-removed-from-target-selector#impact-on-custom-integrations-and-blueprints" class="hash-link" aria-label="Direct link to Impact on custom integrations and blueprints" title="Direct link to Impact on custom integrations and blueprints" translate="no">​</a></h3>
<p>Update custom integrations and blueprints to remove device filters from target selectors.</p>
<p>If you have a valid use case for device filters on target selectors, reach out on Discord.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Update coordinator now allows retriggering]]></title>
            <link>https://developers.home-assistant.io/blog/2025/10/05/coordinator-retrigger</link>
            <guid>https://developers.home-assistant.io/blog/2025/10/05/coordinator-retrigger</guid>
            <pubDate>Sun, 05 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The update coordinator with debouncer active will now accept a request for an update]]></description>
            <content:encoded><![CDATA[<p>The update coordinator with debouncer active will now accept a request for an update
while an update is currently in progress. The request will be queued up to be performed
after the current update finishes.</p>
<p>Consider the following case:</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"><span class="token-line" style="color:#bfc7d5"><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)">_update</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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    a </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"> get_a</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></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># A: User or other logic request a new update here through async_schedule_update()</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    b </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"> get_b</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></span><span 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 plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<p>A user or code that request an updates at timestamp <code>A</code> expects that the entities linked will
all get new data from that time. However, since we previously ignored that request, entities
would have data for the value of <code>a</code> that is from a time before the update request that was ignored.</p>
<p>To make sure we avoid this case, the update coordinator will now schedule an additional
update, if a request is received while currently executing an update.</p>
<p>A side effect of this is that it is now possible to schedule an update from inside an update
function of the coordinator. That is useful if for example a connection is lost mid update,
and we want all entities to indicate directly as unavailable, yet we want to attempt a
re-connect as quick as possible but do that in the next update cycle.</p>]]></content:encoded>
        </item>
    </channel>
</rss>