mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Bump whirlpool to 0.21.1 (#147611)
This commit is contained in:
parent
8cc4105984
commit
78c2405e61
@ -42,14 +42,21 @@ async def async_setup_entry(
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Config flow entry for Whirlpool binary sensors."""
|
||||
entities: list = []
|
||||
appliances_manager = config_entry.runtime_data
|
||||
for washer_dryer in appliances_manager.washer_dryers:
|
||||
entities.extend(
|
||||
WhirlpoolBinarySensor(washer_dryer, description)
|
||||
for description in WASHER_DRYER_SENSORS
|
||||
)
|
||||
async_add_entities(entities)
|
||||
|
||||
washer_binary_sensors = [
|
||||
WhirlpoolBinarySensor(washer, description)
|
||||
for washer in appliances_manager.washers
|
||||
for description in WASHER_DRYER_SENSORS
|
||||
]
|
||||
|
||||
dryer_binary_sensors = [
|
||||
WhirlpoolBinarySensor(dryer, description)
|
||||
for dryer in appliances_manager.dryers
|
||||
for description in WASHER_DRYER_SENSORS
|
||||
]
|
||||
|
||||
async_add_entities([*washer_binary_sensors, *dryer_binary_sensors])
|
||||
|
||||
|
||||
class WhirlpoolBinarySensor(WhirlpoolEntity, BinarySensorEntity):
|
||||
|
@ -70,7 +70,11 @@ async def authenticate(
|
||||
appliances_manager = AppliancesManager(backend_selector, auth, session)
|
||||
await appliances_manager.fetch_appliances()
|
||||
|
||||
if not appliances_manager.aircons and not appliances_manager.washer_dryers:
|
||||
if (
|
||||
not appliances_manager.aircons
|
||||
and not appliances_manager.washers
|
||||
and not appliances_manager.dryers
|
||||
):
|
||||
return "no_appliances"
|
||||
|
||||
return None
|
||||
|
@ -37,9 +37,13 @@ async def async_get_config_entry_diagnostics(
|
||||
|
||||
appliances_manager = config_entry.runtime_data
|
||||
diagnostics_data = {
|
||||
"washer_dryers": {
|
||||
wd.name: get_appliance_diagnostics(wd)
|
||||
for wd in appliances_manager.washer_dryers
|
||||
"washers": {
|
||||
washer.name: get_appliance_diagnostics(washer)
|
||||
for washer in appliances_manager.washers
|
||||
},
|
||||
"dryers": {
|
||||
dryer.name: get_appliance_diagnostics(dryer)
|
||||
for dryer in appliances_manager.dryers
|
||||
},
|
||||
"aircons": {
|
||||
ac.name: get_appliance_diagnostics(ac) for ac in appliances_manager.aircons
|
||||
|
@ -8,5 +8,5 @@
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["whirlpool"],
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["whirlpool-sixth-sense==0.20.0"]
|
||||
"requirements": ["whirlpool-sixth-sense==0.21.1"]
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
"""The Washer/Dryer Sensor for Whirlpool Appliances."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
from typing import override
|
||||
|
||||
from whirlpool.appliance import Appliance
|
||||
from whirlpool.washerdryer import MachineState, WasherDryer
|
||||
from whirlpool.dryer import Dryer, MachineState as DryerMachineState
|
||||
from whirlpool.washer import MachineState as WasherMachineState, Washer
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
RestoreSensor,
|
||||
@ -33,26 +35,49 @@ WASHER_TANK_FILL = {
|
||||
5: "active",
|
||||
}
|
||||
|
||||
WASHER_DRYER_MACHINE_STATE = {
|
||||
MachineState.Standby: "standby",
|
||||
MachineState.Setting: "setting",
|
||||
MachineState.DelayCountdownMode: "delay_countdown",
|
||||
MachineState.DelayPause: "delay_paused",
|
||||
MachineState.SmartDelay: "smart_delay",
|
||||
MachineState.SmartGridPause: "smart_grid_pause",
|
||||
MachineState.Pause: "pause",
|
||||
MachineState.RunningMainCycle: "running_maincycle",
|
||||
MachineState.RunningPostCycle: "running_postcycle",
|
||||
MachineState.Exceptions: "exception",
|
||||
MachineState.Complete: "complete",
|
||||
MachineState.PowerFailure: "power_failure",
|
||||
MachineState.ServiceDiagnostic: "service_diagnostic_mode",
|
||||
MachineState.FactoryDiagnostic: "factory_diagnostic_mode",
|
||||
MachineState.LifeTest: "life_test",
|
||||
MachineState.CustomerFocusMode: "customer_focus_mode",
|
||||
MachineState.DemoMode: "demo_mode",
|
||||
MachineState.HardStopOrError: "hard_stop_or_error",
|
||||
MachineState.SystemInit: "system_initialize",
|
||||
WASHER_MACHINE_STATE = {
|
||||
WasherMachineState.Standby: "standby",
|
||||
WasherMachineState.Setting: "setting",
|
||||
WasherMachineState.DelayCountdownMode: "delay_countdown",
|
||||
WasherMachineState.DelayPause: "delay_paused",
|
||||
WasherMachineState.SmartDelay: "smart_delay",
|
||||
WasherMachineState.SmartGridPause: "smart_grid_pause",
|
||||
WasherMachineState.Pause: "pause",
|
||||
WasherMachineState.RunningMainCycle: "running_maincycle",
|
||||
WasherMachineState.RunningPostCycle: "running_postcycle",
|
||||
WasherMachineState.Exceptions: "exception",
|
||||
WasherMachineState.Complete: "complete",
|
||||
WasherMachineState.PowerFailure: "power_failure",
|
||||
WasherMachineState.ServiceDiagnostic: "service_diagnostic_mode",
|
||||
WasherMachineState.FactoryDiagnostic: "factory_diagnostic_mode",
|
||||
WasherMachineState.LifeTest: "life_test",
|
||||
WasherMachineState.CustomerFocusMode: "customer_focus_mode",
|
||||
WasherMachineState.DemoMode: "demo_mode",
|
||||
WasherMachineState.HardStopOrError: "hard_stop_or_error",
|
||||
WasherMachineState.SystemInit: "system_initialize",
|
||||
}
|
||||
|
||||
DRYER_MACHINE_STATE = {
|
||||
DryerMachineState.Standby: "standby",
|
||||
DryerMachineState.Setting: "setting",
|
||||
DryerMachineState.DelayCountdownMode: "delay_countdown",
|
||||
DryerMachineState.DelayPause: "delay_paused",
|
||||
DryerMachineState.SmartDelay: "smart_delay",
|
||||
DryerMachineState.SmartGridPause: "smart_grid_pause",
|
||||
DryerMachineState.Pause: "pause",
|
||||
DryerMachineState.RunningMainCycle: "running_maincycle",
|
||||
DryerMachineState.RunningPostCycle: "running_postcycle",
|
||||
DryerMachineState.Exceptions: "exception",
|
||||
DryerMachineState.Complete: "complete",
|
||||
DryerMachineState.PowerFailure: "power_failure",
|
||||
DryerMachineState.ServiceDiagnostic: "service_diagnostic_mode",
|
||||
DryerMachineState.FactoryDiagnostic: "factory_diagnostic_mode",
|
||||
DryerMachineState.LifeTest: "life_test",
|
||||
DryerMachineState.CustomerFocusMode: "customer_focus_mode",
|
||||
DryerMachineState.DemoMode: "demo_mode",
|
||||
DryerMachineState.HardStopOrError: "hard_stop_or_error",
|
||||
DryerMachineState.SystemInit: "system_initialize",
|
||||
DryerMachineState.Cancelled: "cancelled",
|
||||
}
|
||||
|
||||
STATE_CYCLE_FILLING = "cycle_filling"
|
||||
@ -64,29 +89,44 @@ STATE_CYCLE_WASHING = "cycle_washing"
|
||||
STATE_DOOR_OPEN = "door_open"
|
||||
|
||||
|
||||
def washer_dryer_state(washer_dryer: WasherDryer) -> str | None:
|
||||
"""Determine correct states for a washer/dryer."""
|
||||
def washer_state(washer: Washer) -> str | None:
|
||||
"""Determine correct states for a washer."""
|
||||
|
||||
if washer_dryer.get_door_open():
|
||||
if washer.get_door_open():
|
||||
return STATE_DOOR_OPEN
|
||||
|
||||
machine_state = washer_dryer.get_machine_state()
|
||||
machine_state = washer.get_machine_state()
|
||||
|
||||
if machine_state == MachineState.RunningMainCycle:
|
||||
if washer_dryer.get_cycle_status_filling():
|
||||
if machine_state == WasherMachineState.RunningMainCycle:
|
||||
if washer.get_cycle_status_filling():
|
||||
return STATE_CYCLE_FILLING
|
||||
if washer_dryer.get_cycle_status_rinsing():
|
||||
if washer.get_cycle_status_rinsing():
|
||||
return STATE_CYCLE_RINSING
|
||||
if washer_dryer.get_cycle_status_sensing():
|
||||
if washer.get_cycle_status_sensing():
|
||||
return STATE_CYCLE_SENSING
|
||||
if washer_dryer.get_cycle_status_soaking():
|
||||
if washer.get_cycle_status_soaking():
|
||||
return STATE_CYCLE_SOAKING
|
||||
if washer_dryer.get_cycle_status_spinning():
|
||||
if washer.get_cycle_status_spinning():
|
||||
return STATE_CYCLE_SPINNING
|
||||
if washer_dryer.get_cycle_status_washing():
|
||||
if washer.get_cycle_status_washing():
|
||||
return STATE_CYCLE_WASHING
|
||||
|
||||
return WASHER_DRYER_MACHINE_STATE.get(machine_state)
|
||||
return WASHER_MACHINE_STATE.get(machine_state)
|
||||
|
||||
|
||||
def dryer_state(dryer: Dryer) -> str | None:
|
||||
"""Determine correct states for a dryer."""
|
||||
|
||||
if dryer.get_door_open():
|
||||
return STATE_DOOR_OPEN
|
||||
|
||||
machine_state = dryer.get_machine_state()
|
||||
|
||||
if machine_state == DryerMachineState.RunningMainCycle:
|
||||
if dryer.get_cycle_status_sensing():
|
||||
return STATE_CYCLE_SENSING
|
||||
|
||||
return DRYER_MACHINE_STATE.get(machine_state)
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
@ -96,8 +136,8 @@ class WhirlpoolSensorEntityDescription(SensorEntityDescription):
|
||||
value_fn: Callable[[Appliance], str | None]
|
||||
|
||||
|
||||
WASHER_DRYER_STATE_OPTIONS = [
|
||||
*WASHER_DRYER_MACHINE_STATE.values(),
|
||||
WASHER_STATE_OPTIONS = [
|
||||
*WASHER_MACHINE_STATE.values(),
|
||||
STATE_CYCLE_FILLING,
|
||||
STATE_CYCLE_RINSING,
|
||||
STATE_CYCLE_SENSING,
|
||||
@ -107,13 +147,19 @@ WASHER_DRYER_STATE_OPTIONS = [
|
||||
STATE_DOOR_OPEN,
|
||||
]
|
||||
|
||||
DRYER_STATE_OPTIONS = [
|
||||
*DRYER_MACHINE_STATE.values(),
|
||||
STATE_CYCLE_SENSING,
|
||||
STATE_DOOR_OPEN,
|
||||
]
|
||||
|
||||
WASHER_SENSORS: tuple[WhirlpoolSensorEntityDescription, ...] = (
|
||||
WhirlpoolSensorEntityDescription(
|
||||
key="state",
|
||||
translation_key="washer_state",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=WASHER_DRYER_STATE_OPTIONS,
|
||||
value_fn=washer_dryer_state,
|
||||
options=WASHER_STATE_OPTIONS,
|
||||
value_fn=washer_state,
|
||||
),
|
||||
WhirlpoolSensorEntityDescription(
|
||||
key="DispenseLevel",
|
||||
@ -130,8 +176,8 @@ DRYER_SENSORS: tuple[WhirlpoolSensorEntityDescription, ...] = (
|
||||
key="state",
|
||||
translation_key="dryer_state",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=WASHER_DRYER_STATE_OPTIONS,
|
||||
value_fn=washer_dryer_state,
|
||||
options=DRYER_STATE_OPTIONS,
|
||||
value_fn=dryer_state,
|
||||
),
|
||||
)
|
||||
|
||||
@ -151,24 +197,40 @@ async def async_setup_entry(
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Config flow entry for Whirlpool sensors."""
|
||||
entities: list = []
|
||||
appliances_manager = config_entry.runtime_data
|
||||
for washer_dryer in appliances_manager.washer_dryers:
|
||||
sensor_descriptions = (
|
||||
DRYER_SENSORS
|
||||
if "dryer" in washer_dryer.appliance_info.data_model.lower()
|
||||
else WASHER_SENSORS
|
||||
)
|
||||
|
||||
entities.extend(
|
||||
WhirlpoolSensor(washer_dryer, description)
|
||||
for description in sensor_descriptions
|
||||
)
|
||||
entities.extend(
|
||||
WasherDryerTimeSensor(washer_dryer, description)
|
||||
for description in WASHER_DRYER_TIME_SENSORS
|
||||
)
|
||||
async_add_entities(entities)
|
||||
washer_sensors = [
|
||||
WhirlpoolSensor(washer, description)
|
||||
for washer in appliances_manager.washers
|
||||
for description in WASHER_SENSORS
|
||||
]
|
||||
|
||||
washer_time_sensors = [
|
||||
WasherTimeSensor(washer, description)
|
||||
for washer in appliances_manager.washers
|
||||
for description in WASHER_DRYER_TIME_SENSORS
|
||||
]
|
||||
|
||||
dryer_sensors = [
|
||||
WhirlpoolSensor(dryer, description)
|
||||
for dryer in appliances_manager.dryers
|
||||
for description in DRYER_SENSORS
|
||||
]
|
||||
|
||||
dryer_time_sensors = [
|
||||
DryerTimeSensor(dryer, description)
|
||||
for dryer in appliances_manager.dryers
|
||||
for description in WASHER_DRYER_TIME_SENSORS
|
||||
]
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
*washer_sensors,
|
||||
*washer_time_sensors,
|
||||
*dryer_sensors,
|
||||
*dryer_time_sensors,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class WhirlpoolSensor(WhirlpoolEntity, SensorEntity):
|
||||
@ -187,22 +249,30 @@ class WhirlpoolSensor(WhirlpoolEntity, SensorEntity):
|
||||
return self.entity_description.value_fn(self._appliance)
|
||||
|
||||
|
||||
class WasherDryerTimeSensor(WhirlpoolEntity, RestoreSensor):
|
||||
"""A timestamp class for the Whirlpool washer/dryer."""
|
||||
class WasherDryerTimeSensorBase(WhirlpoolEntity, RestoreSensor, ABC):
|
||||
"""Abstract base class for Whirlpool washer/dryer time sensors."""
|
||||
|
||||
_attr_should_poll = True
|
||||
_appliance: Washer | Dryer
|
||||
|
||||
def __init__(
|
||||
self, washer_dryer: WasherDryer, description: SensorEntityDescription
|
||||
self, appliance: Washer | Dryer, description: SensorEntityDescription
|
||||
) -> None:
|
||||
"""Initialize the washer sensor."""
|
||||
super().__init__(washer_dryer, unique_id_suffix=f"-{description.key}")
|
||||
"""Initialize the washer/dryer sensor."""
|
||||
super().__init__(appliance, unique_id_suffix=f"-{description.key}")
|
||||
self.entity_description = description
|
||||
|
||||
self._wd = washer_dryer
|
||||
self._running: bool | None = None
|
||||
self._value: datetime | None = None
|
||||
|
||||
@abstractmethod
|
||||
def _is_machine_state_finished(self) -> bool:
|
||||
"""Return true if the machine is in a finished state."""
|
||||
|
||||
@abstractmethod
|
||||
def _is_machine_state_running(self) -> bool:
|
||||
"""Return true if the machine is in a running state."""
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register attribute updates callback."""
|
||||
if restored_data := await self.async_get_last_sensor_data():
|
||||
@ -212,28 +282,62 @@ class WasherDryerTimeSensor(WhirlpoolEntity, RestoreSensor):
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Update status of Whirlpool."""
|
||||
await self._wd.fetch_data()
|
||||
await self._appliance.fetch_data()
|
||||
|
||||
@override
|
||||
@property
|
||||
def native_value(self) -> datetime | None:
|
||||
"""Calculate the time stamp for completion."""
|
||||
machine_state = self._wd.get_machine_state()
|
||||
now = utcnow()
|
||||
if (
|
||||
machine_state.value
|
||||
in {MachineState.Complete.value, MachineState.Standby.value}
|
||||
and self._running
|
||||
):
|
||||
|
||||
if self._is_machine_state_finished() and self._running:
|
||||
self._running = False
|
||||
self._value = now
|
||||
|
||||
if machine_state is MachineState.RunningMainCycle:
|
||||
if self._is_machine_state_running():
|
||||
self._running = True
|
||||
new_timestamp = now + timedelta(seconds=self._wd.get_time_remaining())
|
||||
new_timestamp = now + timedelta(
|
||||
seconds=self._appliance.get_time_remaining()
|
||||
)
|
||||
if self._value is None or (
|
||||
isinstance(self._value, datetime)
|
||||
and abs(new_timestamp - self._value) > timedelta(seconds=60)
|
||||
):
|
||||
self._value = new_timestamp
|
||||
return self._value
|
||||
|
||||
|
||||
class WasherTimeSensor(WasherDryerTimeSensorBase):
|
||||
"""A timestamp class for Whirlpool washers."""
|
||||
|
||||
_appliance: Washer
|
||||
|
||||
def _is_machine_state_finished(self) -> bool:
|
||||
"""Return true if the machine is in a finished state."""
|
||||
return self._appliance.get_machine_state() in {
|
||||
WasherMachineState.Complete,
|
||||
WasherMachineState.Standby,
|
||||
}
|
||||
|
||||
def _is_machine_state_running(self) -> bool:
|
||||
"""Return true if the machine is in a running state."""
|
||||
return (
|
||||
self._appliance.get_machine_state() is WasherMachineState.RunningMainCycle
|
||||
)
|
||||
|
||||
|
||||
class DryerTimeSensor(WasherDryerTimeSensorBase):
|
||||
"""A timestamp class for Whirlpool dryers."""
|
||||
|
||||
_appliance: Dryer
|
||||
|
||||
def _is_machine_state_finished(self) -> bool:
|
||||
"""Return true if the machine is in a finished state."""
|
||||
return self._appliance.get_machine_state() in {
|
||||
DryerMachineState.Complete,
|
||||
DryerMachineState.Standby,
|
||||
}
|
||||
|
||||
def _is_machine_state_running(self) -> bool:
|
||||
"""Return true if the machine is in a running state."""
|
||||
return self._appliance.get_machine_state() is DryerMachineState.RunningMainCycle
|
||||
|
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@ -3102,7 +3102,7 @@ webmin-xmlrpc==0.0.2
|
||||
weheat==2025.6.10
|
||||
|
||||
# homeassistant.components.whirlpool
|
||||
whirlpool-sixth-sense==0.20.0
|
||||
whirlpool-sixth-sense==0.21.1
|
||||
|
||||
# homeassistant.components.whois
|
||||
whois==0.9.27
|
||||
|
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@ -2555,7 +2555,7 @@ webmin-xmlrpc==0.0.2
|
||||
weheat==2025.6.10
|
||||
|
||||
# homeassistant.components.whirlpool
|
||||
whirlpool-sixth-sense==0.20.0
|
||||
whirlpool-sixth-sense==0.21.1
|
||||
|
||||
# homeassistant.components.whois
|
||||
whois==0.9.27
|
||||
|
@ -4,7 +4,7 @@ from unittest import mock
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from whirlpool import aircon, appliancesmanager, auth, washerdryer
|
||||
from whirlpool import aircon, appliancesmanager, auth, dryer, washer
|
||||
from whirlpool.backendselector import Brand, Region
|
||||
|
||||
from .const import MOCK_SAID1, MOCK_SAID2
|
||||
@ -66,10 +66,8 @@ def fixture_mock_appliances_manager_api(
|
||||
mock_aircon1_api,
|
||||
mock_aircon2_api,
|
||||
]
|
||||
mock_appliances_manager.return_value.washer_dryers = [
|
||||
mock_washer_api,
|
||||
mock_dryer_api,
|
||||
]
|
||||
mock_appliances_manager.return_value.washers = [mock_washer_api]
|
||||
mock_appliances_manager.return_value.dryers = [mock_dryer_api]
|
||||
yield mock_appliances_manager
|
||||
|
||||
|
||||
@ -123,15 +121,13 @@ def fixture_mock_aircon2_api():
|
||||
@pytest.fixture
|
||||
def mock_washer_api():
|
||||
"""Get a mock of a washer."""
|
||||
mock_washer = Mock(spec=washerdryer.WasherDryer, said="said_washer")
|
||||
mock_washer = Mock(spec=washer.Washer, said="said_washer")
|
||||
mock_washer.name = "Washer"
|
||||
mock_washer.appliance_info = Mock(
|
||||
data_model="washer", category="washer_dryer", model_number="12345"
|
||||
)
|
||||
mock_washer.get_online.return_value = True
|
||||
mock_washer.get_machine_state.return_value = (
|
||||
washerdryer.MachineState.RunningMainCycle
|
||||
)
|
||||
mock_washer.get_machine_state.return_value = washer.MachineState.RunningMainCycle
|
||||
mock_washer.get_door_open.return_value = False
|
||||
mock_washer.get_dispense_1_level.return_value = 3
|
||||
mock_washer.get_time_remaining.return_value = 3540
|
||||
@ -148,21 +144,14 @@ def mock_washer_api():
|
||||
@pytest.fixture
|
||||
def mock_dryer_api():
|
||||
"""Get a mock of a dryer."""
|
||||
mock_dryer = mock.Mock(spec=washerdryer.WasherDryer, said="said_dryer")
|
||||
mock_dryer = mock.Mock(spec=dryer.Dryer, said="said_dryer")
|
||||
mock_dryer.name = "Dryer"
|
||||
mock_dryer.appliance_info = Mock(
|
||||
data_model="dryer", category="washer_dryer", model_number="12345"
|
||||
)
|
||||
mock_dryer.get_online.return_value = True
|
||||
mock_dryer.get_machine_state.return_value = (
|
||||
washerdryer.MachineState.RunningMainCycle
|
||||
)
|
||||
mock_dryer.get_machine_state.return_value = dryer.MachineState.RunningMainCycle
|
||||
mock_dryer.get_door_open.return_value = False
|
||||
mock_dryer.get_time_remaining.return_value = 3540
|
||||
mock_dryer.get_cycle_status_filling.return_value = False
|
||||
mock_dryer.get_cycle_status_rinsing.return_value = False
|
||||
mock_dryer.get_cycle_status_sensing.return_value = False
|
||||
mock_dryer.get_cycle_status_soaking.return_value = False
|
||||
mock_dryer.get_cycle_status_spinning.return_value = False
|
||||
mock_dryer.get_cycle_status_washing.return_value = False
|
||||
return mock_dryer
|
||||
|
@ -14,14 +14,16 @@
|
||||
'model_number': '12345',
|
||||
}),
|
||||
}),
|
||||
'ovens': dict({
|
||||
}),
|
||||
'washer_dryers': dict({
|
||||
'dryers': dict({
|
||||
'Dryer': dict({
|
||||
'category': 'washer_dryer',
|
||||
'data_model': 'dryer',
|
||||
'model_number': '12345',
|
||||
}),
|
||||
}),
|
||||
'ovens': dict({
|
||||
}),
|
||||
'washers': dict({
|
||||
'Washer': dict({
|
||||
'category': 'washer_dryer',
|
||||
'data_model': 'washer',
|
||||
|
@ -75,12 +75,8 @@
|
||||
'demo_mode',
|
||||
'hard_stop_or_error',
|
||||
'system_initialize',
|
||||
'cycle_filling',
|
||||
'cycle_rinsing',
|
||||
'cancelled',
|
||||
'cycle_sensing',
|
||||
'cycle_soaking',
|
||||
'cycle_spinning',
|
||||
'cycle_washing',
|
||||
'door_open',
|
||||
]),
|
||||
}),
|
||||
@ -138,12 +134,8 @@
|
||||
'demo_mode',
|
||||
'hard_stop_or_error',
|
||||
'system_initialize',
|
||||
'cycle_filling',
|
||||
'cycle_rinsing',
|
||||
'cancelled',
|
||||
'cycle_sensing',
|
||||
'cycle_soaking',
|
||||
'cycle_spinning',
|
||||
'cycle_washing',
|
||||
'door_open',
|
||||
]),
|
||||
}),
|
||||
|
@ -208,7 +208,8 @@ async def test_no_appliances_flow(
|
||||
|
||||
original_aircons = mock_appliances_manager_api.return_value.aircons
|
||||
mock_appliances_manager_api.return_value.aircons = []
|
||||
mock_appliances_manager_api.return_value.washer_dryers = []
|
||||
mock_appliances_manager_api.return_value.washers = []
|
||||
mock_appliances_manager_api.return_value.dryers = []
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], CONFIG_INPUT | {CONF_REGION: region[0], CONF_BRAND: brand[0]}
|
||||
)
|
||||
|
@ -80,7 +80,8 @@ async def test_setup_no_appliances(
|
||||
) -> None:
|
||||
"""Test setup when there are no appliances available."""
|
||||
mock_appliances_manager_api.return_value.aircons = []
|
||||
mock_appliances_manager_api.return_value.washer_dryers = []
|
||||
mock_appliances_manager_api.return_value.washers = []
|
||||
mock_appliances_manager_api.return_value.dryers = []
|
||||
await init_integration(hass)
|
||||
assert len(hass.states.async_all()) == 0
|
||||
|
||||
|
@ -5,7 +5,8 @@ from datetime import UTC, datetime, timedelta
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from whirlpool.washerdryer import MachineState
|
||||
from whirlpool.dryer import MachineState as DryerMachineState
|
||||
from whirlpool.washer import MachineState as WasherMachineState
|
||||
|
||||
from homeassistant.components.whirlpool.sensor import SCAN_INTERVAL
|
||||
from homeassistant.const import STATE_UNKNOWN, Platform
|
||||
@ -63,7 +64,7 @@ async def test_washer_dryer_time_sensor(
|
||||
)
|
||||
|
||||
mock_instance = request.getfixturevalue(mock_fixture)
|
||||
mock_instance.get_machine_state.return_value = MachineState.Pause
|
||||
mock_instance.get_machine_state.return_value = WasherMachineState.Pause
|
||||
await init_integration(hass)
|
||||
|
||||
# Test restored state.
|
||||
@ -77,7 +78,15 @@ async def test_washer_dryer_time_sensor(
|
||||
assert state.state == restored_datetime.isoformat()
|
||||
|
||||
# Test new time when machine starts a cycle.
|
||||
mock_instance.get_machine_state.return_value = MachineState.RunningMainCycle
|
||||
if "washer" in entity_id:
|
||||
mock_instance.get_machine_state.return_value = (
|
||||
WasherMachineState.RunningMainCycle
|
||||
)
|
||||
else:
|
||||
mock_instance.get_machine_state.return_value = (
|
||||
DryerMachineState.RunningMainCycle
|
||||
)
|
||||
|
||||
mock_instance.get_time_remaining.return_value = 60
|
||||
await trigger_attr_callback(hass, mock_instance)
|
||||
|
||||
@ -127,7 +136,10 @@ async def test_washer_dryer_time_sensor_no_restore(
|
||||
now = utcnow()
|
||||
|
||||
mock_instance = request.getfixturevalue(mock_fixture)
|
||||
mock_instance.get_machine_state.return_value = MachineState.Pause
|
||||
if "washer" in entity_id:
|
||||
mock_instance.get_machine_state.return_value = WasherMachineState.Pause
|
||||
else:
|
||||
mock_instance.get_machine_state.return_value = DryerMachineState.Pause
|
||||
await init_integration(hass)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
@ -140,7 +152,14 @@ async def test_washer_dryer_time_sensor_no_restore(
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
# Test new time when machine starts a cycle.
|
||||
mock_instance.get_machine_state.return_value = MachineState.RunningMainCycle
|
||||
if "washer" in entity_id:
|
||||
mock_instance.get_machine_state.return_value = (
|
||||
WasherMachineState.RunningMainCycle
|
||||
)
|
||||
else:
|
||||
mock_instance.get_machine_state.return_value = (
|
||||
DryerMachineState.RunningMainCycle
|
||||
)
|
||||
mock_instance.get_time_remaining.return_value = 60
|
||||
await trigger_attr_callback(hass, mock_instance)
|
||||
|
||||
@ -149,63 +168,87 @@ async def test_washer_dryer_time_sensor_no_restore(
|
||||
assert state.state == expected_time
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("entity_id", "mock_fixture"),
|
||||
[
|
||||
("sensor.washer_state", "mock_washer_api"),
|
||||
("sensor.dryer_state", "mock_dryer_api"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("machine_state", "expected_state"),
|
||||
[
|
||||
(MachineState.Standby, "standby"),
|
||||
(MachineState.Setting, "setting"),
|
||||
(MachineState.DelayCountdownMode, "delay_countdown"),
|
||||
(MachineState.DelayPause, "delay_paused"),
|
||||
(MachineState.SmartDelay, "smart_delay"),
|
||||
(MachineState.SmartGridPause, "smart_grid_pause"),
|
||||
(MachineState.Pause, "pause"),
|
||||
(MachineState.RunningMainCycle, "running_maincycle"),
|
||||
(MachineState.RunningPostCycle, "running_postcycle"),
|
||||
(MachineState.Exceptions, "exception"),
|
||||
(MachineState.Complete, "complete"),
|
||||
(MachineState.PowerFailure, "power_failure"),
|
||||
(MachineState.ServiceDiagnostic, "service_diagnostic_mode"),
|
||||
(MachineState.FactoryDiagnostic, "factory_diagnostic_mode"),
|
||||
(MachineState.LifeTest, "life_test"),
|
||||
(MachineState.CustomerFocusMode, "customer_focus_mode"),
|
||||
(MachineState.DemoMode, "demo_mode"),
|
||||
(MachineState.HardStopOrError, "hard_stop_or_error"),
|
||||
(MachineState.SystemInit, "system_initialize"),
|
||||
(WasherMachineState.Standby, "standby"),
|
||||
(WasherMachineState.Setting, "setting"),
|
||||
(WasherMachineState.DelayCountdownMode, "delay_countdown"),
|
||||
(WasherMachineState.DelayPause, "delay_paused"),
|
||||
(WasherMachineState.SmartDelay, "smart_delay"),
|
||||
(WasherMachineState.SmartGridPause, "smart_grid_pause"),
|
||||
(WasherMachineState.Pause, "pause"),
|
||||
(WasherMachineState.RunningMainCycle, "running_maincycle"),
|
||||
(WasherMachineState.RunningPostCycle, "running_postcycle"),
|
||||
(WasherMachineState.Exceptions, "exception"),
|
||||
(WasherMachineState.Complete, "complete"),
|
||||
(WasherMachineState.PowerFailure, "power_failure"),
|
||||
(WasherMachineState.ServiceDiagnostic, "service_diagnostic_mode"),
|
||||
(WasherMachineState.FactoryDiagnostic, "factory_diagnostic_mode"),
|
||||
(WasherMachineState.LifeTest, "life_test"),
|
||||
(WasherMachineState.CustomerFocusMode, "customer_focus_mode"),
|
||||
(WasherMachineState.DemoMode, "demo_mode"),
|
||||
(WasherMachineState.HardStopOrError, "hard_stop_or_error"),
|
||||
(WasherMachineState.SystemInit, "system_initialize"),
|
||||
],
|
||||
)
|
||||
async def test_washer_dryer_machine_states(
|
||||
async def test_washer_machine_states(
|
||||
hass: HomeAssistant,
|
||||
entity_id: str,
|
||||
mock_fixture: str,
|
||||
machine_state: MachineState,
|
||||
machine_state: WasherMachineState,
|
||||
expected_state: str,
|
||||
request: pytest.FixtureRequest,
|
||||
mock_washer_api,
|
||||
) -> None:
|
||||
"""Test Washer/Dryer machine states."""
|
||||
mock_instance = request.getfixturevalue(mock_fixture)
|
||||
"""Test Washer machine states."""
|
||||
await init_integration(hass)
|
||||
|
||||
mock_instance.get_machine_state.return_value = machine_state
|
||||
await trigger_attr_callback(hass, mock_instance)
|
||||
state = hass.states.get(entity_id)
|
||||
mock_washer_api.get_machine_state.return_value = machine_state
|
||||
await trigger_attr_callback(hass, mock_washer_api)
|
||||
state = hass.states.get("sensor.washer_state")
|
||||
assert state is not None
|
||||
assert state.state == expected_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("entity_id", "mock_fixture"),
|
||||
("machine_state", "expected_state"),
|
||||
[
|
||||
("sensor.washer_state", "mock_washer_api"),
|
||||
("sensor.dryer_state", "mock_dryer_api"),
|
||||
(DryerMachineState.Standby, "standby"),
|
||||
(DryerMachineState.Setting, "setting"),
|
||||
(DryerMachineState.DelayCountdownMode, "delay_countdown"),
|
||||
(DryerMachineState.DelayPause, "delay_paused"),
|
||||
(DryerMachineState.SmartDelay, "smart_delay"),
|
||||
(DryerMachineState.SmartGridPause, "smart_grid_pause"),
|
||||
(DryerMachineState.Pause, "pause"),
|
||||
(DryerMachineState.RunningMainCycle, "running_maincycle"),
|
||||
(DryerMachineState.RunningPostCycle, "running_postcycle"),
|
||||
(DryerMachineState.Exceptions, "exception"),
|
||||
(DryerMachineState.Complete, "complete"),
|
||||
(DryerMachineState.PowerFailure, "power_failure"),
|
||||
(DryerMachineState.ServiceDiagnostic, "service_diagnostic_mode"),
|
||||
(DryerMachineState.FactoryDiagnostic, "factory_diagnostic_mode"),
|
||||
(DryerMachineState.LifeTest, "life_test"),
|
||||
(DryerMachineState.CustomerFocusMode, "customer_focus_mode"),
|
||||
(DryerMachineState.DemoMode, "demo_mode"),
|
||||
(DryerMachineState.HardStopOrError, "hard_stop_or_error"),
|
||||
(DryerMachineState.SystemInit, "system_initialize"),
|
||||
(DryerMachineState.Cancelled, "cancelled"),
|
||||
],
|
||||
)
|
||||
async def test_dryer_machine_states(
|
||||
hass: HomeAssistant,
|
||||
machine_state: DryerMachineState,
|
||||
expected_state: str,
|
||||
mock_dryer_api,
|
||||
) -> None:
|
||||
"""Test Dryer machine states."""
|
||||
await init_integration(hass)
|
||||
|
||||
mock_dryer_api.get_machine_state.return_value = machine_state
|
||||
await trigger_attr_callback(hass, mock_dryer_api)
|
||||
state = hass.states.get("sensor.dryer_state")
|
||||
assert state is not None
|
||||
assert state.state == expected_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"filling",
|
||||
@ -225,10 +268,8 @@ async def test_washer_dryer_machine_states(
|
||||
(False, False, False, False, False, True, "cycle_washing"),
|
||||
],
|
||||
)
|
||||
async def test_washer_dryer_running_states(
|
||||
async def test_washer_running_states(
|
||||
hass: HomeAssistant,
|
||||
entity_id: str,
|
||||
mock_fixture: str,
|
||||
filling: bool,
|
||||
rinsing: bool,
|
||||
sensing: bool,
|
||||
@ -236,22 +277,21 @@ async def test_washer_dryer_running_states(
|
||||
spinning: bool,
|
||||
washing: bool,
|
||||
expected_state: str,
|
||||
request: pytest.FixtureRequest,
|
||||
mock_washer_api,
|
||||
) -> None:
|
||||
"""Test Washer/Dryer machine states for RunningMainCycle."""
|
||||
mock_instance = request.getfixturevalue(mock_fixture)
|
||||
"""Test Washer machine states for RunningMainCycle."""
|
||||
await init_integration(hass)
|
||||
|
||||
mock_instance.get_machine_state.return_value = MachineState.RunningMainCycle
|
||||
mock_instance.get_cycle_status_filling.return_value = filling
|
||||
mock_instance.get_cycle_status_rinsing.return_value = rinsing
|
||||
mock_instance.get_cycle_status_sensing.return_value = sensing
|
||||
mock_instance.get_cycle_status_soaking.return_value = soaking
|
||||
mock_instance.get_cycle_status_spinning.return_value = spinning
|
||||
mock_instance.get_cycle_status_washing.return_value = washing
|
||||
mock_washer_api.get_machine_state.return_value = WasherMachineState.RunningMainCycle
|
||||
mock_washer_api.get_cycle_status_filling.return_value = filling
|
||||
mock_washer_api.get_cycle_status_rinsing.return_value = rinsing
|
||||
mock_washer_api.get_cycle_status_sensing.return_value = sensing
|
||||
mock_washer_api.get_cycle_status_soaking.return_value = soaking
|
||||
mock_washer_api.get_cycle_status_spinning.return_value = spinning
|
||||
mock_washer_api.get_cycle_status_washing.return_value = washing
|
||||
|
||||
await trigger_attr_callback(hass, mock_instance)
|
||||
state = hass.states.get(entity_id)
|
||||
await trigger_attr_callback(hass, mock_washer_api)
|
||||
state = hass.states.get("sensor.washer_state")
|
||||
assert state is not None
|
||||
assert state.state == expected_state
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user