Fetch all programs instead of only the available ones at Home Connect (#136949)

Fetch all programs instead of only the available ones
This commit is contained in:
J. Diego Rodríguez Royo 2025-01-31 08:26:57 +01:00 committed by GitHub
parent 4613087e86
commit 4d4e11a0eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 35 additions and 49 deletions

View File

@ -25,7 +25,7 @@ from aiohomeconnect.model.error import (
HomeConnectError, HomeConnectError,
HomeConnectRequestError, HomeConnectRequestError,
) )
from aiohomeconnect.model.program import EnumerateAvailableProgram from aiohomeconnect.model.program import EnumerateProgram
from propcache.api import cached_property from propcache.api import cached_property
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -48,7 +48,7 @@ class HomeConnectApplianceData:
events: dict[EventKey, Event] = field(default_factory=dict) events: dict[EventKey, Event] = field(default_factory=dict)
info: HomeAppliance info: HomeAppliance
programs: list[EnumerateAvailableProgram] = field(default_factory=list) programs: list[EnumerateProgram] = field(default_factory=list)
settings: dict[SettingKey, GetSetting] settings: dict[SettingKey, GetSetting]
status: dict[StatusKey, Status] status: dict[StatusKey, Status]
@ -243,9 +243,7 @@ class HomeConnectCoordinator(
): ):
try: try:
appliance_data.programs.extend( appliance_data.programs.extend(
( (await self.client.get_all_programs(appliance.ha_id)).programs
await self.client.get_available_programs(appliance.ha_id)
).programs
) )
except HomeConnectError as error: except HomeConnectError as error:
_LOGGER.debug( _LOGGER.debug(

View File

@ -5,7 +5,7 @@ from typing import Any, cast
from aiohomeconnect.model import EventKey, ProgramKey, SettingKey from aiohomeconnect.model import EventKey, ProgramKey, SettingKey
from aiohomeconnect.model.error import HomeConnectError from aiohomeconnect.model.error import HomeConnectError
from aiohomeconnect.model.program import EnumerateAvailableProgram from aiohomeconnect.model.program import EnumerateProgram
from homeassistant.components.automation import automations_with_entity from homeassistant.components.automation import automations_with_entity
from homeassistant.components.script import scripts_with_entity from homeassistant.components.script import scripts_with_entity
@ -184,7 +184,7 @@ class HomeConnectProgramSwitch(HomeConnectEntity, SwitchEntity):
self, self,
coordinator: HomeConnectCoordinator, coordinator: HomeConnectCoordinator,
appliance: HomeConnectApplianceData, appliance: HomeConnectApplianceData,
program: EnumerateAvailableProgram, program: EnumerateProgram,
) -> None: ) -> None:
"""Initialize the entity.""" """Initialize the entity."""
desc = " ".join(["Program", program.key.split(".")[-1]]) desc = " ".join(["Program", program.key.split(".")[-1]])

View File

