As part of an effort to improve performance and simplify the core job API, async_add_hass_job
is deprecated and will be removed from Home Assistant in 2025.5.
Calls should be replaced with async_run_hass_job
instead.
As part of an effort to improve performance and simplify the core job API, async_add_hass_job
is deprecated and will be removed from Home Assistant in 2025.5.
Calls should be replaced with async_run_hass_job
instead.
By replacing pip
with uv
in our production images, our build pipeline (and therefore releasing a new version) is a lot faster.
Uv
is an extremely fast Python package installer and resolver written in Rust. It is developed by Astral and it's open source. Check it out on GitHub.
In the following table, you can see that we can save around 5 hours of execution time on each build.
Arch | Pip | UV | Savings |
---|---|---|---|
aarch64 | 1h 24m 53s | 5m 18s | ~1h 20m |
armhf | 1h 52m 20s | 6m 2s | ~1h 46m |
armv7 | 1h 26m 43s | 5m 28s | ~1h 21m |
amd64 | 22m 10s | 3m 20s | ~19m |
i386 | 17m 37s | 3m 11s | ~14m |
On average, we run the build pipeline 43 times as we create
In total, we save around 215 hours per month. With this massive improvement, we can now ship hotfixes even faster, as the pipeline to ship a new version now takes around 20 minutes instead of 2.5 hours.
The 215 monthly saved execution hours can be used by other jobs and make the CI experience for all developers and our community better.
By replacing pip
with uv
, we improve our sustainability by using fewer resources to build our images.
A big thank you to Astral for developing this amazing tool. Please check out their website and products as they offer, for example, a "lightning" fast linter/formatter for Python too.
As of Home Assistant 2024.5, we deprecate the use of hass.helpers
.
Using hass.helpers
will issue a warning in the logs.
Authors of custom integrations are encouraged to update their code
to prevent any issues before Home Assistant 2024.11.
Starting from Home Assistant 2024.11, hass.helpers
will be removed and will no longer work.
Integrations that use hass.helpers
should be updated to import the functions and classes directly
from the integration package and pass the hass
object as first parameter.
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
async def async_setup(hass: HomeAssistant, config):
"""Set up the component."""
client = async_get_clientsession(hass)
from homeassistant.core import HomeAssistant
async def async_setup(hass: HomeAssistant, config):
"""Set up the component."""
client = hass.helpers.aiohttp_client.async_get_clientsession()
As of Home Assistant Core 2024.4, config entries can now be reconfigured by adding a reconfigure
step in their config flows.
This is not to replace the optional configuration (OptionsFlow
) but instead to allow the user to change the setup configuration after a config entry has been created.
The reconfigure
step does not replace a reauth
step and they have different purposes.
Reauthentication should be started automatically by the integration in the case of a login/token/etc. is invalidated, so the user has an option to adjust those settings.
Reconfiguration is started by the user from the config entry options menu and should be implemented to update config entry data which are not optional for the integration to work. Authentication issues are handled with a re-authentication flow. (See reauthentication).
Examples could be changing the latitude and longitude of a WeatherEntity
when moving between homes or having a mobile home, changing the communication port of a local device, etc.
To implement the reconfigure
step, include it in your config flow as:
import voluptuous as vol
class ExampleConfigFlow(ConfigFlow, domain=DOMAIN):
"""Config flow for Example integration."""
async def async_step_reconfigure(self, user_input: dict[str, Any] | None = None):
"""Add reconfigure step to allow to reconfigure a config entry."""
if user_input is not None:
pass # TODO: process user input
return self.async_show_form(
step_id="reconfigure",
data_schema=vol.Schema({vol.Required("password"): str}),
)
The State
object is now always updated and an event is always fired when an integration sets the state of an entity, regardless of any change to the state or a state attribute. This is implemented by adding a new timestamp, State.last_reported
and a new event state_reported
.
The state_reported
event is fired in large volume, and must be used with care to avoid detrimental effects on system load:
state_reported
is fired.state_reported
events for all entities.state_reported
, an event_filter
must be used to screen out events for other entities.state_reported
, the run_immediately
flag must be set.Home Assistant previously discarded state writes where neither the state nor the state attributes were changed, unless the integration set the force_update
flag. This behavior made it very difficult for integrations to correctly do time series analysis of numerical sensor state. It also meant the user didn't know if an integration is updating a sensor or not.
The new timestamp and associated event were discussed in architecure discussion #1062.
The following APIs have breaking changes:
time_fired
argument for hass.bus.async_fire
now accepts a float
timestamp instead of a datetime
object.hass.bus.async_listen
has changed.time_fired: datetime | None
argument for Event()
has been replaced with time_fired_timestamp: float | None
.last_reported: datetime
has been added to State()
in the middle of the argument list.For more details, see core PR #113511
and core PR #113798
.
Translation support applies to HomeAssistantError
and subclasses like ServiceValidationError
. When a translation_domain
and translation_key
is set and the error message is added in strings.json
, it is no longer needed to add the error message string for the local logging. Home Assistant will automatically fetch the English error message from the translation cache.
When raising HomeAssistantError
or a subclass with translation support we should remove the log message from the argument list to enable it to be fetched from the translation cache.
For example:
async def async_select_index(hass: HomeAssistant, index: int) -> None:
"""Setup the config entry for my device."""
try:
check_index(index)
except ValueError as exc:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="invalid_index",
translation_placeholders={
"index": index,
"expected": expected,
},
) from exc
The error message is placed in strings.json
:
{
...
"exceptions": {
"invalid_index": {
"message": "An invalid index is selected, expected: {expected}, got: {index}"
}
}
}
async_run_job
and async_add_job
are deprecated and will be removed in Home Assistant 2025.4. This deprecation does not apply to the sync API add_job
method, which is not planned to be removed.
Instead, it's more efficient to use one of the other job methods, as the method of calling the job does not ever have to be worked out:
If the callable is a coroutine function running from a config entry:
entry.async_create_background_task
, entry.async_create_task
If the callable is a coroutine function running from another place:
hass.async_create_background_task
, hass.async_create_task
If the callable should run in the executor:
hass.async_add_executor_job
As of Home Assistant Core 2024.4 we have deprecated the auxiliary heater functionality in ClimateEntity
.
Integrations that are currently implementing the is_aux_heat
property and the turn_aux_heat_on
/turn_aux_heat_off
methods need to remove these and alternatively implement other entities to accommodate the necessary functionality such as a SwitchEntity
or in the case of a read-only property a BinarySensorEntity
.
You can read more about this decision here.
Starting from Home Assistant 2024.4, all integrations are imported in the executor to avoid blocking the event loop while the code is imported and executed.
In the rare event that an integration creates loop-bound objects at import time, this may fail because there is no running loop in the executor.
Custom integrations needing more time to adjust their code to avoid creating such objects can opt-out and continue to have their code imported in the event loop, understanding that system stability will be impacted.
To opt-out of importing in the executor, an integration can add:
"import_executor": false
to their manifest.json
The method for integrations to provide translations for states of its entities under other integrations, for example to translate an integration's sensors was changed in November 2022, and support for the old method will be removed in Home Assistant Core 2024.5.0.
Once Home Assistant Core 2024.5.0 is released, integrations can no longer use custom device classes together with a strings.<platform name>.json
file. Instead, entities must set the translation_key
property on an entity and include that translation_key
in the integration's strings.json
.
The following example strings.json
is for a Moon domain sensor
entity with its translation_key
property set to phase
:
{
"entity": {
"sensor": {
"phase": {
"state": {
"new_moon": "New moon",
"first_quarter": "First quarter",
"full_moon": "Full moon",
"last_quarter": "Last quarter"
}
}
}
}
}
For more details, see the translation
and entity
documentation.