Skip to main content

· One min read

In the Home Assistant Core 2022.3 release, we add custom features for the tile card. If you are a developer of custom cards, you can now build your own features to the tile card instead of building a whole card.

Screenshot showing example of custom tile feature

type: tile
entity: button.push
- type: custom:button-press-tile-feature

Custom tile features can even be added to the tile card editor like any other built-in tile feature using similar syntax as custom cards.

window.customTileFeatures = window.customTileFeatures || [];
type: "button-press-tile-feature",
name: "Button press",

For more details, see the custom tile features documentation.

· One min read

Home Assistant's MQTT integration no longer supports deprecated callback signatures for MQTT subscribe.

Custome integrations that still used the deprecated callback signature for the callback function on MQTT subscribe will break unless updated. An exception will be raised if a not supported callback type is detected.

Examples of deprecated callback functions that will no longer work:

async def async_deprecated_callback1(topic: str, payload: ReceivePayloadType, qos: int) -> None:
"""Deprecated async callback example 1."""

def async_deprecated_callback2(topic: str, payload: ReceivePayloadType, qos: int) -> None:
"""Deprecated async callback example 2."""

Example of a correct callback signature:

def async_correct_callback(msg: ReceiveMessage) -> None:
"""Callback example 1."""

· 2 min read

Home Assistant now supports snapshot testing for our Python codebase.

Snapshot testing (also known as approval tests) are tests that assert values against a stored reference value (the snapshot); ensuring the output of code remains the same over time.

Snapshot tests are different from regular (functional) tests and do not replace functional tests, but they can be very useful for testing larger test outputs. Within Home Assistant they could, for example, be used to test entity states, device or entity registry items, or the output of a diagnostic dump.

Take, for example, this diagnostic test, which uses a snapshot to assert the output of a diagnostic dump:

