Fetch current active and selected programs at Home Connect (#136948)
* Fetch current active and selected programs * Intialize HomeConnectEntity first at SelectProgramEntity * Use the right exception * Use active/selected program from `get_all_programs` This will allow us to reduce the number of requests that we need to perform to get all the data ready (only one requests vs. three requests) * Remove no longer required mocks * Fixpull/136549/head^2
parent
bf6f790d09
commit
147b5f549f
|
@ -257,14 +257,9 @@ class HomeConnectCoordinator(
|
||||||
appliance_data = appliances_data[appliance.ha_id]
|
appliance_data = appliances_data[appliance.ha_id]
|
||||||
else:
|
else:
|
||||||
appliances_data[appliance.ha_id] = appliance_data
|
appliances_data[appliance.ha_id] = appliance_data
|
||||||
if (
|
if appliance.type in APPLIANCES_WITH_PROGRAMS:
|
||||||
appliance.type in APPLIANCES_WITH_PROGRAMS
|
|
||||||
and not appliance_data.programs
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
appliance_data.programs.extend(
|
all_programs = await self.client.get_all_programs(appliance.ha_id)
|
||||||
(await self.client.get_all_programs(appliance.ha_id)).programs
|
|
||||||
)
|
|
||||||
except HomeConnectError as error:
|
except HomeConnectError as error:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Error fetching programs for %s: %s",
|
"Error fetching programs for %s: %s",
|
||||||
|
@ -273,4 +268,30 @@ class HomeConnectCoordinator(
|
||||||
if isinstance(error, HomeConnectApiError)
|
if isinstance(error, HomeConnectApiError)
|
||||||
else type(error).__name__,
|
else type(error).__name__,
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
appliance_data.programs.extend(all_programs.programs)
|
||||||
|
for program, event_key in (
|
||||||
|
(
|
||||||
|
all_programs.active,
|
||||||
|
EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
all_programs.selected,
|
||||||
|
EventKey.BSH_COMMON_ROOT_SELECTED_PROGRAM,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
if program and program.key:
|
||||||
|
appliance_data.events.update(
|
||||||
|
{
|
||||||
|
event_key: Event(
|
||||||
|
event_key,
|
||||||
|
event_key.value,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
program.key,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return appliances_data
|
return appliances_data
|
||||||
|
|
|
@ -110,7 +110,6 @@ class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity):
|
||||||
or program.constraints.execution in desc.allowed_executions
|
or program.constraints.execution in desc.allowed_executions
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self._attr_current_option = None
|
|
||||||
|
|
||||||
def update_native_value(self) -> None:
|
def update_native_value(self) -> None:
|
||||||
"""Set the program value."""
|
"""Set the program value."""
|
||||||
|
|
|
@ -192,6 +192,7 @@ class HomeConnectProgramSwitch(HomeConnectEntity, SwitchEntity):
|
||||||
desc = " ".join(
|
desc = " ".join(
|
||||||
["Program", program.key.split(".")[-3], program.key.split(".")[-1]]
|
["Program", program.key.split(".")[-3], program.key.split(".")[-1]]
|
||||||
)
|
)
|
||||||
|
self.program = program
|
||||||
super().__init__(
|
super().__init__(
|
||||||
coordinator,
|
coordinator,
|
||||||
appliance,
|
appliance,
|
||||||
|
@ -200,7 +201,6 @@ class HomeConnectProgramSwitch(HomeConnectEntity, SwitchEntity):
|
||||||
self._attr_name = f"{appliance.info.name} {desc}"
|
self._attr_name = f"{appliance.info.name} {desc}"
|
||||||
self._attr_unique_id = f"{appliance.info.ha_id}-{desc}"
|
self._attr_unique_id = f"{appliance.info.ha_id}-{desc}"
|
||||||
self._attr_has_entity_name = False
|
self._attr_has_entity_name = False
|
||||||
self.program = program
|
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Call when entity is added to hass."""
|
"""Call when entity is added to hass."""
|
||||||
|
|
|
@ -19,8 +19,10 @@ from aiohomeconnect.model import (
|
||||||
EventMessage,
|
EventMessage,
|
||||||
EventType,
|
EventType,
|
||||||
Option,
|
Option,
|
||||||
|
Program,
|
||||||
)
|
)
|
||||||
from aiohomeconnect.model.error import HomeConnectApiError, HomeConnectError
|
from aiohomeconnect.model.error import HomeConnectApiError, HomeConnectError
|
||||||
|
from aiohomeconnect.model.program import EnumerateProgram
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.application_credentials import (
|
from homeassistant.components.application_credentials import (
|
||||||
|
@ -227,7 +229,14 @@ async def _get_all_programs_side_effect(ha_id: str) -> ArrayOfPrograms:
|
||||||
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 ArrayOfPrograms.from_dict(MOCK_PROGRAMS[appliance_type]["data"])
|
return ArrayOfPrograms(
|
||||||
|
[
|
||||||
|
EnumerateProgram.from_dict(program)
|
||||||
|
for program in MOCK_PROGRAMS[appliance_type]["data"]["programs"]
|
||||||
|
],
|
||||||
|
Program.from_dict(MOCK_PROGRAMS[appliance_type]["data"]["programs"][0]),
|
||||||
|
Program.from_dict(MOCK_PROGRAMS[appliance_type]["data"]["programs"][0]),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _get_settings_side_effect(ha_id: str) -> ArrayOfSettings:
|
async def _get_settings_side_effect(ha_id: str) -> ArrayOfSettings:
|
||||||
|
|
|
@ -174,6 +174,7 @@ async def test_filter_programs(
|
||||||
(
|
(
|
||||||
"appliance_ha_id",
|
"appliance_ha_id",
|
||||||
"entity_id",
|
"entity_id",
|
||||||
|
"expected_initial_state",
|
||||||
"mock_method",
|
"mock_method",
|
||||||
"program_key",
|
"program_key",
|
||||||
"program_to_set",
|
"program_to_set",
|
||||||
|
@ -183,6 +184,7 @@ async def test_filter_programs(
|
||||||
(
|
(
|
||||||
"Dishwasher",
|
"Dishwasher",
|
||||||
"select.dishwasher_selected_program",
|
"select.dishwasher_selected_program",
|
||||||
|
"dishcare_dishwasher_program_auto_1",
|
||||||
"set_selected_program",
|
"set_selected_program",
|
||||||
ProgramKey.DISHCARE_DISHWASHER_ECO_50,
|
ProgramKey.DISHCARE_DISHWASHER_ECO_50,
|
||||||
"dishcare_dishwasher_program_eco_50",
|
"dishcare_dishwasher_program_eco_50",
|
||||||
|
@ -191,6 +193,7 @@ async def test_filter_programs(
|
||||||
(
|
(
|
||||||
"Dishwasher",
|
"Dishwasher",
|
||||||
"select.dishwasher_active_program",
|
"select.dishwasher_active_program",
|
||||||
|
"dishcare_dishwasher_program_auto_1",
|
||||||
"start_program",
|
"start_program",
|
||||||
ProgramKey.DISHCARE_DISHWASHER_ECO_50,
|
ProgramKey.DISHCARE_DISHWASHER_ECO_50,
|
||||||
"dishcare_dishwasher_program_eco_50",
|
"dishcare_dishwasher_program_eco_50",
|
||||||
|
@ -202,6 +205,7 @@ async def test_filter_programs(
|
||||||
async def test_select_program_functionality(
|
async def test_select_program_functionality(
|
||||||
appliance_ha_id: str,
|
appliance_ha_id: str,
|
||||||
entity_id: str,
|
entity_id: str,
|
||||||
|
expected_initial_state: str,
|
||||||
mock_method: str,
|
mock_method: str,
|
||||||
program_key: ProgramKey,
|
program_key: ProgramKey,
|
||||||
program_to_set: str,
|
program_to_set: str,
|
||||||
|
@ -217,7 +221,7 @@ async def test_select_program_functionality(
|
||||||
assert await integration_setup(client)
|
assert await integration_setup(client)
|
||||||
assert config_entry.state is ConfigEntryState.LOADED
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
assert hass.states.is_state(entity_id, "unknown")
|
assert hass.states.is_state(entity_id, expected_initial_state)
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
SELECT_DOMAIN,
|
SELECT_DOMAIN,
|
||||||
SERVICE_SELECT_OPTION,
|
SERVICE_SELECT_OPTION,
|
||||||
|
@ -301,6 +305,8 @@ async def test_select_exception_handling(
|
||||||
assert await integration_setup(client_with_exception)
|
assert await integration_setup(client_with_exception)
|
||||||
assert config_entry.state is ConfigEntryState.LOADED
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
assert hass.states.is_state(entity_id, STATE_UNKNOWN)
|
||||||
|
|
||||||
# Assert that an exception is called.
|
# Assert that an exception is called.
|
||||||
with pytest.raises(HomeConnectError):
|
with pytest.raises(HomeConnectError):
|
||||||
await getattr(client_with_exception, mock_attr)()
|
await getattr(client_with_exception, mock_attr)()
|
||||||
|
|
|
@ -178,11 +178,18 @@ async def test_switch_functionality(
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("entity_id", "program_key", "appliance_ha_id"),
|
("entity_id", "program_key", "initial_state", "appliance_ha_id"),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"switch.dryer_program_mix",
|
"switch.dryer_program_mix",
|
||||||
ProgramKey.LAUNDRY_CARE_DRYER_MIX,
|
ProgramKey.LAUNDRY_CARE_DRYER_MIX,
|
||||||
|
STATE_OFF,
|
||||||
|
"Dryer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"switch.dryer_program_cotton",
|
||||||
|
ProgramKey.LAUNDRY_CARE_DRYER_COTTON,
|
||||||
|
STATE_ON,
|
||||||
"Dryer",
|
"Dryer",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -191,6 +198,7 @@ async def test_switch_functionality(
|
||||||
async def test_program_switch_functionality(
|
async def test_program_switch_functionality(
|
||||||
entity_id: str,
|
entity_id: str,
|
||||||
program_key: ProgramKey,
|
program_key: ProgramKey,
|
||||||
|
initial_state: str,
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: MockConfigEntry,
|
config_entry: MockConfigEntry,
|
||||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||||
|
@ -227,6 +235,7 @@ async def test_program_switch_functionality(
|
||||||
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||||
assert await integration_setup(client)
|
assert await integration_setup(client)
|
||||||
assert config_entry.state == ConfigEntryState.LOADED
|
assert config_entry.state == ConfigEntryState.LOADED
|
||||||
|
assert hass.states.is_state(entity_id, initial_state)
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}
|
SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}
|
||||||
|
|
Loading…
Reference in New Issue