Skip to main content

Device tracker TrackerEntity location accuracy attribute type change

· One min read

The type of location_accuracy attribute (short hand _attr_location_accuracy) of the TrackerEntity class of the device_tracker entity component has been changed from int to float.

Type conversions in case the source value is a float are no longer needed.

Example

class ExampleTrackerEntity(TrackerEntity):
"""Test tracker entity."""

_attr_location_accuracy: float = 2.5

@cached_property
def location_accuracy(self) -> float:
"""Return the location accuracy of the device.

Value in meters.
"""
return self._attr_location_accuracy

Searching in media players

· One min read

Media players can now allow users to search through the media, by adding MediaEntityFeature.SEARCH_MEDIA and implementing async_search_media. The users can filter the search result by a search query and a list of MediaClasses that the returned results should have. For more info, see the updated documentation.

UnitSystem dataclass is now frozen

· One min read

UnitSystem class is changed to a frozen data class, and all instances derived from it are now frozen.

The following unit systems that derived from the UnitSystem class are now frozen:

  • METRIC_SYSTEM
  • US_CUSTOMARY_SYSTEM

The reason for this change is that Unit systems are constants that should not be modified. An integration that modifies these constants can break unit conversions and create undesired output for other components of Home Assistant.

With a frozen data class an attempt to modify the UnitSystem constant will fail:

dataclasses.FrozenInstanceError: cannot assign to field 'temperature_unit'

This change was introduced in the home assistant core PR #140954.

Changes to ConfigSubentryFlow

· One min read

ConfigSubentryFlow._reconfigure_entry_id has been renamed to ConfigSubentryFlow._entry_id and ConfigSubentryFlow._get_reconfigure_entry has been renamed to ConfigSubentryFlow._get_entry.

The reason for the change is that both sub entry user flows and subentry reconfigure flows need access to parent config entry, e.g. getting options, data, etc.

Custom integrations which call either of the renamed methods need to update their implementations.

The change is introduced in the home assistant core PR #141017.

Media player toggle action changed

· One min read

The implementation of the toggle action service has been adjusted in the media player base class. The media player will now be turned on if it is in the states off or standby; in all other states, it will be turned off.

Before this change, the media player would also be turned on if it was in state idle. This was not in line with the meaning of the idle state, as it is counted as a state where the device is already turned on.

Custom integrations which have overridden the async_toggle may need to update their implementations.

The change is introduced in the home assistant core PR #78192.

New checks for config flow unique ID

· One min read

Summary of changes

Creating a config entry with a unique ID already present in the registry is deprecated, and will now log a warning.

Details

When a config flow creates an entry with a colliding unique ID, the old entry is currently automatically removed and replaced with the new config entry. This can lead to unexpected behavior, and integrations should be adjusted to instead abort the flow.

In case of manual flows, integrations should implement options, reauth, reconfigure to allow the user to change settings. In case of non user visible flows, the integration should optionally update the existing entry before aborting.

More details can be found in the config flow documentation.

Changed config entry state transitions

· 2 min read

Config entry state transitions when unloading and removing entries has been modified:

  • A new state ConfigEntryState.UNLOAD_IN_PROGRESS is added, which is set before calling the integration's async_unload_entry
    Rationale:

    • Make it easier to write cleanup code which should run after the last config entry has been unloaded
    • Improve debugging of issues related to reload and unload of config entries
  • The config entry state is set to ConfigEntryState.FAILED_UNLOAD when the integration's async_unload_entry returns False
    Rationale:

    • If async_unload_entry returns False, we can't assume the integration is still loaded, most likely it has partially unloaded itself, especially considering this is the pattern we recommend:
    async def async_unload_entry(hass: HomeAssistant, entry: MyConfigEntry) -> bool:
    """Unload a config entry."""
    # async_unload_platforms returns False if at least one platform did not unload
    if (unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS)):
    entry.runtime_data.listener()
    # Finish cleanup not related to platforms
    return unload_ok
  • The config entry is removed from hass.config_entries before calling the integration's async_remove_entry is called
    Rationale:

    • Make it easier to write cleanup code which should run after the last config entry has been removed

Custom integration authors need to review and update their integrations' async_unload_entry and async_remove_entry if needed. The most common pattern which requires an update is this:

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
loaded_entries = [
entry
for entry in hass.config_entries.async_entries(DOMAIN)
if entry.state is ConfigEntryState.LOADED
]
if len(loaded_entries) == 1:
# The last config entry is being unloaded, release shared resources, unregister services etc.
...

This can now be simplified, if the custom integration's minimum Home Assistant version is set to 2025.3.0:

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
if not hass.config_entries.async_loaded_entries(DOMAIN):
# The last config entry is being unloaded, release shared resources, unregister services etc.
...

If the custom integration needs to be backwards compatible with previous releases of Home Assistant Core:

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
other_loaded_entries = [
_entry
for _entry in hass.config_entries.async_loaded_entries(DOMAIN)
if _entry.entry_id != entry.entry_id
]
if not other_loaded_entries:
# The last config entry is being unloaded, release shared resources, unregister services etc.
...

Check the config entry documentation, and the home assistant core PR #138522 for additional background.

Backup agents

· One min read

In the January release of 2025, we introduced a new feature for backups called backup agents.

Previously, backup platforms were used only to pause or prepare integration operations before creating a backup and to execute a post-backup operation. With the introduction of backup agents, the backup platform now allows integrations to add one or more backup agents that can upload backups to some local or remote location.

The first integration to implement a backup agent was the Home Assistant Cloud integration. In the February release of 2025, three more integrations implemented backup agents: Google Drive, OneDrive and Synology DSM. If you are an integration author, and want to add support for your favorite backup location, you can find more information on how to implement backup agents in the developer documentation.

Support for config subentries

· One min read

Config entries now have a new data type called “config subentry”. Config subentries are owned by a config entry and set up as part of async_setup_entry. Config subentries are created by config subentry flows and updated by config subentry reconfigure flows. This works similarly to how we create/edit config entries.

This makes it easier for integration authors to allow users to add, modify and remove pieces of configuration which share some common resource, for example a cloud account or an MQTT broker.

The architecture discussion gives more background.