# tests/components/example/
async def test_diagnostics(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
init_integration: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test diagnostics."""
assert (
await get_diagnostics_for_config_entry(hass, hass_client, init_integration)
== snapshot

When this test is run for the first time, it will fail, as no snapshot exists. To create (or update) a snapshot, run pytest with the --snapshot-update flag, which will create a snapshot file in the snapshots directory of this component.

The snapshot file is named after the test file, in this case: tests/components/example/snapshots/test_diagnostics.ambr. The snapshot files are human-readable and must be committed to the repository.

Any sequential runs of the tests will then compare the results against the snapshot. If the results are different, the test will fail.

Snapshots are an easy way to ensure the output of code remains the same over time and can greatly reduce the amount of testing code needed (while providing) a full assert against a complete output.

Snapshot testing in Home Assistant is build on top of Syrupy, which has been extended to handle Home Assistant-specific data structures.

More information on testing integrations, can be found in our documentation.

· One min read

As of Home Assistant Core 2023.3, some constants and functions have been moved between homeassistant.helpers.json and homeassistant.util.json :

  • save_json and find_paths_unserializable_data functions should now be imported from homeassistant.helpers.json
  • json_loads function should now be imported from homeassistant.util.json
  • JSON_ENCODE_EXCEPTIONS and JSON_DECODE_EXCEPTIONS constants should now be imported from homeassistant.util.json

· One min read

We've added a new built-in intent: HassGetState

This intent will enable users to ask questions to Assist once we've added translations to the intents repository. You can try it out now by adding custom sentences:

# Example <config>/custom_sentences/en/get_state.yaml

language: en
- sentences:
- what is <name> [in <area>]
- is <name> {state} [in <area>]

default: "{{ }} is {{ state.state_with_unit }}"

- "on"
- "off"
- open
- closed
- locked
- unlocked
- wet
- dry

With these sentences, you can now ask Assist things like "what is the outside temperature?", "is the front door locked?", or "is the floor in the basement wet?" This relies on having entity names (or aliases) set up just right, of course. For example, a sensor named "outside temperature" and a binary moisture sensor named "floor" in the "basement" area.

As we add translations, more types of questions will be possible such as "which lights are in the living room?" and "are any doors unlocked?"

· One min read

The number of decimal digits shown when displaying a sensor state is now configurable by the user. Integrations can suggest the number of decimal digits by setting the property suggested_display_precision. Integrations are encouraged to remove rounding for display and instead set property suggested_display_precision.

Round for presentation is done by the frontend, as well as by new template functions introduced in core PR #87619.

The number of displayed decimal digits is influenced by unit conversion:

  • Converting from a smaller to a larger unit increases the display precision
  • Converting from a larger to a smaller unit decreases the display precision if the integration has set suggested_display_precision
  • Minimum precision when converting from a larger to a smaller unit is 0, i.e. there's no rounding to tens, hundreds etc.

The number of displayed decimal digits is not influenced by unit conversion if the user has set the display precision themselves.

Note: A similar concept where the sensor's state was rounded, detailed in an earlier blog post, has been reverted.

· 3 min read

Home Assistant gets lots of contributions, which is absolutely amazing! But when having lots of PRs, it becomes harder to keep track of the state of those.

To help with this, we are introducing a new process to our review process that automatically drafts PRs when they require more work before they can be reviewed again (or merged).

We have adjusted our bot to automatically draft PRs if a review has requested changes to be made. Once the changes have been made, the author of the PR can click the "Ready for review" button to un-draft the PR and make it ready for review again.

The ready for review button in the bottom of a PR in draft mode

Before you click the "Ready for review" button, make sure you have addressed all requested changes, and all our CI jobs and checks are passing successfully.

What is a draft PR?

A draft PR is a PR that is not ready for review yet. It is a way to let others know that you are working on something, but it is not ready for review and merging yet.

Draft PRs are recognizable by the "Draft" label in the top right of the PR and show up with a grey merge icon eveywhere in the GitHub UI.

This is what a PR in draft looks like

This doesn't mean you should open a PR to start working on something; please only open a PR if you think it is ready for review and merging. However, after opening a PR, there may be a reason to put it back into draft state.

For example, opening a PR will automatically trigger our CI jobs and checks. These checks can reveal issues in your code that need adjustments, or of course, an actual review took place that requested changes.

You can put any of your PRs back into draft at any moment, by clicking the "Convert to draft" link in the top right of your PR.

Putting a PR in draft is something you can do too

Why are we doing this?

As a reviewer, you are presented with a lot of PRs. Some of them are ready for review, and some of them are not. Typically, the only way to find out, is to open the PR and look at it, to discover it is still in progress.

This is not only a waste of time but also a waste of energy. Especially considering this happens to multiple reviewers on the same PR multiple times a day.

The draft state of a PR is visible in all places in GitHub. In notifications, searches, and just the overview of PRs. Above all, it is easily filterable.

This gives reviewers a better focus on what can actually use their attention right now.

More background information can be found in this Google Document.

Or, read all about our review process on this page.

· 2 min read

We have removed all translation files from the Home Assistant Core repository and put in place a helper script to compile English translations from the translation strings files (strings.json) for development purposes.

Previously, all translation files (including all languages) were part of the Home Assistant Core repository. Every night we would update the translations by downloading them from Lokalise and committing them into the Core repository.

Instead, we have moved this process @ build time. We now download the latest translations from Lokalise when we ship a new release (including betas & nightly builds).

This approach comes with some benefits:

  • We no longer have to commit translation files into the Core repository. This means as a developer, this is also no longer a confusing burden.
  • People will no longer (incorrectly) try to contribute language translations via GitHub.
  • Each release, including patch, beta, and nightly versions, will now also have the latest translations.

Local development

For local development, we have our translations development helper script. This always has been in place already, except now, it can compile the English translations for all integrations at once.

python3 -m script.translations develop --all

This script is automatically run when a dev environment is set up, and each time you run running Home Assistant in your VSCode (as a pre-launch task).

· One min read

The intents repository which powers Assist, has had two important changes.

First, data blocks in the intents YAML can now have a response key. For example:

language: en
- sentences:
- "open {name}"
response: cover

A response with a matching key must be defined in responses/<language>/<intent>.yaml:

language: en
cover: "Opened {{ }}"

Response templates are in the Jinja2 format, and may access the matched intent's slots as well as the state of the affected entity.

The second change comes from hassil, the parser for our intent template syntax. In addition to an 8-10x speed-up in parsing, whitespace inside templates is taken literally.

Previously, a template like light(s | ing) would match both "lights" and "lighting". Now, "light s" and "light ing" would be matched instead due to the extra space around |. The correct template would be light(s|ing)

· 2 min read

Note: The changes described here have been reverted and replaced with rounding for presentation, more details can be found in this blog post.

SensorEntity can now do rounding of a numerical native_value when it's converted to the sensor state. This is implemented as a part of core PR #86074. The rounding is opt-in by integrations setting the native_precision property. It is recommended that this property is set by integrations because it ensures the number of decimals is reasonable also after unit conversion.

A summary of the changes, copied from the PR description:

  • By default, no rounding is done
    • Integrations can influence the state precision by setting a new property native_precision
  • The state precision is influenced by unit conversion
    • Converting from a smaller to a larger unit increases the display precision
    • Converting from a larger to a smaller unit decreases the display precision if the integration has set native_precision
    • Minimum precision when converting from a larger to a smaller unit is 0, i.e. there's no rounding to tens, hundreds etc.
  • User can override the display precision from the frontend
    • There's no minimum precision, i.e. rounding to tens, hundreds, etc. is possible by setting a negative precision
  • Integrations are encouraged to drop rounding for display and instead set property native_precision
  • Trailing zeroes are added to the sensor state's string representation to match the precision if:
    • The precision is set by user
    • The native_precision property is not None
    • Unit conversion is done