@ -9,9 +9,9 @@ from unittest.mock import AsyncMock, MagicMock, patch
from aiohomeconnect.client import Client as HomeConnectClient from aiohomeconnect.client import Client as HomeConnectClient
from aiohomeconnect.model import ( from aiohomeconnect.model import (
ArrayOfAvailablePrograms,
ArrayOfEvents, ArrayOfEvents,
ArrayOfHomeAppliances, ArrayOfHomeAppliances,
ArrayOfPrograms,
ArrayOfSettings, ArrayOfSettings,
ArrayOfStatus, ArrayOfStatus,
Event, Event,
@ -37,9 +37,7 @@ from tests.common import MockConfigEntry, load_json_object_fixture
MOCK_APPLIANCES = ArrayOfHomeAppliances.from_dict( MOCK_APPLIANCES = ArrayOfHomeAppliances.from_dict(
load_json_object_fixture("home_connect/appliances.json")["data"] load_json_object_fixture("home_connect/appliances.json")["data"]
) )
MOCK_PROGRAMS: dict[str, Any] = load_json_object_fixture( MOCK_PROGRAMS: dict[str, Any] = load_json_object_fixture("home_connect/programs.json")
"home_connect/programs-available.json"
)
MOCK_SETTINGS: dict[str, Any] = load_json_object_fixture("home_connect/settings.json") MOCK_SETTINGS: dict[str, Any] = load_json_object_fixture("home_connect/settings.json")
MOCK_STATUS = ArrayOfStatus.from_dict( MOCK_STATUS = ArrayOfStatus.from_dict(
load_json_object_fixture("home_connect/status.json")["data"] load_json_object_fixture("home_connect/status.json")["data"]
@ -219,8 +217,8 @@ def _get_set_key_value_side_effect(
return set_key_value_side_effect return set_key_value_side_effect
async def _get_available_programs_side_effect(ha_id: str) -> ArrayOfAvailablePrograms: async def _get_all_programs_side_effect(ha_id: str) -> ArrayOfPrograms:
"""Get available programs.""" """Get all programs."""
appliance_type = next( appliance_type = next(
appliance appliance
for appliance in MOCK_APPLIANCES.homeappliances for appliance in MOCK_APPLIANCES.homeappliances
@ -229,7 +227,7 @@ async def _get_available_programs_side_effect(ha_id: str) -> ArrayOfAvailablePro
if appliance_type not in MOCK_PROGRAMS: if appliance_type not in MOCK_PROGRAMS:
raise HomeConnectApiError("error.key", "error description") raise HomeConnectApiError("error.key", "error description")
return ArrayOfAvailablePrograms.from_dict(MOCK_PROGRAMS[appliance_type]["data"]) return ArrayOfPrograms.from_dict(MOCK_PROGRAMS[appliance_type]["data"])
async def _get_settings_side_effect(ha_id: str) -> ArrayOfSettings: async def _get_settings_side_effect(ha_id: str) -> ArrayOfSettings:
@ -290,9 +288,7 @@ def mock_client(request: pytest.FixtureRequest) -> MagicMock:
) )
mock.get_settings = AsyncMock(side_effect=_get_settings_side_effect) mock.get_settings = AsyncMock(side_effect=_get_settings_side_effect)
mock.get_status = AsyncMock(return_value=copy.deepcopy(MOCK_STATUS)) mock.get_status = AsyncMock(return_value=copy.deepcopy(MOCK_STATUS))
mock.get_available_programs = AsyncMock( mock.get_all_programs = AsyncMock(side_effect=_get_all_programs_side_effect)
side_effect=_get_available_programs_side_effect
)
mock.put_command = AsyncMock() mock.put_command = AsyncMock()
mock.side_effect = mock mock.side_effect = mock
@ -323,7 +319,6 @@ def mock_client_with_exception(request: pytest.FixtureRequest) -> MagicMock:
mock.start_program = AsyncMock(side_effect=exception) mock.start_program = AsyncMock(side_effect=exception)
mock.stop_program = AsyncMock(side_effect=exception) mock.stop_program = AsyncMock(side_effect=exception)
mock.get_available_programs = AsyncMock(side_effect=exception)
mock.set_selected_program = AsyncMock(side_effect=exception) mock.set_selected_program = AsyncMock(side_effect=exception)
mock.set_active_program_option = AsyncMock(side_effect=exception) mock.set_active_program_option = AsyncMock(side_effect=exception)
mock.set_selected_program_option = AsyncMock(side_effect=exception) mock.set_selected_program_option = AsyncMock(side_effect=exception)
@ -331,7 +326,7 @@ def mock_client_with_exception(request: pytest.FixtureRequest) -> MagicMock:
mock.get_settings = AsyncMock(side_effect=exception) mock.get_settings = AsyncMock(side_effect=exception)
mock.get_setting = AsyncMock(side_effect=exception) mock.get_setting = AsyncMock(side_effect=exception)
mock.get_status = AsyncMock(side_effect=exception) mock.get_status = AsyncMock(side_effect=exception)
mock.get_available_programs = AsyncMock(side_effect=exception) mock.get_all_programs = AsyncMock(side_effect=exception)
mock.put_command = AsyncMock(side_effect=exception) mock.put_command = AsyncMock(side_effect=exception)
return mock return mock

View File

@ -4,8 +4,8 @@ from collections.abc import Awaitable, Callable
from unittest.mock import MagicMock from unittest.mock import MagicMock
from aiohomeconnect.model import ( from aiohomeconnect.model import (
ArrayOfAvailablePrograms,
ArrayOfEvents, ArrayOfEvents,
ArrayOfPrograms,
Event, Event,
EventKey, EventKey,
EventMessage, EventMessage,
@ -13,7 +13,7 @@ from aiohomeconnect.model import (
ProgramKey, ProgramKey,
) )
from aiohomeconnect.model.error import HomeConnectError from aiohomeconnect.model.error import HomeConnectError
from aiohomeconnect.model.program import EnumerateAvailableProgram from aiohomeconnect.model.program import EnumerateProgram
import pytest import pytest
from homeassistant.components.select import ( from homeassistant.components.select import (
@ -61,14 +61,14 @@ async def test_filter_unknown_programs(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test select that only known programs are shown.""" """Test select that only known programs are shown."""
client.get_available_programs.side_effect = None client.get_all_programs.side_effect = None
client.get_available_programs.return_value = ArrayOfAvailablePrograms( client.get_all_programs.return_value = ArrayOfPrograms(
[ [
EnumerateAvailableProgram( 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,
), ),
EnumerateAvailableProgram( EnumerateProgram(
key=ProgramKey.UNKNOWN, key=ProgramKey.UNKNOWN,
raw_key="an unknown program", raw_key="an unknown program",
), ),
@ -202,16 +202,14 @@ async def test_select_exception_handling(
client_with_exception: MagicMock, client_with_exception: MagicMock,
) -> None: ) -> None:
"""Test exception handling.""" """Test exception handling."""
client_with_exception.get_available_programs.side_effect = None client_with_exception.get_all_programs.side_effect = None
client_with_exception.get_available_programs.return_value = ( client_with_exception.get_all_programs.return_value = ArrayOfPrograms(
ArrayOfAvailablePrograms( [
[ EnumerateProgram(
EnumerateAvailableProgram( 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, )
) ]
]
)
) )
assert config_entry.state is ConfigEntryState.NOT_LOADED assert config_entry.state is ConfigEntryState.NOT_LOADED

View File

@ -15,10 +15,7 @@ from aiohomeconnect.model import (
) )
from aiohomeconnect.model.error import HomeConnectError from aiohomeconnect.model.error import HomeConnectError
from aiohomeconnect.model.event import ArrayOfEvents, EventType from aiohomeconnect.model.event import ArrayOfEvents, EventType
from aiohomeconnect.model.program import ( from aiohomeconnect.model.program import ArrayOfPrograms, EnumerateProgram
ArrayOfAvailablePrograms,
EnumerateAvailableProgram,
)
from aiohomeconnect.model.setting import SettingConstraints from aiohomeconnect.model.setting import SettingConstraints
import pytest import pytest
@ -250,16 +247,14 @@ async def test_switch_exception_handling(
client_with_exception: MagicMock, client_with_exception: MagicMock,
) -> None: ) -> None:
"""Test exception handling.""" """Test exception handling."""
client_with_exception.get_available_programs.side_effect = None client_with_exception.get_all_programs.side_effect = None
client_with_exception.get_available_programs.return_value = ( client_with_exception.get_all_programs.return_value = ArrayOfPrograms(
ArrayOfAvailablePrograms( [
[ EnumerateProgram(
EnumerateAvailableProgram( 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, )
) ]
]
)
) )
client_with_exception.get_settings.side_effect = None client_with_exception.get_settings.side_effect = None
client_with_exception.get_settings.return_value = ArrayOfSettings( client_with_exception.get_settings.return_value = ArrayOfSettings(