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>pull/136951/head^2
parent
889fe05a48
commit
efcfd97d1b
|
@ -1,9 +1,13 @@
|
|||
"""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.error import HomeConnectError
|
||||
from aiohomeconnect.model.program import Execution
|
||||
|
||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -29,14 +33,38 @@ PROGRAMS_TRANSLATION_KEYS_MAP = {
|
|||
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 = (
|
||||
SelectEntityDescription(
|
||||
HomeConnectProgramSelectEntityDescription(
|
||||
key=EventKey.BSH_COMMON_ROOT_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,
|
||||
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):
|
||||
"""Select class for Home Connect programs."""
|
||||
|
||||
entity_description: HomeConnectProgramSelectEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: HomeConnectCoordinator,
|
||||
appliance: HomeConnectApplianceData,
|
||||
desc: SelectEntityDescription,
|
||||
desc: HomeConnectProgramSelectEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the entity."""
|
||||
super().__init__(
|
||||
|
@ -75,8 +105,11 @@ class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity):
|
|||
PROGRAMS_TRANSLATION_KEYS_MAP[program.key]
|
||||
for program in appliance.programs
|
||||
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
|
||||
|
||||
def update_native_value(self) -> None:
|
||||
|
@ -92,22 +125,15 @@ class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity):
|
|||
"""Select new program."""
|
||||
program_key = TRANSLATION_KEYS_PROGRAMS_MAP[option]
|
||||
try:
|
||||
if self.start_on_select:
|
||||
await self.coordinator.client.start_program(
|
||||
self.appliance.info.ha_id, program_key=program_key
|
||||
)
|
||||
else:
|
||||
await self.coordinator.client.set_selected_program(
|
||||
self.appliance.info.ha_id, program_key=program_key
|
||||
)
|
||||
await self.entity_description.set_program_fn(
|
||||
self.coordinator.client,
|
||||
self.appliance.info.ha_id,
|
||||
program_key,
|
||||
)
|
||||
except HomeConnectError as err:
|
||||
if self.start_on_select:
|
||||
translation_key = "start_program"
|
||||
else:
|
||||
translation_key = "select_program"
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key=translation_key,
|
||||
translation_key=self.entity_description.error_translation_key,
|
||||
translation_placeholders={
|
||||
**get_dict_from_home_connect_error(err),
|
||||
SVE_TRANSLATION_PLACEHOLDER_PROGRAM: program_key.value,
|
||||
|
|
|
@ -13,7 +13,11 @@ from aiohomeconnect.model import (
|
|||
ProgramKey,
|
||||
)
|
||||
from aiohomeconnect.model.error import HomeConnectError
|
||||
from aiohomeconnect.model.program import EnumerateProgram
|
||||
from aiohomeconnect.model.program import (
|
||||
EnumerateProgram,
|
||||
EnumerateProgramConstraints,
|
||||
Execution,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.select import (
|
||||
|
@ -53,25 +57,42 @@ async def test_select(
|
|||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_filter_unknown_programs(
|
||||
async def test_filter_programs(
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
setup_credentials: None,
|
||||
client: MagicMock,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> 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.return_value = ArrayOfPrograms(
|
||||
[
|
||||
EnumerateProgram(
|
||||
key=ProgramKey.DISHCARE_DISHWASHER_ECO_50,
|
||||
raw_key=ProgramKey.DISHCARE_DISHWASHER_ECO_50.value,
|
||||
constraints=EnumerateProgramConstraints(
|
||||
execution=Execution.SELECT_ONLY,
|
||||
),
|
||||
),
|
||||
EnumerateProgram(
|
||||
key=ProgramKey.UNKNOWN,
|
||||
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")
|
||||
assert entity
|
||||
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(
|
||||
|
|
Loading…
Reference in New Issue