Rename Services to Service actions (#2249)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
Franck Nijhof 2024-07-16 12:05:05 +02:00 committed by GitHub
parent 3fa1f36dd6
commit 8eeaf3af91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 132 additions and 112 deletions

View File

@ -0,0 +1,17 @@
---
author: Franck Nijhof
authorURL: https://twitter.com/frenck
authorImageURL: /img/profile/frenck.png
authorTwitter: frenck
title: Services are now actions
---
The term "Services" has been a source of confusion for many users, as it is not immediately clear what it refers to; it could be a web or STT service, but in the context of Home Assistant, it means something entirely different (service calls).
In Home Assistant 2024.8, "Services" (as in service calls) will be renamed to "Actions". This change is part of our ongoing effort to make Home Assistant more user-friendly and easier for new users to understand. The term fits in with the UI changes we have been implementing over the past months (call services no longer exist in our automations and script editors). Effectively, one is performing actions in one's automations.
This change will be reflected in the Home Assistant UI, documentation, and other places where the term "Services" is used. For example, the **"Services"** tab in the Developer Tools will be renamed to **"Actions"**.
For developers, there is no need to worry about this change. In the developer documentation, we will update all references to "services" to "service actions", as we have different types of actions in our backend (for example, device actions). The underlying functionality will remain the same, and the transition is seamless.
This is, just like the end-user change, a terminology change only.

View File

@ -9,7 +9,7 @@ There are different ways of communicating between add-ons inside Home Assistant.
We use an internal network that's allowed to communicate with every add-on, including to/from Home Assistant, by using its name or alias. Only add-ons that run on the host network are limited in that they can talk with all internal add-ons by their name, but all other add-ons can't address these add-ons by name. However, using an alias works for both!
Names/aliases are used for communication inside Home Assistant.
The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-on's `config.yaml` file. You can use this name as the DNS name also, but you need to replace any `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: `https://github.com/xy/my_hassio_addons`). See [here](https://github.com/home-assistant/supervisor/blob/4ac7f7dcf08abb6ae5a018536e57d078ace046c8/supervisor/store/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Supervisor add-on API][supervisor-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the Supervisor API `addons` endpoint.
The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-on's `config.yaml` file. You can use this name as the DNS name also, but you need to replace any `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: `https://github.com/xy/my_hassio_addons`). See [here](https://github.com/home-assistant/supervisor/blob/4ac7f7dcf08abb6ae5a018536e57d078ace046c8/supervisor/store/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain actions that use the [Supervisor add-on API][supervisor-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the Supervisor API `addons` endpoint.
Use `supervisor` for communication with the internal API.
@ -23,7 +23,7 @@ There is also a proxy for the [Home Assistant Websocket API][core-websocket] tha
It is also possible to talk directly to the Home Assistant instance, which is named `homeassistant`, over the internal network. However, you'll need to know the configuration that is used by the running instance.
We have several services inside Home Assistant to run tasks. Send data over STDIN to an add-on to use the `hassio.addon_stdin` service.
We have several actions inside Home Assistant to run tasks. Send data over STDIN to an add-on to use the `hassio.addon_stdin` action.
## Supervisor API

View File

@ -151,9 +151,9 @@ This message will inform Home Assistant of new location information.
| `course` | int | The direction in which the device is traveling, measured in degrees and relative to due north. Must be greater than 0.
| `vertical_accuracy` | int | The accuracy of the altitude value, measured in meters. Must be greater than 0.
## Call a service
## Call a service action
Call a service in Home Assistant.
Call a service action in Home Assistant.
```json
{
@ -170,9 +170,9 @@ Call a service in Home Assistant.
| Key | Type | Description
| --- | ---- | -----------
| `domain` | string | The domain of the service
| `service` | string | The service name
| `service_data` | dict | The data to send to the service
| `domain` | string | The domain of the service action
| `service` | string | The service action name
| `service_data` | dict | The data to send to the service action
## Fire an event

View File

@ -7,7 +7,7 @@ The Home Assistant Core consists of four main parts. On top of this it includes
- **Event Bus**: facilitates the firing and listening of events -- the beating heart of Home Assistant.
- **State Machine**: keeps track of the states of things and fires a `state_changed` event when a state has been changed.
- **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services.
- **Service Registry**: listens on the event bus for `call_service` events and allows other code to register service actions.
- **Timer**: sends a `time_changed` event every 1 second on the event bus.
<img class='invertDark'

View File

@ -3,9 +3,9 @@ title: "Entities: integrating devices & services"
sidebar_label: "Introduction"
---
Integrations can represent devices & services in Home Assistant. The data points are represented as entities. Entities are standardized by other integrations like `light`, `switch`, etc. Standardized entities come with services for control, but an integration can also provide their own services in case something is not standardized.
Integrations can represent devices & services in Home Assistant. The data points are represented as entities. Entities are standardized by other integrations like `light`, `switch`, etc. Standardized entities come with actions for control, but an integration can also provide their own service actions in case something is not standardized.
An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating.
An entity abstracts away the internal workings of Home Assistant. As an integrator, you don't have to worry about how service actions or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating.
<img className='invertDark'
src='/img/en/architecture/integrating-devices-services.svg'
@ -17,7 +17,7 @@ An entity abstracts away the internal working of Home Assistant. As an integrato
Configuration is provided by the user via a [Config Entry](../config_entries_index.md) or in special/legacy cases via [configuration.yaml](../configuration_yaml_index.md).
The device integration (i.e. `hue`) will use this configuration to set up a connection with the device/service. It will forward the config entry (legacy uses discovery helper) to set up its entities in their respective integrations (light, switch). The device integration can also register their own services for things that are not made standardized. These services are published under the integration's domain, ie `hue.activate_scene`.
The device integration (i.e. `hue`) will use this configuration to set up a connection with the device/service. It will forward the config entry (legacy uses discovery helper) to set up its entities in their respective integrations (light, switch). The device integration can also register their own service actions for things that are not made standardized. These actions are published under the integration's domain, ie `hue.activate_scene`.
The entity integration (i.e. `light`) is responsible for defining the abstract entity class and services to control the entities.

View File

@ -3,7 +3,7 @@ title: "Integration architecture"
sidebar_label: "Integrations"
---
Home Assistant Core can be extended with **integrations**. Each integration is responsible for a specific domain within Home Assistant. Integrations can listen for or trigger events, offer services, and maintain states. Integrations are made up of a component (the base logic) and platforms (bits that integrate with other integrations). Integrations are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in integrations](https://www.home-assistant.io/integrations/).
Home Assistant Core can be extended with **integrations**. Each integration is responsible for a specific domain within Home Assistant. Integrations can listen for or trigger events, offer actions, and maintain states. Integrations are made up of a component (the base logic) and platforms (bits that integrate with other integrations). Integrations are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in integrations](https://www.home-assistant.io/integrations/).
<img class='invertDark'
src='/img/en/architecture/component-interaction.svg'
@ -13,7 +13,7 @@ Home Assistant distinguishes the following integration types:
## Define an Internet of Things domain
These integrations define a specific device category of Internet of Things devices in Home Assistant, like a light. It's up to the `light` integration to define what data is available in Home Assistant and in what format. It also provides services to control lights.
These integrations define a specific device category of Internet of Things devices in Home Assistant, like a light. It's up to the `light` integration to define what data is available in Home Assistant and in what format. It also provides actions to control lights.
For a list of defined domains, see [entities](./core/entity.md).

View File

@ -32,7 +32,7 @@ This is a normal function that is considered safe to be run from within the even
To declare a function as a callback, import the callback annotation from the core package and annotate your function.
A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component.
A common use case for a callback in Home Assistant is as a listener for an event or a service action call. It can process the incoming information and then schedule the right calls to be made. Example from the automation engine.
```python
from homeassistant.core import callback
@ -40,7 +40,7 @@ from homeassistant.core import callback
@callback
def async_trigger_service_handler(service_call):
"""Handle automation trigger service calls."""
"""Handle automation trigger service action call."""
vars = service_call.data.get(ATTR_VARIABLES)
for entity in component.async_extract_from_service(service_call):
hass.loop.create_task(entity.async_trigger(vars, True))

View File

@ -128,9 +128,9 @@ if not user.permissions.check_entity(entity_id, POLICY_CONTROL):
### The context object
All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions.
All service action calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and actions. These context objects also contain a user id, which is used for checking the permissions.
It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user:
It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service action handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user:
```python
from homeassistant.core import Context
@ -158,15 +158,15 @@ The `Unauthorized` exception has various parameters, to identify the permission
| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry).
| permission | The permission that we tested, ie `POLICY_READ`.
### Securing a service call handler
### Securing a service action handler
Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls.
Actions allow a user to control entities or with the integration as a whole. A service action uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service action.
All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked.
All service actions that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked.
#### Checking entity permissions
Your service call handler will need to check the permissions for each entity that it will act on.
Your service action handler will need to check the permissions for each entity that it will act on.
```python
from homeassistant.exceptions import Unauthorized, UnknownUser

View File

@ -27,7 +27,7 @@ Other properties that are common to all entities such as `device_class`, `icon`,
The press method can be used to trigger an action towards a device or service.
It is called by Home Assistant when the user presses the button or the
service to press the button has been called.
action to press the button has been called.
```python
class MyButton(ButtonEntity):

View File

@ -147,8 +147,8 @@ class MyClimateEntity(ClimateEntity):
class MyClimateEntity(ClimateEntity):
# Implement one of these methods.
# The `turn_on` method should set `hvac_mode` to any other than
# `HVACMode.OFF` by optimistically setting it from the service handler
# or with the next state update
# `HVACMode.OFF` by optimistically setting it from the service action
# handler or with the next state update
def turn_on(self):
"""Turn the entity on."""
@ -163,7 +163,8 @@ class MyClimateEntity(ClimateEntity):
class MyClimateEntity(ClimateEntity):
# Implement one of these methods.
# The `turn_off` method should set `hvac_mode` to `HVACMode.OFF` by
# optimistically setting it from the service handler or with the next state update
# optimistically setting it from the service action handler or with the
# next state update
def turn_off(self):
"""Turn the entity off."""
@ -180,7 +181,8 @@ class MyClimateEntity(ClimateEntity):
# will call `turn_on`/`turn_off` according to the current HVAC mode.
# If implemented, the `toggle` method should set `hvac_mode` to the right `HVACMode` by
# optimistically setting it from the service handler or with the next state update.
# optimistically setting it from the service action handler
# or with the next state update.
def toggle(self):
"""Toggle the entity."""

View File

@ -27,7 +27,7 @@ A fan may have preset modes that automatically control the percentage speed or o
Preset modes should not include named (manual) speed settings as these should be represented as percentages.
Manually setting a speed must disable any set preset mode. If it is possible to set a percentage speed manually without disabling the preset mode, create a switch or service to represent the mode.
Manually setting a speed must disable any set preset mode. If it is possible to set a percentage speed manually without disabling the preset mode, create a switch or service action to represent the mode.
## Supported features

View File

@ -59,7 +59,7 @@ If a light does not implement the `color_mode`, the `LightEntity` will attempt t
| `ColorMode.RGB` | The light can be dimmed and its color can be adjusted. The light's brightness can be set using the `brightness` parameter and read through the `brightness` property. The light's color can be set using the `rgb_color` parameter and read through the `rgb_color` property. `rgb_color` is an (r, g, b) tuple (not normalized for brightness).
| `ColorMode.RGBW` | The light can be dimmed and its color can be adjusted. The light's brightness can be set using the `brightness` parameter and read through the `brightness` property. The light's color can be set using the `rgbw_color` parameter and read through the `rgbw_color` property. `rgbw_color` is an (r, g, b, w) tuple (not normalized for brightness).
| `ColorMode.RGBWW` | The light can be dimmed and its color can be adjusted. The light's brightness can be set using the `brightness` parameter and read through the `brightness` property. The light's color can be set using the `rgbww_color` parameter and read through the `rgbww_color` property. `rgbww_color` is an (r, g, b, cw, ww) tuple (not normalized for brightness).
| `ColorMode.WHITE` | The light can be dimmed and its color can be adjusted. In addition, the light can be set to white mode. The light's brightness can be set using the `brightness` parameter and read through the `brightness` property. The light can be set to white mode by using the `white` parameter with the desired brightness as value. Note that there's no `white` property. If both `brighthness` and `white` are present in a service call, the `white` parameter will be updated with the value of `brightness`. If this mode is supported, the light *must* also support at least one of `ColorMode.HS`, `ColorMode.RGB`, `ColorMode.RGBW`, `ColorMode.RGBWW` or `ColorMode.XY` and *must not* support `ColorMode.COLOR_TEMP`.
| `ColorMode.WHITE` | The light can be dimmed and its color can be adjusted. In addition, the light can be set to white mode. The light's brightness can be set using the `brightness` parameter and read through the `brightness` property. The light can be set to white mode by using the `white` parameter with the desired brightness as value. Note that there's no `white` property. If both `brighthness` and `white` are present in a service action call, the `white` parameter will be updated with the value of `brightness`. If this mode is supported, the light *must* also support at least one of `ColorMode.HS`, `ColorMode.RGB`, `ColorMode.RGBW`, `ColorMode.RGBWW` or `ColorMode.XY` and *must not* support `ColorMode.COLOR_TEMP`.
| `ColorMode.XY` | The light can be dimmed and its color can be adjusted. The light's brightness can be set using the `brightness` parameter and read through the `brightness` property. The light's color can be set using the `xy_color` parameter and read through the `xy_color` property. `xy_color` is an (x, y) tuple.
Note that in color modes `ColorMode.RGB`, `ColorMode.RGBW` and `ColorMode.RGBWW` there is brightness information both in the light's `brightness` property and in the color. As an example, if the light's brightness is 128 and the light's color is (192, 64, 32), the overall brightness of the light is: 128/255 * max(192, 64, 32)/255 = 38%.
@ -111,16 +111,16 @@ class MyLightEntity(LightEntity):
```
Note that there's no `color_mode` passed to the `async_turn_on` method, instead only a single color attribute is allowed.
It is guaranteed that the integration will only receive a single color attribute in a `turn_on`call, which is guaranteed to be supported by the light according to the light's `supported_color_modes` property. To ensure this, colors in the service call will be translated before the entity's `async_turn_on` method is called if the light doesn't support the corresponding color mode:
It is guaranteed that the integration will only receive a single color attribute in a `turn_on`call, which is guaranteed to be supported by the light according to the light's `supported_color_modes` property. To ensure this, colors in the service action call will be translated before the entity's `async_turn_on` method is called if the light doesn't support the corresponding color mode:
| Color type | Translation
|--------------|-----------------------
| color_temp | Will be removed from the service call if not supported and translated to `hs_color`, `rgb_color`, `rgbw_color`, `rgbww_color` or `xy_color` if supported by the light.
| hs_color | Will be removed from the service call if not supported and translated to `rgb_color`, `rgbw_color`, `rgbww_color` or `xy_color` if supported by the light.
| rgb_color | Will be removed from the service call if not supported and translated to `rgbw_color`, `rgbww_color`, `hs_color` or `xy_color` if supported by the light.
| rgbw_color | Will be removed from the service call if not supported.
| rgbww_color | Will be removed from the service call if not supported.
| xy_color | Will be removed from the service call if not supported and translated to `hs_color`, `rgb_color`, `rgbw_color` or `rgbww_color` if supported by the light.
| color_temp | Will be removed from the service action call if not supported and translated to `hs_color`, `rgb_color`, `rgbw_color`, `rgbww_color` or `xy_color` if supported by the light.
| hs_color | Will be removed from the service action call if not supported and translated to `rgb_color`, `rgbw_color`, `rgbww_color` or `xy_color` if supported by the light.
| rgb_color | Will be removed from the service action call if not supported and translated to `rgbw_color`, `rgbww_color`, `hs_color` or `xy_color` if supported by the light.
| rgbw_color | Will be removed from the service action call if not supported.
| rgbww_color | Will be removed from the service action call if not supported.
| xy_color | Will be removed from the service action call if not supported and translated to `hs_color`, `rgb_color`, `rgbw_color` or `rgbww_color` if supported by the light.
:::tip Scaling brightness

View File

@ -47,7 +47,7 @@ Properties should always only return information from memory and not do I/O (lik
| source_list | <code>list[str] &#124; None</code> | `None` | The list of possible input sources for the media player. (This list should contain human readable names, suitable for frontend display).
| state | <code>MediaPlayerState &#124; None</code> | `None` | State of the media player.
| volume_level | <code>float &#124; None</code> | `None` | Volume level of the media player in the range (0..1).
| volume_step | <code>float &#124; None</code> | 0.1 | Volume step to use for the `volume_up` and `volume_down` services.
| volume_step | <code>float &#124; None</code> | 0.1 | Volume step to use for the `volume_up` and `volume_down` service actions.
## Supported features
@ -59,8 +59,8 @@ and are combined using the bitwise or (`|`) operator.
| `BROWSE_MEDIA` | Entity allows browsing media. |
| `CLEAR_PLAYLIST` | Entity allows clearing the active playlist. |
| `GROUPING` | Entity can be grouped with other players for synchronous playback. |
| `MEDIA_ANNOUNCE` | Entity supports the `play_media` service's announce parameter. |
| `MEDIA_ENQUEUE` | Entity supports the `play_media` service's enqueue parameter. |
| `MEDIA_ANNOUNCE` | Entity supports the `play_media` action's announce parameter. |
| `MEDIA_ENQUEUE` | Entity supports the `play_media` action's enqueue parameter. |
| `NEXT_TRACK` | Entity allows skipping to the next media track. |
| `PAUSE` | Entity allows pausing the playback of media. |
| `PLAY` | Entity allows playing/resuming playback of media. |
@ -250,7 +250,7 @@ class MyMediaPlayer(MediaPlayerEntity):
```
:::info
Using the integration name as the `media_content_type` is also acceptable within the `play_media` service if the integration provides handling which does not map to the defined constants.
Using the integration name as the `media_content_type` is also acceptable within the `play_media` service action if the integration provides handling which does not map to the defined constants.
:::
### Available device classes

View File

@ -34,7 +34,7 @@ class MySwitch(Scene):
```
The activate method can be used to activate the scene towards a device or service.
It is called by Home Assistant when the user presses the scene `activate` button or when the `scene.turn_on` service is called to activate the scene.
It is called by Home Assistant when the user presses the scene `activate` button or when the `scene.turn_on` action is called to activate the scene.
### Available device classes

View File

@ -14,7 +14,7 @@ Properties should always only return information from memory and not do I/O (lik
| Name | Type | Default | Description |
| ----------------------- | ------ | ------------------------------------- | --------------------------------------------------------------------------------------- |
| is_on | bool | `None` | Whether the device is on or off. |
| available_tones | list or dict | `NotImplementedError()` | The list or dictionary of available tones on the device to pass into the `turn_on` service. If a dictionary is provided, when a user uses the dict value of a tone, it will get converted to the corresponding dict key before being passed on to the integration platform. Requires `SUPPORT_TONES` feature. |
| available_tones | list or dict | `NotImplementedError()` | The list or dictionary of available tones on the device to pass into the `turn_on` service action. If a dictionary is provided, when a user uses the dict value of a tone, it will get converted to the corresponding dict key before being passed on to the integration platform. Requires `SUPPORT_TONES` feature. |
### Tones
@ -26,16 +26,16 @@ Supported features constants are combined using the bitwise or (`|`) operator.
| Name | Description |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `SirenEntityFeature.TONES` | The device supports different tones (the tone can be passed in to `turn_on` service). |
| `SirenEntityFeature.DURATION` | The device supports setting a duration for the tone (the duration can be passed in to `turn_on` service). |
| `SirenEntityFeature.VOLUME_SET` | The device supports setting the volume level of the device (the volume level can be passed in to `turn_on` service). |
| `SirenEntityFeature.TONES` | The device supports different tones (the tone can be passed in to `turn_on` service action). |
| `SirenEntityFeature.DURATION` | The device supports setting a duration for the tone (the duration can be passed in to `turn_on` service action). |
| `SirenEntityFeature.VOLUME_SET` | The device supports setting the volume level of the device (the volume level can be passed in to `turn_on` service action). |
## Methods
### Turn on
There are three optional input parameters that can be passed into the service call, each gated by a supported feature flag. If the corresponding flag isn't set when a given input parameter is provided in the service call, it will be filtered out from the service call by the base platform before being passed to the integration.
There are three optional input parameters that can be passed into the service action call, each gated by a supported feature flag. If the corresponding flag isn't set when a given input parameter is provided in the service action call, it will be filtered out from the call by the base platform before being passed to the integration.
| Parameter Name | Data Validation | Supported Feature Flag |
|---------------- |--------------------------------------- |------------------------ |

View File

@ -42,7 +42,7 @@ Supported features are defined by using values in the `UpdateEntityFeature` enum
| 'BACKUP' | A backup can be made automatically, before installing an update.
| 'INSTALL' | The update can be installed from Home Assistant.
| 'PROGRESS' | This integration is able to provide progress information. If omitted, Home Assistant will try to provide a progress status; although it is better if the progress can be extracted from the device or service API.
| 'SPECIFIC_VERSION' | A specific version of an update can be installed using the `update.install` service.
| 'SPECIFIC_VERSION' | A specific version of an update can be installed using the `update.install` service action.
| 'RELEASE_NOTES' | The entity provides methods to fetch a complete changelog.
## Methods

View File

@ -2,9 +2,9 @@
title: "Raising exceptions"
---
## Raising exceptions in service handlers
## Raising exceptions in service action handlers
Operations like service calls and entity methods (e.g. *Set HVAC Mode*) should raise exceptions properly.
Operations like service action calls and entity methods (e.g. *Set HVAC Mode*) should raise exceptions properly.
Integrations should raise `ServiceValidationError` (instead of `ValueError`) in case when the user did something wrong. In this case a stack trace will only be printed at debug level.

View File

@ -97,7 +97,7 @@ async def async_create_fix_flow(
An issue will be kept in the issue registry until it's removed by the integration that created it or by the user [fixing](#fixing-an-issue) it.
The `is_persistent` flag controls if an issue should be shown to the user after a restart of Home Assistant:
- If the `is_persistent` flag is set on the issue, the issue will be shown again to the user after a restart. Use this for issues that can only be detected when they occur (update failed, unknown service in automation).
- If the `is_persistent` flag is set on the issue, the issue will be shown again to the user after a restart. Use this for issues that can only be detected when they occur (update failed, unknown action in automation).
- If the `is_persistent` flag is not set on the issue, the issue will not be shown again to the user after a restart until it's created again by its integration. Use this for issues that can be checked for, like low disk space.
### Ignored issues

View File

@ -2,9 +2,9 @@
title: "Reproduce state"
---
Home Assistant has support for scenes. Scenes are a collection of (partial) entity states. When a scene is activated, Home Assistant will try to call the right services to get the specified scenes in their specified state.
Home Assistant has support for scenes. Scenes are a collection of (partial) entity states. When a scene is activated, Home Assistant will try to call the right service actions to get the specified scenes in their specified state.
Integrations are responsible for adding support to Home Assistant to be able to call the right services to reproduce the states in a scene.
Integrations are responsible for adding support to Home Assistant to be able to call the right service actions to reproduce the states in a scene.
## Adding support

View File

@ -54,7 +54,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
1. Verify that the passed in configuration (user/pass/host etc.) works.
2. Group your calls to `add_entities if possible.
3. If the platform adds extra services, the format should be `<domain of your integration>.<service name>`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions).
3. If the platform adds extra actions, the format should be `<domain of your integration>.<service action name>`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register service actions under the `awesome_sauce` domain. Make sure that your service actions [verify permissions](auth_permissions.md#checking-permissions).
### 4. Entity

View File

@ -15,7 +15,7 @@ The Home Assistant instance contains four objects to help you interact with the
| `hass.config` | This is the core configuration of Home Assistant exposing location, temperature preferences and config directory path. [See available methods.](https://dev-docs.home-assistant.io/en/dev/api/core.html#homeassistant.core.Config)
| `hass.states` | This is the StateMachine. It allows you to set states and track when they are changed. [See available methods.](https://developers.home-assistant.io/docs/dev_101_states) |
| `hass.bus` | This is the EventBus. It allows you to trigger and listen for events. [See available methods.](https://developers.home-assistant.io/docs/dev_101_events) |
| `hass.services` | This is the ServiceRegistry. It allows you to register services. [See available methods.](https://developers.home-assistant.io/docs/dev_101_services) |
| `hass.services` | This is the ServiceRegistry. It allows you to register service actions. [See available methods.](https://developers.home-assistant.io/docs/dev_101_services) |
<img class='invertDark'
alt='Overview of the Home Assistant core architecture'

View File

@ -1,13 +1,13 @@
---
title: "Integration services"
sidebar_label: "Custom services"
title: "Integration service actions"
sidebar_label: "Custom actions"
---
Home Assistant provides ready-made services for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service under your own integration first. Once we see a pattern in these services, we can talk about generalizing them.
Home Assistant provides ready-made actions for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service action under your own integration first. Once we see a pattern in these service actions, we can talk about generalizing them.
This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `<config dir>/custom_components/hello_service/__init__.py` and copy the below example code.
This is a simple "hello world" example to show the basics of registering a service action. To use this example, create the file `<config dir>/custom_components/hello_service/__init__.py` and copy the below example code.
Services can be called from automations and from the service "Developer tools" in the frontend.
Actions can be called from automations and from the actions "Developer tools" in the frontend.
```python
DOMAIN = "hello_service"
@ -20,7 +20,7 @@ def setup(hass, config):
"""Set up is called when Home Assistant is loading our component."""
def handle_hello(call):
"""Handle the service call."""
"""Handle the service action call."""
name = call.data.get(ATTR_NAME, DEFAULT_NAME)
hass.states.set("hello_service.hello", name)
@ -35,67 +35,68 @@ To load the integration in Home Assistant is necessary to create a `manifest.jso
```yaml
# configuration.yaml entry
hello_service:
hello_action:
```
An example of `manifest.json`:
```json
{
"domain": "hello_service",
"name": "Hello Service",
"domain": "hello_action",
"name": "Hello Action",
"documentation": "https://developers.home-assistant.io/docs/dev_101_services",
"iot_class": "local_push",
"version": "0.1.0"
}
```
Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values.
Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Actions developer tool. On the right, find your action and click on it. This will automatically fill in the correct values.
Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify a parameter by providing it through Service Data. In YAML mode, add the following and press "Call Service again".
Pressing "Perform action" will now call your service action without any parameters. This will cause your service action to create a state with the default name 'World'. If you want to specify the name, you have to specify a parameter by providing it through service action Data. In YAML mode, add the following and press "Perform Service" again.
```yaml
service: hello_service.hello
service: hello_action.hello
data:
name: Planet
```
The service will now overwrite the previous state with "Planet".
The service action will now overwrite the previous state with "Planet".
## Service descriptions
## Service action descriptions
Adding services is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the services.
Adding actions is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the service actions.
Services are published under the domain name of your integration, so in `services.yaml` we only use the service name as the base key.
Actions are published under the domain name of your integration, so in `services.yaml` we only use the service action name as the base key.
```yaml
# Example services.yaml entry
# Service ID
set_speed:
# If the service accepts entity IDs, target allows the user to specify entities by
# entity, device, or area. If `target` is specified, `entity_id` should not be
# defined in the `fields` map. By default it shows only targets matching entities
# from the same domain as the service, but if further customization is required,
# target supports the entity, device, and area selectors
# (https://www.home-assistant.io/docs/blueprint/selectors/). Entity selector
# parameters will automatically be applied to device and area, and device selector
# parameters will automatically be applied to area.
# If the service action accepts entity IDs, target allows the user to specify
# entities by entity, device, or area. If `target` is specified, `entity_id`
# should not be defined in the `fields` map. By default it shows only targets
# matching entities from the same domain as the action, but if further
# customization is required, target supports the entity, device, and area
# selectors (https://www.home-assistant.io/docs/blueprint/selectors/).
# Entity selector parameters will automatically be applied to device and area,
# and device selector parameters will automatically be applied to area.
target:
entity:
domain: fan
# If not all entities from the service's domain support a service, entities
# If not all entities from the action's domain support a action, entities
# can be further filtered by the `supported_features` state attribute. An
# entity will only be possible to select if it supports at least one of the
# listed supported features.
supported_features:
- fan.FanEntityFeature.SET_SPEED
# If a service requires more than one supported feature, the item should
# be given as a list of required supported features. For example, if the
# service requires both SET_SPEED and OSCILLATE it would be expressed like this
# If a service action requires more than one supported feature, the item
# should be given as a list of required supported features. For example,
# if the service action requires both SET_SPEED and OSCILLATE it would
# be expressed like this
- - fan.FanEntityFeature.SET_SPEED
- fan.FanEntityFeature.OSCILLATE
# Different fields that your service accepts
# Different fields that your service action accepts
fields:
# Key of the field
speed:
@ -120,7 +121,7 @@ set_speed:
- "high"
# Fields can be grouped in collapsible sections, this is useful to initially hide
# advanced fields. Note that the collapsible section only affect presentation to the
# user, service data will not be nested.
# user, service action data will not be nested.
advanced_fields:
# Whether or not the section is initially collapsed (default = false)
collapsed: true
@ -134,14 +135,14 @@ set_speed:
```
:::info
The name and description of the services are set in our [translations](/docs/internationalization/core#services) and not in the service description. Each service and service field must have a matching translation defined.
The name and description of the service actions are set in our [translations](/docs/internationalization/core#services) and not in the service action description. Each service action and service action field must have a matching translation defined.
:::
### Filtering service fields
### Filtering service action fields
In some cases, entities from a service's domain may not support all service fields. By
providing a `filter` for the field description, the field will only be shown if at least
one selected entity supports the field according to the configured filter.
In some cases, entities from a action's domain may not support all service action fields.
By providing a `filter` for the field description, the field will only be shown if at
least one selected entity supports the field according to the configured filter.
A filter must specify either `supported_features` or `attribute`, combing both is not
supported.
@ -184,11 +185,11 @@ This is a partial example of a field which is only shown if at least one selecte
## Icons
Services can also have icons. These icons are used in the Home Assistant UI when displaying the service in places like the automation and script editors.
Actions can also have icons. These icons are used in the Home Assistant UI when displaying the service action in places like the automation and script editors.
The icon to use for each service can be defined in the `icons.json` translation file in the integration folder, under the `services` key. The key should be the service name, and the value should be the icon to use.
The icon to use for each service action can be defined in the `icons.json` translation file in the integration folder, under the `services` key. The key should be the service action name, and the value should be the icon to use.
The following example, shows how to provide icons for the `turn_on` and `turn_off` services of an integration:
The following example, shows how to provide icons for the `turn_on` and `turn_off` service actions of an integration:
```json
{
@ -200,11 +201,11 @@ The following example, shows how to provide icons for the `turn_on` and `turn_of
```
## Entity services
## Entity service actions
Sometimes you want to provide extra services to control your entities. For example, the Sonos integration provides services to group and ungroup devices. Entity services are special because there are many different ways a user can specify entities. It can use areas, a group or a list of entities.
Sometimes you want to provide extra actions to control your entities. For example, the Sonos integration provides action to group and ungroup devices. Entity service actions are special because there are many different ways a user can specify entities. It can use areas, a group or a list of entities.
You need to register entity services in your platforms, like `<your-domain>/media_player.py`. These services will be made available under your domain and not the media player domain. Example code:
You need to register entity service actions in your platforms, like `<your-domain>/media_player.py`. These service actions will be made available under your domain and not the media player domain. Example code:
```python
from homeassistant.helpers import config_validation as cv, entity_platform, service
@ -224,7 +225,7 @@ async def async_setup_entry(hass, entry):
)
```
If you need more control over the service call, you can also pass an async function that instead of `"set_sleep_timer"`:
If you need more control over the service action call, you can also pass an async function that instead of `"set_sleep_timer"`:
```python
async def custom_set_sleep_timer(entity, service_call):
@ -233,11 +234,11 @@ async def custom_set_sleep_timer(entity, service_call):
## Response data
Services may respond to a service call with data for powering more advanced automations. There are some additional implementation requirements:
Actions may respond to an action call with data for powering more advanced automations. There are some additional implementation requirements:
- Response data must be a `dict` and serializable in JSON [`homeassistant.util.json.JsonObjectType`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/util/json.py) in order to interoperate with other parts of the system, such as the frontend.
- Errors must be raised as exceptions just like any other service call as we do
not want end users to need complex error handling in scripts and automations.
- Errors must be raised as exceptions just like any other service action call as
we do not want end users to need complex error handling in scripts and automations.
The response data should not contain error codes used for error handling.
Example code:
@ -286,9 +287,9 @@ The use of response data is meant for cases that do not fit the Home Assistant s
### Supporting response data
Service calls are registered with a `SupportsResponse` value to indicate response data is supported.
Action calls are registered with a `SupportsResponse` value to indicate response data is supported.
| Value | Description |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OPTIONAL` | The service performs an action and can optionally return response data. The service should conditionally check the `ServiceCall` property `return_response` to decide whether or not response data should be returned, or `None`. |
| `ONLY` | The service doesn't perform any actions and always returns response data. |
| `OPTIONAL` | Performs an action and can optionally return response data. The service action should conditionally check the `ServiceCall` property `return_response` to decide whether or not response data should be returned, or `None`. |
| `ONLY` | Doesn't perform any actions and always returns response data. |

View File

@ -99,7 +99,7 @@ If you can't avoid a PyLint warning, add a comment to disable the PyLint check f
- Make sure to not interact with any integration details in tests of integrations. Following this pattern will make the tests more robust for changes in the integration.
- Set up the integration with the core interface either [`async_setup_component`](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/setup.py#L44-L46) or [`hass.config_entries.async_setup`](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/config_entries.py#L693) if the integration supports config entries.
- Assert the entity state via the core state machine [`hass.states`](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/core.py#L887).
- Call services via the core service registry [`hass.services`](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/core.py#L1133).
- Perform service action calls via the core service registry [`hass.services`](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/core.py#L1133).
- Assert `DeviceEntry` state via the [device registry](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/helpers/device_registry.py#L101).
- Assert entity registry `RegistryEntry` state via the [entity registry](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/helpers/entity_registry.py#L120).
- Modify a `ConfigEntry` via the config entries interface [`hass.config_entries`](https://github.com/home-assistant/core/blob/4cce724473233d4fb32c08bd251940b1ce2ba570/homeassistant/config_entries.py#L570).

View File

@ -7,7 +7,7 @@ Device Automations provide users with a device-centric layer on top of the core
Integrations can hook into this system by exposing functions to generate the pre-defined triggers, conditions, actions and having functions that can listen for the triggers, check the condition and execute the action.
Device automations are not exposing extra functionality but are a way for users to not have to learn new concepts. Device automations are using events, state and service helpers under the hood.
Device automations are not exposing extra functionality but are a way for users to not have to learn new concepts. Device automations are using events, state and service action helpers under the hood.
### Secondary device automations

View File

@ -252,7 +252,7 @@ as is makes our examples more readable:
- Platform types (e.g., `light`, `switch`)
- Condition types (e.g., `numeric_state`, `state`)
- Trigger platforms (e.g., `state`, `time`)
- Service names (e.g., `light.turn_on`)
- Service action names (e.g., `light.turn_on`)
- Device classes (e.g., `problem`, `motion`)
- Event names
- Values that accept a limited set of possible, hardcoded values.

View File

@ -108,7 +108,7 @@ All methods starting with `call` are async methods. This means that they will re
### `hass.callService(domain, service, data)`
Call a service on the backend.
Call a service action on the backend.
```js
hass.callService('light', 'turn_on', {

View File

@ -21,7 +21,7 @@ The `strings.json` contains translations for different things that the integrati
| `issues` | Translations for repairs issues. |
| `options` | Translations for the options flow. |
| `selectors` | Selectors of the integration. |
| `services` | Services of the integration. |
| `services` | Service actions of the integration. |
### Title
@ -123,12 +123,12 @@ The translation for selectors are defined under the `selector` key. It supports
```
### Services
### Service Actions
The translations of service strings are defined under the `services` key.
The translations of service actions strings are defined under the `services` key.
It supports translating the `name` and `description` of each service,
and the `name` and `description` of each service's `fields`.
It supports translating the `name` and `description` of each action,
and the `name` and `description` of each action's `fields`.
```json
{
@ -158,7 +158,7 @@ and the `name` and `description` of each service's `fields`.
```
:::note
Services may use selectors in their `fields`. The translation of those selectors can be provided using the `translation_key` property on the selector definition in the services.yaml file. See the [Selectors](#selectors) section and the [Service description](/docs/dev_101_services.md#service-descriptions) page for more information.
Service actions may use selectors in their `fields`. The translation of those selectors can be provided using the `translation_key` property on the selector definition in the services.yaml file. See the [Selectors](#selectors) section and the [Service action description](/docs/dev_101_services.md#service-action-descriptions) page for more information.
:::
### Device automations
@ -207,7 +207,7 @@ The translation strings for exceptions are defined under the `exception` key in
```
Example of raising an exception with localization during a service call:
Example of raising an exception with localization during a service action call:
```python
async def async_select_index(hass: HomeAssistant, index: int) -> None: