mirror of
https://github.com/home-assistant/core.git
synced 2026-04-29 02:13:44 +02:00
Delete Home Connect deprecated actions (#150929)
This commit is contained in:
committed by
GitHub
parent
158fb35c5b
commit
dd270f54fc
@@ -61,19 +61,12 @@ BSH_DOOR_STATE_LOCKED = "BSH.Common.EnumType.DoorState.Locked"
|
||||
BSH_DOOR_STATE_OPEN = "BSH.Common.EnumType.DoorState.Open"
|
||||
|
||||
|
||||
SERVICE_OPTION_ACTIVE = "set_option_active"
|
||||
SERVICE_OPTION_SELECTED = "set_option_selected"
|
||||
SERVICE_PAUSE_PROGRAM = "pause_program"
|
||||
SERVICE_RESUME_PROGRAM = "resume_program"
|
||||
SERVICE_SELECT_PROGRAM = "select_program"
|
||||
SERVICE_SET_PROGRAM_AND_OPTIONS = "set_program_and_options"
|
||||
SERVICE_SETTING = "change_setting"
|
||||
SERVICE_START_PROGRAM = "start_program"
|
||||
|
||||
ATTR_AFFECTS_TO = "affects_to"
|
||||
ATTR_KEY = "key"
|
||||
ATTR_PROGRAM = "program"
|
||||
ATTR_UNIT = "unit"
|
||||
ATTR_VALUE = "value"
|
||||
|
||||
AFFECTS_TO_ACTIVE_PROGRAM = "active_program"
|
||||
|
||||
@@ -8,7 +8,6 @@ from typing import Any, cast
|
||||
from aiohomeconnect.client import Client as HomeConnectClient
|
||||
from aiohomeconnect.model import (
|
||||
ArrayOfOptions,
|
||||
CommandKey,
|
||||
Option,
|
||||
OptionKey,
|
||||
ProgramKey,
|
||||
@@ -21,7 +20,6 @@ from homeassistant.const import ATTR_DEVICE_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
|
||||
from .const import (
|
||||
AFFECTS_TO_ACTIVE_PROGRAM,
|
||||
@@ -29,18 +27,11 @@ from .const import (
|
||||
ATTR_AFFECTS_TO,
|
||||
ATTR_KEY,
|
||||
ATTR_PROGRAM,
|
||||
ATTR_UNIT,
|
||||
ATTR_VALUE,
|
||||
DOMAIN,
|
||||
PROGRAM_ENUM_OPTIONS,
|
||||
SERVICE_OPTION_ACTIVE,
|
||||
SERVICE_OPTION_SELECTED,
|
||||
SERVICE_PAUSE_PROGRAM,
|
||||
SERVICE_RESUME_PROGRAM,
|
||||
SERVICE_SELECT_PROGRAM,
|
||||
SERVICE_SET_PROGRAM_AND_OPTIONS,
|
||||
SERVICE_SETTING,
|
||||
SERVICE_START_PROGRAM,
|
||||
TRANSLATION_KEYS_PROGRAMS_MAP,
|
||||
)
|
||||
from .coordinator import HomeConnectConfigEntry
|
||||
@@ -88,43 +79,6 @@ SERVICE_SETTING_SCHEMA = vol.Schema(
|
||||
}
|
||||
)
|
||||
|
||||
# DEPRECATED: Remove in 2025.9.0
|
||||
SERVICE_OPTION_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_DEVICE_ID): str,
|
||||
vol.Required(ATTR_KEY): vol.All(
|
||||
vol.Coerce(OptionKey),
|
||||
vol.NotIn([OptionKey.UNKNOWN]),
|
||||
),
|
||||
vol.Required(ATTR_VALUE): vol.Any(str, int, bool),
|
||||
vol.Optional(ATTR_UNIT): str,
|
||||
}
|
||||
)
|
||||
|
||||
# DEPRECATED: Remove in 2025.9.0
|
||||
SERVICE_PROGRAM_SCHEMA = vol.Any(
|
||||
{
|
||||
vol.Required(ATTR_DEVICE_ID): str,
|
||||
vol.Required(ATTR_PROGRAM): vol.All(
|
||||
vol.Coerce(ProgramKey),
|
||||
vol.NotIn([ProgramKey.UNKNOWN]),
|
||||
),
|
||||
vol.Required(ATTR_KEY): vol.All(
|
||||
vol.Coerce(OptionKey),
|
||||
vol.NotIn([OptionKey.UNKNOWN]),
|
||||
),
|
||||
vol.Required(ATTR_VALUE): vol.Any(int, str),
|
||||
vol.Optional(ATTR_UNIT): str,
|
||||
},
|
||||
{
|
||||
vol.Required(ATTR_DEVICE_ID): str,
|
||||
vol.Required(ATTR_PROGRAM): vol.All(
|
||||
vol.Coerce(ProgramKey),
|
||||
vol.NotIn([ProgramKey.UNKNOWN]),
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def _require_program_or_at_least_one_option(data: dict) -> dict:
|
||||
if ATTR_PROGRAM not in data and not any(
|
||||
@@ -216,205 +170,6 @@ async def _get_client_and_ha_id(
|
||||
return entry.runtime_data.client, ha_id
|
||||
|
||||
|
||||
async def _async_service_program(call: ServiceCall, start: bool) -> None:
|
||||
"""Execute calls to services taking a program."""
|
||||
program = call.data[ATTR_PROGRAM]
|
||||
client, ha_id = await _get_client_and_ha_id(call.hass, call.data[ATTR_DEVICE_ID])
|
||||
|
||||
option_key = call.data.get(ATTR_KEY)
|
||||
options = (
|
||||
[
|
||||
Option(
|
||||
option_key,
|
||||
call.data[ATTR_VALUE],
|
||||
unit=call.data.get(ATTR_UNIT),
|
||||
)
|
||||
]
|
||||
if option_key is not None
|
||||
else None
|
||||
)
|
||||
|
||||
async_create_issue(
|
||||
call.hass,
|
||||
DOMAIN,
|
||||
"deprecated_set_program_and_option_actions",
|
||||
breaks_in_ha_version="2025.9.0",
|
||||
is_fixable=True,
|
||||
is_persistent=True,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_set_program_and_option_actions",
|
||||
translation_placeholders={
|
||||
"new_action_key": SERVICE_SET_PROGRAM_AND_OPTIONS,
|
||||
"remove_release": "2025.9.0",
|
||||
"deprecated_action_yaml": "\n".join(
|
||||
[
|
||||
"```yaml",
|
||||
f"action: {DOMAIN}.{SERVICE_START_PROGRAM if start else SERVICE_SELECT_PROGRAM}",
|
||||
"data:",
|
||||
f" {ATTR_DEVICE_ID}: DEVICE_ID",
|
||||
f" {ATTR_PROGRAM}: {program}",
|
||||
*([f" {ATTR_KEY}: {options[0].key}"] if options else []),
|
||||
*([f" {ATTR_VALUE}: {options[0].value}"] if options else []),
|
||||
*(
|
||||
[f" {ATTR_UNIT}: {options[0].unit}"]
|
||||
if options and options[0].unit
|
||||
else []
|
||||
),
|
||||
"```",
|
||||
]
|
||||
),
|
||||
"new_action_yaml": "\n ".join(
|
||||
[
|
||||
"```yaml",
|
||||
f"action: {DOMAIN}.{SERVICE_SET_PROGRAM_AND_OPTIONS}",
|
||||
"data:",
|
||||
f" {ATTR_DEVICE_ID}: DEVICE_ID",
|
||||
f" {ATTR_AFFECTS_TO}: {AFFECTS_TO_ACTIVE_PROGRAM if start else AFFECTS_TO_SELECTED_PROGRAM}",
|
||||
f" {ATTR_PROGRAM}: {bsh_key_to_translation_key(program.value)}",
|
||||
*(
|
||||
[
|
||||
f" {bsh_key_to_translation_key(options[0].key)}: {options[0].value}"
|
||||
]
|
||||
if options
|
||||
else []
|
||||
),
|
||||
"```",
|
||||
]
|
||||
),
|
||||
"repo_link": "[aiohomeconnect](https://github.com/MartinHjelmare/aiohomeconnect)",
|
||||
},
|
||||
)
|
||||
|
||||
try:
|
||||
if start:
|
||||
await client.start_program(ha_id, program_key=program, options=options)
|
||||
else:
|
||||
await client.set_selected_program(
|
||||
ha_id, program_key=program, options=options
|
||||
)
|
||||
except HomeConnectError as err:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="start_program" if start else "select_program",
|
||||
translation_placeholders={
|
||||
**get_dict_from_home_connect_error(err),
|
||||
"program": program,
|
||||
},
|
||||
) from err
|
||||
|
||||
|
||||
async def _async_service_set_program_options(call: ServiceCall, active: bool) -> None:
|
||||
"""Execute calls to services taking a program."""
|
||||
option_key = call.data[ATTR_KEY]
|
||||
value = call.data[ATTR_VALUE]
|
||||
unit = call.data.get(ATTR_UNIT)
|
||||
client, ha_id = await _get_client_and_ha_id(call.hass, call.data[ATTR_DEVICE_ID])
|
||||
|
||||
async_create_issue(
|
||||
call.hass,
|
||||
DOMAIN,
|
||||
"deprecated_set_program_and_option_actions",
|
||||
breaks_in_ha_version="2025.9.0",
|
||||
is_fixable=True,
|
||||
is_persistent=True,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_set_program_and_option_actions",
|
||||
translation_placeholders={
|
||||
"new_action_key": SERVICE_SET_PROGRAM_AND_OPTIONS,
|
||||
"remove_release": "2025.9.0",
|
||||
"deprecated_action_yaml": "\n".join(
|
||||
[
|
||||
"```yaml",
|
||||
f"action: {DOMAIN}.{SERVICE_OPTION_ACTIVE if active else SERVICE_OPTION_SELECTED}",
|
||||
"data:",
|
||||
f" {ATTR_DEVICE_ID}: DEVICE_ID",
|
||||
f" {ATTR_KEY}: {option_key}",
|
||||
f" {ATTR_VALUE}: {value}",
|
||||
*([f" {ATTR_UNIT}: {unit}"] if unit else []),
|
||||
"```",
|
||||
]
|
||||
),
|
||||
"new_action_yaml": "\n ".join(
|
||||
[
|
||||
"```yaml",
|
||||
f"action: {DOMAIN}.{SERVICE_SET_PROGRAM_AND_OPTIONS}",
|
||||
"data:",
|
||||
f" {ATTR_DEVICE_ID}: DEVICE_ID",
|
||||
f" {ATTR_AFFECTS_TO}: {AFFECTS_TO_ACTIVE_PROGRAM if active else AFFECTS_TO_SELECTED_PROGRAM}",
|
||||
f" {bsh_key_to_translation_key(option_key)}: {value}",
|
||||
"```",
|
||||
]
|
||||
),
|
||||
"repo_link": "[aiohomeconnect](https://github.com/MartinHjelmare/aiohomeconnect)",
|
||||
},
|
||||
)
|
||||
try:
|
||||
if active:
|
||||
await client.set_active_program_option(
|
||||
ha_id,
|
||||
option_key=option_key,
|
||||
value=value,
|
||||
unit=unit,
|
||||
)
|
||||
else:
|
||||
await client.set_selected_program_option(
|
||||
ha_id,
|
||||
option_key=option_key,
|
||||
value=value,
|
||||
unit=unit,
|
||||
)
|
||||
except HomeConnectError as err:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="set_options_active_program"
|
||||
if active
|
||||
else "set_options_selected_program",
|
||||
translation_placeholders={
|
||||
**get_dict_from_home_connect_error(err),
|
||||
"key": option_key,
|
||||
"value": str(value),
|
||||
},
|
||||
) from err
|
||||
|
||||
|
||||
async def _async_service_command(call: ServiceCall, command_key: CommandKey) -> None:
|
||||
"""Execute calls to services executing a command."""
|
||||
client, ha_id = await _get_client_and_ha_id(call.hass, call.data[ATTR_DEVICE_ID])
|
||||
|
||||
async_create_issue(
|
||||
call.hass,
|
||||
DOMAIN,
|
||||
"deprecated_command_actions",
|
||||
breaks_in_ha_version="2025.9.0",
|
||||
is_fixable=True,
|
||||
is_persistent=True,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_command_actions",
|
||||
)
|
||||
|
||||
try:
|
||||
await client.put_command(ha_id, command_key=command_key, value=True)
|
||||
except HomeConnectError as err:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="execute_command",
|
||||
translation_placeholders={
|
||||
**get_dict_from_home_connect_error(err),
|
||||
"command": command_key.value,
|
||||
},
|
||||
) from err
|
||||
|
||||
|
||||
async def async_service_option_active(call: ServiceCall) -> None:
|
||||
"""Service for setting an option for an active program."""
|
||||
await _async_service_set_program_options(call, True)
|
||||
|
||||
|
||||
async def async_service_option_selected(call: ServiceCall) -> None:
|
||||
"""Service for setting an option for a selected program."""
|
||||
await _async_service_set_program_options(call, False)
|
||||
|
||||
|
||||
async def async_service_setting(call: ServiceCall) -> None:
|
||||
"""Service for changing a setting."""
|
||||
key = call.data[ATTR_KEY]
|
||||
@@ -435,21 +190,6 @@ async def async_service_setting(call: ServiceCall) -> None:
|
||||
) from err
|
||||
|
||||
|
||||
async def async_service_pause_program(call: ServiceCall) -> None:
|
||||
"""Service for pausing a program."""
|
||||
await _async_service_command(call, CommandKey.BSH_COMMON_PAUSE_PROGRAM)
|
||||
|
||||
|
||||
async def async_service_resume_program(call: ServiceCall) -> None:
|
||||
"""Service for resuming a paused program."""
|
||||
await _async_service_command(call, CommandKey.BSH_COMMON_RESUME_PROGRAM)
|
||||
|
||||
|
||||
async def async_service_select_program(call: ServiceCall) -> None:
|
||||
"""Service for selecting a program."""
|
||||
await _async_service_program(call, False)
|
||||
|
||||
|
||||
async def async_service_set_program_and_options(call: ServiceCall) -> None:
|
||||
"""Service for setting a program and options."""
|
||||
data = dict(call.data)
|
||||
@@ -517,54 +257,13 @@ async def async_service_set_program_and_options(call: ServiceCall) -> None:
|
||||
) from err
|
||||
|
||||
|
||||
async def async_service_start_program(call: ServiceCall) -> None:
|
||||
"""Service for starting a program."""
|
||||
await _async_service_program(call, True)
|
||||
|
||||
|
||||
@callback
|
||||
def async_setup_services(hass: HomeAssistant) -> None:
|
||||
"""Register custom actions."""
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_OPTION_ACTIVE,
|
||||
async_service_option_active,
|
||||
schema=SERVICE_OPTION_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_OPTION_SELECTED,
|
||||
async_service_option_selected,
|
||||
schema=SERVICE_OPTION_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SETTING, async_service_setting, schema=SERVICE_SETTING_SCHEMA
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_PAUSE_PROGRAM,
|
||||
async_service_pause_program,
|
||||
schema=SERVICE_COMMAND_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_RESUME_PROGRAM,
|
||||
async_service_resume_program,
|
||||
schema=SERVICE_COMMAND_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_SELECT_PROGRAM,
|
||||
async_service_select_program,
|
||||
schema=SERVICE_PROGRAM_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_START_PROGRAM,
|
||||
async_service_start_program,
|
||||
schema=SERVICE_PROGRAM_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_SET_PROGRAM_AND_OPTIONS,
|
||||
|
||||
@@ -1,51 +1,3 @@
|
||||
start_program:
|
||||
fields:
|
||||
device_id:
|
||||
required: true
|
||||
selector:
|
||||
device:
|
||||
integration: home_connect
|
||||
program:
|
||||
example: "Dishcare.Dishwasher.Program.Auto2"
|
||||
required: true
|
||||
selector:
|
||||
text:
|
||||
key:
|
||||
example: "BSH.Common.Option.StartInRelative"
|
||||
selector:
|
||||
text:
|
||||
value:
|
||||
example: 1800
|
||||
selector:
|
||||
object:
|
||||
unit:
|
||||
example: "seconds"
|
||||
selector:
|
||||
text:
|
||||
select_program:
|
||||
fields:
|
||||
device_id:
|
||||
required: true
|
||||
selector:
|
||||
device:
|
||||
integration: home_connect
|
||||
program:
|
||||
example: "Dishcare.Dishwasher.Program.Auto2"
|
||||
required: true
|
||||
selector:
|
||||
text:
|
||||
key:
|
||||
example: "BSH.Common.Option.StartInRelative"
|
||||
selector:
|
||||
text:
|
||||
value:
|
||||
example: 1800
|
||||
selector:
|
||||
object:
|
||||
unit:
|
||||
example: "seconds"
|
||||
selector:
|
||||
text:
|
||||
set_program_and_options:
|
||||
fields:
|
||||
device_id:
|
||||
@@ -599,54 +551,6 @@ set_program_and_options:
|
||||
- laundry_care_common_enum_type_vario_perfect_off
|
||||
- laundry_care_common_enum_type_vario_perfect_eco_perfect
|
||||
- laundry_care_common_enum_type_vario_perfect_speed_perfect
|
||||
pause_program:
|
||||
fields:
|
||||
device_id:
|
||||
required: true
|
||||
selector:
|
||||
device:
|
||||
integration: home_connect
|
||||
resume_program:
|
||||
fields:
|
||||
device_id:
|
||||
required: true
|
||||
selector:
|
||||
device:
|
||||
integration: home_connect
|
||||
set_option_active:
|
||||
fields:
|
||||
device_id:
|
||||
required: true
|
||||
selector:
|
||||
device:
|
||||
integration: home_connect
|
||||
key:
|
||||
example: "LaundryCare.Dryer.Option.DryingTarget"
|
||||
required: true
|
||||
selector:
|
||||
text:
|
||||
value:
|
||||
example: "LaundryCare.Dryer.EnumType.DryingTarget.IronDry"
|
||||
required: true
|
||||
selector:
|
||||
object:
|
||||
set_option_selected:
|
||||
fields:
|
||||
device_id:
|
||||
required: true
|
||||
selector:
|
||||
device:
|
||||
integration: home_connect
|
||||
key:
|
||||
example: "LaundryCare.Dryer.Option.DryingTarget"
|
||||
required: true
|
||||
selector:
|
||||
text:
|
||||
value:
|
||||
example: "LaundryCare.Dryer.EnumType.DryingTarget.IronDry"
|
||||
required: true
|
||||
selector:
|
||||
object:
|
||||
change_setting:
|
||||
fields:
|
||||
device_id:
|
||||
|
||||
@@ -145,28 +145,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated_command_actions": {
|
||||
"title": "The command related actions are deprecated in favor of the new buttons",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"title": "[%key:component::home_connect::issues::deprecated_command_actions::title%]",
|
||||
"description": "The `pause_program` and `resume_program` actions have been deprecated in favor of new button entities, if the command is available for your appliance. Please update your automations, scripts and panels that use this action to use the button entities instead, and press on submit to fix the issue."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated_set_program_and_option_actions": {
|
||||
"title": "The executed action is deprecated",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"title": "[%key:component::home_connect::issues::deprecated_set_program_and_option_actions::title%]",
|
||||
"description": "`start_program`, `select_program`, `set_option_active`, and `set_option_selected` actions are deprecated and will be removed in the {remove_release} release, please use the `{new_action_key}` action instead. For the executed action:\n{deprecated_action_yaml}\nyou can do the following transformation using the recognized options:\n {new_action_yaml}\nIf the option is not in the recognized options, please submit an issue or a pull request requesting the addition of the option at {repo_link}."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
@@ -517,49 +495,6 @@
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"start_program": {
|
||||
"name": "Start program",
|
||||
"description": "Selects a program and starts it.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::name%]",
|
||||
"description": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::description%]"
|
||||
},
|
||||
"program": { "name": "Program", "description": "Program to select." },
|
||||
"key": { "name": "Option key", "description": "Key of the option." },
|
||||
"value": {
|
||||
"name": "Option value",
|
||||
"description": "Value of the option."
|
||||
},
|
||||
"unit": { "name": "Option unit", "description": "Unit for the option." }
|
||||
}
|
||||
},
|
||||
"select_program": {
|
||||
"name": "Select program",
|
||||
"description": "Selects a program without starting it.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::name%]",
|
||||
"description": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::description%]"
|
||||
},
|
||||
"program": {
|
||||
"name": "[%key:component::home_connect::services::start_program::fields::program::name%]",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::program::description%]"
|
||||
},
|
||||
"key": {
|
||||
"name": "[%key:component::home_connect::services::start_program::fields::key::name%]",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::key::description%]"
|
||||
},
|
||||
"value": {
|
||||
"name": "[%key:component::home_connect::services::start_program::fields::value::name%]",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::value::description%]"
|
||||
},
|
||||
"unit": {
|
||||
"name": "[%key:component::home_connect::services::start_program::fields::unit::name%]",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::unit::description%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"set_program_and_options": {
|
||||
"name": "Set program and options",
|
||||
"description": "Starts or selects a program with options or sets the options for the active or the selected program.",
|
||||
@@ -744,62 +679,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"pause_program": {
|
||||
"name": "Pause program",
|
||||
"description": "Pauses the current running program.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::name%]",
|
||||
"description": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::description%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resume_program": {
|
||||
"name": "Resume program",
|
||||
"description": "Resumes a paused program.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::name%]",
|
||||
"description": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::description%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"set_option_active": {
|
||||
"name": "Set active program option",
|
||||
"description": "Sets an option for the active program.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::name%]",
|
||||
"description": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::description%]"
|
||||
},
|
||||
"key": {
|
||||
"name": "Key",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::key::description%]"
|
||||
},
|
||||
"value": {
|
||||
"name": "Value",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::value::description%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"set_option_selected": {
|
||||
"name": "Set selected program option",
|
||||
"description": "Sets options for the selected program.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::name%]",
|
||||
"description": "[%key:component::home_connect::services::set_program_and_options::fields::device_id::description%]"
|
||||
},
|
||||
"key": {
|
||||
"name": "[%key:component::home_connect::services::start_program::fields::key::name%]",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::key::description%]"
|
||||
},
|
||||
"value": {
|
||||
"name": "[%key:component::home_connect::services::start_program::fields::value::name%]",
|
||||
"description": "[%key:component::home_connect::services::start_program::fields::value::description%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"change_setting": {
|
||||
"name": "Change setting",
|
||||
"description": "Changes a setting.",
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
"""Tests for the Home Connect actions."""
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from http import HTTPStatus
|
||||
from typing import Any
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from aiohomeconnect.model import HomeAppliance, OptionKey, ProgramKey, SettingKey
|
||||
from aiohomeconnect.model import HomeAppliance, SettingKey
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
@@ -14,37 +13,10 @@ from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
import homeassistant.helpers.issue_registry as ir
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
DEPRECATED_SERVICE_KV_CALL_PARAMS = [
|
||||
{
|
||||
"domain": DOMAIN,
|
||||
"service": "set_option_active",
|
||||
"service_data": {
|
||||
"device_id": "DEVICE_ID",
|
||||
"key": OptionKey.BSH_COMMON_FINISH_IN_RELATIVE.value,
|
||||
"value": 43200,
|
||||
"unit": "seconds",
|
||||
},
|
||||
"blocking": True,
|
||||
},
|
||||
{
|
||||
"domain": DOMAIN,
|
||||
"service": "set_option_selected",
|
||||
"service_data": {
|
||||
"device_id": "DEVICE_ID",
|
||||
"key": OptionKey.LAUNDRY_CARE_WASHER_TEMPERATURE.value,
|
||||
"value": "LaundryCare.Washer.EnumType.Temperature.GC40",
|
||||
},
|
||||
"blocking": True,
|
||||
},
|
||||
]
|
||||
|
||||
SERVICE_KV_CALL_PARAMS = [
|
||||
*DEPRECATED_SERVICE_KV_CALL_PARAMS,
|
||||
{
|
||||
"domain": DOMAIN,
|
||||
"service": "change_setting",
|
||||
@@ -57,70 +29,13 @@ SERVICE_KV_CALL_PARAMS = [
|
||||
},
|
||||
]
|
||||
|
||||
SERVICE_COMMAND_CALL_PARAMS = [
|
||||
{
|
||||
"domain": DOMAIN,
|
||||
"service": "pause_program",
|
||||
"service_data": {
|
||||
"device_id": "DEVICE_ID",
|
||||
},
|
||||
"blocking": True,
|
||||
},
|
||||
{
|
||||
"domain": DOMAIN,
|
||||
"service": "resume_program",
|
||||
"service_data": {
|
||||
"device_id": "DEVICE_ID",
|
||||
},
|
||||
"blocking": True,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
SERVICE_PROGRAM_CALL_PARAMS = [
|
||||
{
|
||||
"domain": DOMAIN,
|
||||
"service": "select_program",
|
||||
"service_data": {
|
||||
"device_id": "DEVICE_ID",
|
||||
"program": ProgramKey.LAUNDRY_CARE_WASHER_COTTON.value,
|
||||
"key": OptionKey.LAUNDRY_CARE_WASHER_TEMPERATURE.value,
|
||||
"value": "LaundryCare.Washer.EnumType.Temperature.GC40",
|
||||
},
|
||||
"blocking": True,
|
||||
},
|
||||
{
|
||||
"domain": DOMAIN,
|
||||
"service": "start_program",
|
||||
"service_data": {
|
||||
"device_id": "DEVICE_ID",
|
||||
"program": ProgramKey.LAUNDRY_CARE_WASHER_COTTON.value,
|
||||
"key": OptionKey.BSH_COMMON_FINISH_IN_RELATIVE.value,
|
||||
"value": 43200,
|
||||
"unit": "seconds",
|
||||
},
|
||||
"blocking": True,
|
||||
},
|
||||
]
|
||||
|
||||
SERVICE_APPLIANCE_METHOD_MAPPING = {
|
||||
"set_option_active": "set_active_program_option",
|
||||
"set_option_selected": "set_selected_program_option",
|
||||
"change_setting": "set_setting",
|
||||
"pause_program": "put_command",
|
||||
"resume_program": "put_command",
|
||||
"select_program": "set_selected_program",
|
||||
"start_program": "start_program",
|
||||
}
|
||||
|
||||
SERVICE_VALIDATION_ERROR_MAPPING = {
|
||||
"set_option_active": r"Error.*setting.*options.*active.*program.*",
|
||||
"set_option_selected": r"Error.*setting.*options.*selected.*program.*",
|
||||
"change_setting": r"Error.*assigning.*value.*setting.*",
|
||||
"pause_program": r"Error.*executing.*command.*",
|
||||
"resume_program": r"Error.*executing.*command.*",
|
||||
"select_program": r"Error.*selecting.*program.*",
|
||||
"start_program": r"Error.*starting.*program.*",
|
||||
}
|
||||
|
||||
|
||||
@@ -171,10 +86,7 @@ SERVICES_SET_PROGRAM_AND_OPTIONS = [
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"service_call",
|
||||
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
|
||||
)
|
||||
@pytest.mark.parametrize("service_call", SERVICE_KV_CALL_PARAMS)
|
||||
async def test_key_value_services(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
@@ -202,81 +114,6 @@ async def test_key_value_services(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("service_call", "issue_id"),
|
||||
[
|
||||
*zip(
|
||||
DEPRECATED_SERVICE_KV_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
|
||||
["deprecated_set_program_and_option_actions"]
|
||||
* (
|
||||
len(DEPRECATED_SERVICE_KV_CALL_PARAMS)
|
||||
+ len(SERVICE_PROGRAM_CALL_PARAMS)
|
||||
),
|
||||
strict=True,
|
||||
),
|
||||
*zip(
|
||||
SERVICE_COMMAND_CALL_PARAMS,
|
||||
["deprecated_command_actions"] * len(SERVICE_COMMAND_CALL_PARAMS),
|
||||
strict=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_programs_and_options_actions_deprecation(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
client: MagicMock,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
appliance: HomeAppliance,
|
||||
service_call: dict[str, Any],
|
||||
issue_id: str,
|
||||
) -> None:
|
||||
"""Test deprecated service keys."""
|
||||
assert await integration_setup(client)
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
device_entry = device_registry.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
identifiers={(DOMAIN, appliance.ha_id)},
|
||||
)
|
||||
|
||||
service_call["service_data"]["device_id"] = device_entry.id
|
||||
await hass.services.async_call(**service_call)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert issue
|
||||
|
||||
_client = await hass_client()
|
||||
resp = await _client.post(
|
||||
"/api/repairs/issues/fix",
|
||||
json={"handler": DOMAIN, "issue_id": issue.issue_id},
|
||||
)
|
||||
assert resp.status == HTTPStatus.OK
|
||||
flow_id = (await resp.json())["flow_id"]
|
||||
resp = await _client.post(f"/api/repairs/issues/fix/{flow_id}")
|
||||
|
||||
assert not issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
await hass.services.async_call(**service_call)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
assert issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
|
||||
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert the issue is no longer present
|
||||
assert not issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("service_call", "called_method"),
|
||||
@@ -360,7 +197,7 @@ async def test_set_program_and_options_exceptions(
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"service_call",
|
||||
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
|
||||
SERVICE_KV_CALL_PARAMS,
|
||||
)
|
||||
async def test_services_exception_device_id(
|
||||
hass: HomeAssistant,
|
||||
@@ -430,7 +267,7 @@ async def test_services_appliance_not_found(
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"service_call",
|
||||
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
|
||||
SERVICE_KV_CALL_PARAMS,
|
||||
)
|
||||
async def test_services_exception(
|
||||
hass: HomeAssistant,
|
||||
|
||||
Reference in New Issue
Block a user