Skip to main content

· One min read

It's now possible to provide static values to be used in an entity translation using placeholders. You can pass placeholders via the translation_placeholders property of an entity.

An example sensor:

class TestEntity(SensorEntity):
"""Example entity."""

_attr_has_entity_name = True
_attr_translation_key = "temperature"

def __init__(self) -> None:
"""Initialize example entity."""
self._attr_translation_placeholders = {"channel_id": "2"}
self._attr_device_info = DeviceInfo(
name="Example device"
)

The strings.json file would look like:

{
"entity": {
"sensor": {
"temperature": {
"name": "Temperature channel {channel_id}"
}
}
}
}

The resulting entity would be called Example device Temperature channel 2.

A warning is logged once when a translation placeholder is expected but not provided by the entity. When this happens on a system that is not on a stable version (dev, nightly, or beta), an error will be raised to be able to catch the mistakes quickly.

Please don't forget to be kind towards your translators, as they need to understand what kind of name or value will be passed in from the placeholder name ❤️.

· 2 min read

In Home Assistant 2024.2, we will introduce a new way to provide icons for integrations: Icon translations.

Icon translations work similarly to our regular translations for entities, which can translate the state of an entity or entity attribute state into any language. Icon translations work in a similar way, but instead of translating the state into the end-user language, it translates the state into an icon.

Each integration can now provide an icons.json file, containing a mapping of states to icons. Here is an example of a Moon sensor entity that provides different icons for each state:

{
"entity": {
"sensor": {
"phase": {
"default": "mdi:moon",
"state": {
"new_moon": "mdi:moon-new",
"first_quarter": "mdi:moon-first-quarter",
"full_moon": "mdi:moon-full",
"last_quarter": "mdi:moon-last-quarter"
}
}
}
}
}

Icon translations also support translating entity attribute states.

Read more about icon translations in our documentation.

Service icons

This change is backward-compatible. The existing icon property of entities will continue to work as it did before. However, we recommend the use of the icon translation over the icon property.

Additionally, services provided by integrations now also support icons and can be provided in the same icon translations file. These icons are used in the Home Assistant UI when displaying the service in places like the automation and script editors. The following example shows how to provide icons for the light.turn_on and light.turn_off services:

{
"services": {
"turn_on": "mdi:lightbulb-on",
"turn_off": "mdi:lightbulb-off"
}
}

Read more about service icons in our documentation.

· One min read

Since Home Assistant Core 2022.12, a warning is issued in the logs if a sensor entity that has a device class uses unit of measurement and state class incorrectly, taking their device class into account.

An invalid use would be a sensor entity that has a device class of SensorDeviceClass.TEMPERATURE but uses the unit of measurement % instead of °C or °F; or the state class SensorStateClass.TOTAL instead of SensorStateClass.MEASUREMENT.

There will be a six-month deprecation period to ensure all custom integration authors have time to adjust. As of Home Assistant Core 2024.8, the warning will then be replaced by an exception.

· One min read

FlowHandler.async_show_progress has been updated:

  • The step_id parameter is deprecated and will be removed in Home Assistant core release 2024.8
  • A new argument progress_task has been added, which will be mandatory in Home Assistant core release 2024.8

If progress_task is passed, FlowManager will:

  • Send an event to fronted once the task has finished
  • Cancel the progress_task if the user closes the config flow dialog before the task is done

This means derived classes are no longer responsible for interaction between the progress task state and the UI.

FlowHandler.async_show_progress will log a warning if it's called without a progress_task. In Home Assistant core release 2024.8, the call will instead fail.

More details can be found in the documentation and in core PR #107668 and "107802.

· One min read

As of Home Assistant Core 2024.1, all usage of magic numbers for supported features is deprecated, and each entity platform has provided an EntityFeature enum to replace them.

There will be a one-year deprecation period, and the magic numbers will stop working in 2025.1 to ensure all custom integration authors have time to adjust.

This applies to, the following platforms:

· One min read

In recent years many constants have been replaced by Enums or other values by adding a code comment pointing to the successor. Using deprecated constants will now create a warning log entry containing the used integration, the replacement, and the version where the constant will be removed from core. There will be a one-year deprecation period to ensure all custom integration authors have time to adjust.

Most constants should already have been replaced, as we created several blog posts in the past about their deprecation. Some are listed below:

More details can be found in core PR #105736 or by checking the usage of the function check_if_deprecated_constant in the deprecation helper.

· One min read

Config entry now supports minor versions.

If minor versions differ, but major versions are the same, the integration setup will be allowed to continue even if the integration does not implement async_migrate_entry. This means a minor version bump is backwards compatible, unlike a major version bump which causes the integration to fail setup if the user downgrades HA Core without restoring configuration from backup.

Background

