mirror of
https://github.com/home-assistant/core.git
synced 2025-08-30 09:51:37 +02:00
Remove deprecated services from home_connect
This commit is contained in:
@@ -8,7 +8,6 @@ from typing import Any, cast
|
|||||||
from aiohomeconnect.client import Client as HomeConnectClient
|
from aiohomeconnect.client import Client as HomeConnectClient
|
||||||
from aiohomeconnect.model import (
|
from aiohomeconnect.model import (
|
||||||
ArrayOfOptions,
|
ArrayOfOptions,
|
||||||
CommandKey,
|
|
||||||
Option,
|
Option,
|
||||||
OptionKey,
|
OptionKey,
|
||||||
ProgramKey,
|
ProgramKey,
|
||||||
@@ -21,7 +20,6 @@ from homeassistant.const import ATTR_DEVICE_ID
|
|||||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
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 (
|
from .const import (
|
||||||
AFFECTS_TO_ACTIVE_PROGRAM,
|
AFFECTS_TO_ACTIVE_PROGRAM,
|
||||||
@@ -29,18 +27,11 @@ from .const import (
|
|||||||
ATTR_AFFECTS_TO,
|
ATTR_AFFECTS_TO,
|
||||||
ATTR_KEY,
|
ATTR_KEY,
|
||||||
ATTR_PROGRAM,
|
ATTR_PROGRAM,
|
||||||
ATTR_UNIT,
|
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
PROGRAM_ENUM_OPTIONS,
|
PROGRAM_ENUM_OPTIONS,
|
||||||
SERVICE_OPTION_ACTIVE,
|
|
||||||
SERVICE_OPTION_SELECTED,
|
|
||||||
SERVICE_PAUSE_PROGRAM,
|
|
||||||
SERVICE_RESUME_PROGRAM,
|
|
||||||
SERVICE_SELECT_PROGRAM,
|
|
||||||
SERVICE_SET_PROGRAM_AND_OPTIONS,
|
SERVICE_SET_PROGRAM_AND_OPTIONS,
|
||||||
SERVICE_SETTING,
|
SERVICE_SETTING,
|
||||||
SERVICE_START_PROGRAM,
|
|
||||||
TRANSLATION_KEYS_PROGRAMS_MAP,
|
TRANSLATION_KEYS_PROGRAMS_MAP,
|
||||||
)
|
)
|
||||||
from .coordinator import HomeConnectConfigEntry
|
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:
|
def _require_program_or_at_least_one_option(data: dict) -> dict:
|
||||||
if ATTR_PROGRAM not in data and not any(
|
if ATTR_PROGRAM not in data and not any(
|
||||||
@@ -165,8 +119,6 @@ SERVICE_PROGRAM_AND_OPTIONS_SCHEMA = vol.All(
|
|||||||
_require_program_or_at_least_one_option,
|
_require_program_or_at_least_one_option,
|
||||||
)
|
)
|
||||||
|
|
||||||
SERVICE_COMMAND_SCHEMA = vol.Schema({vol.Required(ATTR_DEVICE_ID): str})
|
|
||||||
|
|
||||||
|
|
||||||
async def _get_client_and_ha_id(
|
async def _get_client_and_ha_id(
|
||||||
hass: HomeAssistant, device_id: str
|
hass: HomeAssistant, device_id: str
|
||||||
@@ -216,205 +168,6 @@ async def _get_client_and_ha_id(
|
|||||||
return entry.runtime_data.client, 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:
|
async def async_service_setting(call: ServiceCall) -> None:
|
||||||
"""Service for changing a setting."""
|
"""Service for changing a setting."""
|
||||||
key = call.data[ATTR_KEY]
|
key = call.data[ATTR_KEY]
|
||||||
@@ -435,21 +188,6 @@ async def async_service_setting(call: ServiceCall) -> None:
|
|||||||
) from err
|
) 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:
|
async def async_service_set_program_and_options(call: ServiceCall) -> None:
|
||||||
"""Service for setting a program and options."""
|
"""Service for setting a program and options."""
|
||||||
data = dict(call.data)
|
data = dict(call.data)
|
||||||
@@ -517,54 +255,13 @@ async def async_service_set_program_and_options(call: ServiceCall) -> None:
|
|||||||
) from err
|
) from err
|
||||||
|
|
||||||
|
|
||||||
async def async_service_start_program(call: ServiceCall) -> None:
|
|
||||||
"""Service for starting a program."""
|
|
||||||
await _async_service_program(call, True)
|
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_setup_services(hass: HomeAssistant) -> None:
|
def async_setup_services(hass: HomeAssistant) -> None:
|
||||||
"""Register custom actions."""
|
"""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(
|
hass.services.async_register(
|
||||||
DOMAIN, SERVICE_SETTING, async_service_setting, schema=SERVICE_SETTING_SCHEMA
|
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(
|
hass.services.async_register(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
SERVICE_SET_PROGRAM_AND_OPTIONS,
|
SERVICE_SET_PROGRAM_AND_OPTIONS,
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
"""Tests for the Home Connect actions."""
|
"""Tests for the Home Connect actions."""
|
||||||
|
|
||||||
from collections.abc import Awaitable, Callable
|
from collections.abc import Awaitable, Callable
|
||||||
from http import HTTPStatus
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from aiohomeconnect.model import HomeAppliance, OptionKey, ProgramKey, SettingKey
|
from aiohomeconnect.model import HomeAppliance, SettingKey
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
@@ -14,37 +13,10 @@ from homeassistant.config_entries import ConfigEntryState
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
import homeassistant.helpers.issue_registry as ir
|
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
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 = [
|
SERVICE_KV_CALL_PARAMS = [
|
||||||
*DEPRECATED_SERVICE_KV_CALL_PARAMS,
|
|
||||||
{
|
{
|
||||||
"domain": DOMAIN,
|
"domain": DOMAIN,
|
||||||
"service": "change_setting",
|
"service": "change_setting",
|
||||||
@@ -57,70 +29,17 @@ 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 = {
|
SERVICE_APPLIANCE_METHOD_MAPPING = {
|
||||||
"set_option_active": "set_active_program_option",
|
"set_option_active": "set_active_program_option",
|
||||||
"set_option_selected": "set_selected_program_option",
|
"set_option_selected": "set_selected_program_option",
|
||||||
"change_setting": "set_setting",
|
"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 = {
|
SERVICE_VALIDATION_ERROR_MAPPING = {
|
||||||
"set_option_active": r"Error.*setting.*options.*active.*program.*",
|
"set_option_active": r"Error.*setting.*options.*active.*program.*",
|
||||||
"set_option_selected": r"Error.*setting.*options.*selected.*program.*",
|
"set_option_selected": r"Error.*setting.*options.*selected.*program.*",
|
||||||
"change_setting": r"Error.*assigning.*value.*setting.*",
|
"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.*",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,7 +92,7 @@ SERVICES_SET_PROGRAM_AND_OPTIONS = [
|
|||||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"service_call",
|
"service_call",
|
||||||
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
|
SERVICE_KV_CALL_PARAMS,
|
||||||
)
|
)
|
||||||
async def test_key_value_services(
|
async def test_key_value_services(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@@ -202,81 +121,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("appliance", ["Washer"], indirect=True)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("service_call", "called_method"),
|
("service_call", "called_method"),
|
||||||
@@ -360,7 +204,7 @@ async def test_set_program_and_options_exceptions(
|
|||||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"service_call",
|
"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(
|
async def test_services_exception_device_id(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@@ -430,7 +274,7 @@ async def test_services_appliance_not_found(
|
|||||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"service_call",
|
"service_call",
|
||||||
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
|
SERVICE_KV_CALL_PARAMS,
|
||||||
)
|
)
|
||||||
async def test_services_exception(
|
async def test_services_exception(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
Reference in New Issue
Block a user