mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 07:07:28 +00:00
Filter programs by execution type at select program entities at Home Connect (#136950)
* Filter programs by execution type at select program entities * Suggestions and improvements Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Use function and translation key at select program entity description * Fix select entity description docstring --------- Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
889fe05a48
commit
efcfd97d1b
@ -1,9 +1,13 @@
|
|||||||
"""Provides a select platform for Home Connect."""
|
"""Provides a select platform for Home Connect."""
|
||||||
|
|
||||||
from typing import cast
|
from collections.abc import Callable, Coroutine
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
|
from aiohomeconnect.client import Client as HomeConnectClient
|
||||||
from aiohomeconnect.model import EventKey, ProgramKey
|
from aiohomeconnect.model import EventKey, ProgramKey
|
||||||
from aiohomeconnect.model.error import HomeConnectError
|
from aiohomeconnect.model.error import HomeConnectError
|
||||||
|
from aiohomeconnect.model.program import Execution
|
||||||
|
|
||||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -29,14 +33,38 @@ PROGRAMS_TRANSLATION_KEYS_MAP = {
|
|||||||
value: key for key, value in TRANSLATION_KEYS_PROGRAMS_MAP.items()
|
value: key for key, value in TRANSLATION_KEYS_PROGRAMS_MAP.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, kw_only=True)
|
||||||
|
class HomeConnectProgramSelectEntityDescription(
|
||||||
|
SelectEntityDescription,
|
||||||
|
):
|
||||||
|
"""Entity Description class for select entities for programs."""
|
||||||
|
|
||||||
|
allowed_executions: tuple[Execution, ...]
|
||||||
|
set_program_fn: Callable[
|
||||||
|
[HomeConnectClient, str, ProgramKey], Coroutine[Any, Any, None]
|
||||||
|
]
|
||||||
|
error_translation_key: str
|
||||||
|
|
||||||
|
|
||||||
PROGRAM_SELECT_ENTITY_DESCRIPTIONS = (
|
PROGRAM_SELECT_ENTITY_DESCRIPTIONS = (
|
||||||
SelectEntityDescription(
|
HomeConnectProgramSelectEntityDescription(
|
||||||
key=EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM,
|
key=EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM,
|
||||||
translation_key="active_program",
|
translation_key="active_program",
|
||||||
|
allowed_executions=(Execution.SELECT_AND_START, Execution.START_ONLY),
|
||||||
|
set_program_fn=lambda client, ha_id, program_key: client.start_program(
|
||||||
|
ha_id, program_key=program_key
|
||||||
|
),
|
||||||
|
error_translation_key="start_program",
|
||||||
),
|
),
|
||||||
SelectEntityDescription(
|
HomeConnectProgramSelectEntityDescription(
|
||||||
key=EventKey.BSH_COMMON_ROOT_SELECTED_PROGRAM,
|
key=EventKey.BSH_COMMON_ROOT_SELECTED_PROGRAM,
|
||||||
translation_key="selected_program",
|
translation_key="selected_program",
|
||||||
|
allowed_executions=(Execution.SELECT_AND_START, Execution.SELECT_ONLY),
|
||||||
|
set_program_fn=lambda client, ha_id, program_key: client.set_selected_program(
|
||||||
|
ha_id, program_key=program_key
|
||||||
|
),
|
||||||
|
error_translation_key="select_program",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,11 +87,13 @@ async def async_setup_entry(
|
|||||||
class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity):
|
class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity):
|
||||||
"""Select class for Home Connect programs."""
|
"""Select class for Home Connect programs."""
|
||||||
|
|
||||||
|
entity_description: HomeConnectProgramSelectEntityDescription
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: HomeConnectCoordinator,
|
coordinator: HomeConnectCoordinator,
|
||||||
appliance: HomeConnectApplianceData,
|
appliance: HomeConnectApplianceData,
|
||||||
desc: SelectEntityDescription,
|
desc: HomeConnectProgramSelectEntityDescription,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -75,8 +105,11 @@ class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity):
|
|||||||
PROGRAMS_TRANSLATION_KEYS_MAP[program.key]
|
PROGRAMS_TRANSLATION_KEYS_MAP[program.key]
|
||||||
for program in appliance.programs
|
for program in appliance.programs
|
||||||
if program.key != ProgramKey.UNKNOWN
|
if program.key != ProgramKey.UNKNOWN
|
||||||
|
and (
|
||||||
|
program.constraints is None
|
||||||
|
or program.constraints.execution in desc.allowed_executions
|
||||||
|
)
|
||||||
]
|
]
|
||||||
self.start_on_select = desc.key == EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM
|
|
||||||
self._attr_current_option = None
|
self._attr_current_option = None
|
||||||
|
|
||||||
def update_native_value(self) -> None:
|
def update_native_value(self) -> None:
|
||||||
@ -92,22 +125,15 @@ class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity):
|
|||||||
"""Select new program."""
|
"""Select new program."""
|
||||||
program_key = TRANSLATION_KEYS_PROGRAMS_MAP[option]
|
program_key = TRANSLATION_KEYS_PROGRAMS_MAP[option]
|
||||||
try:
|
try:
|
||||||
if self.start_on_select:
|
await self.entity_description.set_program_fn(
|
||||||
await self.coordinator.client.start_program(
|
self.coordinator.client,
|
||||||
self.appliance.info.ha_id, program_key=program_key
|
self.appliance.info.ha_id,
|
||||||
)
|
program_key,
|
||||||
else:
|
)
|
||||||
await self.coordinator.client.set_selected_program(
|
|
||||||
self.appliance.info.ha_id, program_key=program_key
|
|
||||||
)
|
|
||||||
except HomeConnectError as err:
|
except HomeConnectError as err:
|
||||||
if self.start_on_select:
|
|
||||||
translation_key = "start_program"
|
|
||||||
else:
|
|
||||||
translation_key = "select_program"
|
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
translation_domain=DOMAIN,
|
translation_domain=DOMAIN,
|
||||||
translation_key=translation_key,
|
translation_key=self.entity_description.error_translation_key,
|
||||||
translation_placeholders={
|
translation_placeholders={
|
||||||
**get_dict_from_home_connect_error(err),
|
**get_dict_from_home_connect_error(err),
|
||||||
SVE_TRANSLATION_PLACEHOLDER_PROGRAM: program_key.value,
|
SVE_TRANSLATION_PLACEHOLDER_PROGRAM: program_key.value,
|
||||||
|
@ -13,7 +13,11 @@ from aiohomeconnect.model import (
|
|||||||
ProgramKey,
|
ProgramKey,
|
||||||
)
|
)
|
||||||
from aiohomeconnect.model.error import HomeConnectError
|
from aiohomeconnect.model.error import HomeConnectError
|
||||||
from aiohomeconnect.model.program import EnumerateProgram
|
from aiohomeconnect.model.program import (
|
||||||
|
EnumerateProgram,
|
||||||
|
EnumerateProgramConstraints,
|
||||||
|
Execution,
|
||||||
|
)
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.select import (
|
from homeassistant.components.select import (
|
||||||
@ -53,25 +57,42 @@ async def test_select(
|
|||||||
assert config_entry.state is ConfigEntryState.LOADED
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
|
||||||
async def test_filter_unknown_programs(
|
async def test_filter_programs(
|
||||||
config_entry: MockConfigEntry,
|
config_entry: MockConfigEntry,
|
||||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||||
setup_credentials: None,
|
setup_credentials: None,
|
||||||
client: MagicMock,
|
client: MagicMock,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test select that only known programs are shown."""
|
"""Test select that only right programs are shown."""
|
||||||
client.get_all_programs.side_effect = None
|
client.get_all_programs.side_effect = None
|
||||||
client.get_all_programs.return_value = ArrayOfPrograms(
|
client.get_all_programs.return_value = ArrayOfPrograms(
|
||||||
[
|
[
|
||||||
EnumerateProgram(
|
EnumerateProgram(
|
||||||
key=ProgramKey.DISHCARE_DISHWASHER_ECO_50,
|
key=ProgramKey.DISHCARE_DISHWASHER_ECO_50,
|
||||||
raw_key=ProgramKey.DISHCARE_DISHWASHER_ECO_50.value,
|
raw_key=ProgramKey.DISHCARE_DISHWASHER_ECO_50.value,
|
||||||
|
constraints=EnumerateProgramConstraints(
|
||||||
|
execution=Execution.SELECT_ONLY,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
EnumerateProgram(
|
EnumerateProgram(
|
||||||
key=ProgramKey.UNKNOWN,
|
key=ProgramKey.UNKNOWN,
|
||||||
raw_key="an unknown program",
|
raw_key="an unknown program",
|
||||||
),
|
),
|
||||||
|
EnumerateProgram(
|
||||||
|
key=ProgramKey.DISHCARE_DISHWASHER_QUICK_45,
|
||||||
|
raw_key=ProgramKey.DISHCARE_DISHWASHER_QUICK_45.value,
|
||||||
|
constraints=EnumerateProgramConstraints(
|
||||||
|
execution=Execution.START_ONLY,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
EnumerateProgram(
|
||||||
|
key=ProgramKey.DISHCARE_DISHWASHER_AUTO_1,
|
||||||
|
raw_key=ProgramKey.DISHCARE_DISHWASHER_AUTO_1.value,
|
||||||
|
constraints=EnumerateProgramConstraints(
|
||||||
|
execution=Execution.SELECT_AND_START,
|
||||||
|
),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -82,7 +103,18 @@ async def test_filter_unknown_programs(
|
|||||||
entity = entity_registry.async_get("select.dishwasher_selected_program")
|
entity = entity_registry.async_get("select.dishwasher_selected_program")
|
||||||
assert entity
|
assert entity
|
||||||
assert entity.capabilities
|
assert entity.capabilities
|
||||||
assert entity.capabilities[ATTR_OPTIONS] == ["dishcare_dishwasher_program_eco_50"]
|
assert entity.capabilities[ATTR_OPTIONS] == [
|
||||||
|
"dishcare_dishwasher_program_eco_50",
|
||||||
|
"dishcare_dishwasher_program_auto_1",
|
||||||
|
]
|
||||||
|
|
||||||
|
entity = entity_registry.async_get("select.dishwasher_active_program")
|
||||||
|
assert entity
|
||||||
|
assert entity.capabilities
|
||||||
|
assert entity.capabilities[ATTR_OPTIONS] == [
|
||||||
|
"dishcare_dishwasher_program_quick_45",
|
||||||
|
"dishcare_dishwasher_program_auto_1",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user