We have been very conservative with versioning config entry data because it breaks downgrading to an older version of Home Assistant Core. This means in most cases, we don't version, and the integrations instead do a kind of soft upgrade where they may, for example, do dict.get on config entry data that was not in an initial version, transform the data during setup etc.

By introducing minor versions similar to that already offered by the storage helper, this pattern is no longer recommended. A bump of the minor version should be done instead whenever the newly added, or otherwise changed, data does not break older versions.

More details can be found in the documentation on config entry migration and in core PR #105749.

· One min read

The EntityDescription classes have changed; derived dataclasses should now set frozen=True and kw_only=True.

Setting frozen to True makes the EntityDescription instances immutable, which means they cannot be accidentally updated after creation. Setting kw_only to True ensures the order of fields can be changed in the base class without breaking users.

During a deprecation period, which will end with HA Core 2025.1, it will still be possible to derive dataclasses not setting frozen=True or kw_only=True, but this will be logged, and the user will be asked to create an issue with the custom integration.

Once HA Core 2025.1 is released, it will no longer be possible to derive dataclasses without setting frozen=True or kw_only=True.

More details can be found in the core PR #105211.

· 3 min read

New utils for scaling brightness

Multiple integrations have implemented there own scaling algorithm to scale brightness. New utils are introduced now to simplify the implementation of brightness scaling in homeassistant.util.color:

def brightness_to_value(low_high_range: tuple[float, float], brightness: int) -> float:
"""Given a brightness_scale convert a brightness to a single value.

Do not include 0 if the light is off for value 0.

Given a brightness low_high_range of (1,100) this function
will return:

255: 100.0
127: ~49.8039
10: ~3.9216
"""
...

If you'd rather like to scale brightness to an integer range you can also use scale_ranged_value_to_int_range, described here.

def value_to_brightness(low_high_range: tuple[float, float], value: float) -> int:
"""Given a brightness_scale convert a single value to a brightness.

Do not include 0 if the light is off for value 0.

Given a brightness low_high_range of (1,100) this function
will return:

100: 255
50: 127
4: 10

The value will be clamped between 1..255 to ensure valid value.
"""
...

This also ensures a valid brightness value is returned.

Background

To scale fan speed percentage we already have some utils homeassistant.utils.percentage:

def ranged_value_to_percentage(
low_high_range: tuple[float, float], value: float
) -> int:
...

and

def percentage_to_ranged_value(
low_high_range: tuple[float, float], percentage: int
) -> float:
...

These percentage utils will now use new generic scaling utils in homeassistant.utils.scaling:

scale_ranged_value_to_int_range and scale_to_ranged_value

def scale_ranged_value_to_int_range(
source_low_high_range: tuple[float, float],
target_low_high_range: tuple[float, float],
value: float,
) -> int:
"""Given a range of low and high values convert a single value to another range.

Given a source low value of 1 and a high value of 255 and
a target range from 1 to 100 this function
will return:

(1,255), 255: 100
(1,255), 127: 50
(1,255), 10: 4
"""
...

and

def scale_to_ranged_value(
source_low_high_range: tuple[float, float],
target_low_high_range: tuple[float, float],
value: int,
) -> float:
"""Given a range of low and high values convert a single value to another range.

Do not include 0 in a range if 0 means off,
e.g. for brightness or fan speed.

Given a source low value of 1 and a high value of 255 and
a target range from 1 to 100 this function
will return:

(1,255), 255: 100
(1,255), 127: ~49.8039
(1,255), 10: ~3.9216
"""
...

Utils int_states_in_range and states_in_range are moved

These utils are now under homeassistant.util.scaling. If these are used in your custom integration, make sure you update the import to the new module.

· 2 min read

Exception handling during service calls

Service calls which raise exceptions have until now logged stack traces. Service calls that fail due to incorrect usage, for example invalid input, don't need a stack trace and would benefit from a helpful error message in the user's own language.

To be able to suppress the stack trace in these cases, the new exception type ServiceValidationError, which is derived from HomeAssistantError, has been introduced. ServiceValidationError should now be raised instead of ValueError when the service fails because it's used incorrectly.

If the service is used correctly but still fails, HomeAssistantError, or a subclass of HomeAssistantError other than ServiceValidationError, should still be raised.

When a service raises ServiceValidationError, the error message will show in the UI, and in the logs, but the stack trace is logged at debug level. For other exceptions that are raised from a service call (including HomeAssistantError) nothing changes and a full stack trace is still printed at exception severity.

Integrations should be updated and raise ServiceValidationError instead of ValueError when the the service fails due to incorrect usage, and HomeAssistantError when it fails for other expected errors, for example a network error. Read more.

Translation support for Exceptions

The HomeAssistantError exception and its subclasses, including ServiceValidationError, now accept a translation key to allow localization. Read more. The translation key will be used in cases where the frontend receives information about the exception. The English error message from the translation cache will also be used to log a message to the console if no custom error message is passed to the exception as argument.

Background