|
8 | 8 |
|
9 | 9 | from whirlpool.appliance import Appliance |
10 | 10 | from whirlpool.dryer import Dryer, MachineState as DryerMachineState |
| 11 | +from whirlpool.oven import ( |
| 12 | + Cavity as OvenCavity, |
| 13 | + CavityState as OvenCavityState, |
| 14 | + CookMode, |
| 15 | + Oven, |
| 16 | +) |
11 | 17 | from whirlpool.washer import MachineState as WasherMachineState, Washer |
12 | 18 |
|
13 | 19 | from homeassistant.components.sensor import ( |
14 | 20 | RestoreSensor, |
15 | 21 | SensorDeviceClass, |
16 | 22 | SensorEntity, |
17 | 23 | SensorEntityDescription, |
| 24 | + SensorStateClass, |
18 | 25 | ) |
| 26 | +from homeassistant.const import UnitOfTemperature |
19 | 27 | from homeassistant.core import HomeAssistant |
20 | 28 | from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback |
21 | 29 | from homeassistant.helpers.typing import StateType |
22 | 30 | from homeassistant.util.dt import utcnow |
23 | 31 |
|
24 | 32 | from . import WhirlpoolConfigEntry |
25 | | -from .entity import WhirlpoolEntity |
| 33 | +from .entity import WhirlpoolEntity, WhirlpoolOvenEntity |
26 | 34 |
|
27 | 35 | PARALLEL_UPDATES = 1 |
28 | 36 | SCAN_INTERVAL = timedelta(minutes=5) |
|
88 | 96 | STATE_CYCLE_SPINNING = "cycle_spinning" |
89 | 97 | STATE_CYCLE_WASHING = "cycle_washing" |
90 | 98 |
|
| 99 | +OVEN_CAVITY_STATE = { |
| 100 | + OvenCavityState.Standby: "standby", |
| 101 | + OvenCavityState.Preheating: "preheating", |
| 102 | + OvenCavityState.Cooking: "cooking", |
| 103 | +} |
| 104 | + |
| 105 | +OVEN_COOK_MODE = { |
| 106 | + CookMode.Standby: "standby", |
| 107 | + CookMode.Bake: "bake", |
| 108 | + CookMode.ConvectBake: "convection_bake", |
| 109 | + CookMode.Broil: "broil", |
| 110 | + CookMode.ConvectBroil: "convection_broil", |
| 111 | + CookMode.ConvectRoast: "convection_roast", |
| 112 | + CookMode.KeepWarm: "keep_warm", |
| 113 | + CookMode.AirFry: "air_fry", |
| 114 | +} |
| 115 | + |
91 | 116 |
|
92 | 117 | def washer_state(washer: Washer) -> str | None: |
93 | 118 | """Determine correct states for a washer.""" |
@@ -183,6 +208,59 @@ class WhirlpoolSensorEntityDescription(SensorEntityDescription): |
183 | 208 | ) |
184 | 209 |
|
185 | 210 |
|
| 211 | +@dataclass(frozen=True, kw_only=True) |
| 212 | +class WhirlpoolOvenCavitySensorEntityDescription(SensorEntityDescription): |
| 213 | + """Describes a Whirlpool oven cavity sensor entity.""" |
| 214 | + |
| 215 | + value_fn: Callable[[Oven, OvenCavity], str | int | float | None] |
| 216 | + |
| 217 | + |
| 218 | +OVEN_CAVITY_SENSORS: tuple[WhirlpoolOvenCavitySensorEntityDescription, ...] = ( |
| 219 | + WhirlpoolOvenCavitySensorEntityDescription( |
| 220 | + key="oven_state", |
| 221 | + translation_key="oven_state", |
| 222 | + device_class=SensorDeviceClass.ENUM, |
| 223 | + options=list(OVEN_CAVITY_STATE.values()), |
| 224 | + value_fn=lambda oven, cavity: ( |
| 225 | + OVEN_CAVITY_STATE.get(state) |
| 226 | + if (state := oven.get_cavity_state(cavity)) is not None |
| 227 | + else None |
| 228 | + ), |
| 229 | + ), |
| 230 | + WhirlpoolOvenCavitySensorEntityDescription( |
| 231 | + key="oven_cook_mode", |
| 232 | + translation_key="oven_cook_mode", |
| 233 | + device_class=SensorDeviceClass.ENUM, |
| 234 | + options=list(OVEN_COOK_MODE.values()), |
| 235 | + value_fn=lambda oven, cavity: ( |
| 236 | + OVEN_COOK_MODE.get(cook_mode) |
| 237 | + if (cook_mode := oven.get_cook_mode(cavity)) is not None |
| 238 | + else None |
| 239 | + ), |
| 240 | + ), |
| 241 | + WhirlpoolOvenCavitySensorEntityDescription( |
| 242 | + key="oven_current_temperature", |
| 243 | + translation_key="oven_current_temperature", |
| 244 | + device_class=SensorDeviceClass.TEMPERATURE, |
| 245 | + state_class=SensorStateClass.MEASUREMENT, |
| 246 | + native_unit_of_measurement=UnitOfTemperature.CELSIUS, |
| 247 | + value_fn=lambda oven, cavity: ( |
| 248 | + temp if (temp := oven.get_temp(cavity)) != 0 else None |
| 249 | + ), |
| 250 | + ), |
| 251 | + WhirlpoolOvenCavitySensorEntityDescription( |
| 252 | + key="oven_target_temperature", |
| 253 | + translation_key="oven_target_temperature", |
| 254 | + device_class=SensorDeviceClass.TEMPERATURE, |
| 255 | + state_class=SensorStateClass.MEASUREMENT, |
| 256 | + native_unit_of_measurement=UnitOfTemperature.CELSIUS, |
| 257 | + value_fn=lambda oven, cavity: ( |
| 258 | + temp if (temp := oven.get_target_temp(cavity)) != 0 else None |
| 259 | + ), |
| 260 | + ), |
| 261 | +) |
| 262 | + |
| 263 | + |
186 | 264 | async def async_setup_entry( |
187 | 265 | hass: HomeAssistant, |
188 | 266 | config_entry: WhirlpoolConfigEntry, |
@@ -215,12 +293,28 @@ async def async_setup_entry( |
215 | 293 | for description in WASHER_DRYER_TIME_SENSORS |
216 | 294 | ] |
217 | 295 |
|
| 296 | + oven_upper_cavity_sensors = [ |
| 297 | + WhirlpoolOvenCavitySensor(oven, OvenCavity.Upper, description) |
| 298 | + for oven in appliances_manager.ovens |
| 299 | + if oven.get_oven_cavity_exists(OvenCavity.Upper) |
| 300 | + for description in OVEN_CAVITY_SENSORS |
| 301 | + ] |
| 302 | + |
| 303 | + oven_lower_cavity_sensors = [ |
| 304 | + WhirlpoolOvenCavitySensor(oven, OvenCavity.Lower, description) |
| 305 | + for oven in appliances_manager.ovens |
| 306 | + if oven.get_oven_cavity_exists(OvenCavity.Lower) |
| 307 | + for description in OVEN_CAVITY_SENSORS |
| 308 | + ] |
| 309 | + |
218 | 310 | async_add_entities( |
219 | 311 | [ |
220 | 312 | *washer_sensors, |
221 | 313 | *washer_time_sensors, |
222 | 314 | *dryer_sensors, |
223 | 315 | *dryer_time_sensors, |
| 316 | + *oven_upper_cavity_sensors, |
| 317 | + *oven_lower_cavity_sensors, |
224 | 318 | ] |
225 | 319 | ) |
226 | 320 |
|
@@ -333,3 +427,26 @@ def _is_machine_state_finished(self) -> bool: |
333 | 427 | def _is_machine_state_running(self) -> bool: |
334 | 428 | """Return true if the machine is in a running state.""" |
335 | 429 | return self._appliance.get_machine_state() is DryerMachineState.RunningMainCycle |
| 430 | + |
| 431 | + |
| 432 | +class WhirlpoolOvenCavitySensor(WhirlpoolOvenEntity, SensorEntity): |
| 433 | + """A class for Whirlpool oven cavity sensors.""" |
| 434 | + |
| 435 | + def __init__( |
| 436 | + self, |
| 437 | + oven: Oven, |
| 438 | + cavity: OvenCavity, |
| 439 | + description: WhirlpoolOvenCavitySensorEntityDescription, |
| 440 | + ) -> None: |
| 441 | + """Initialize the oven cavity sensor.""" |
| 442 | + super().__init__( |
| 443 | + oven, cavity, description.translation_key, f"-{description.key}" |
| 444 | + ) |
| 445 | + self.entity_description: WhirlpoolOvenCavitySensorEntityDescription = ( |
| 446 | + description |
| 447 | + ) |
| 448 | + |
| 449 | + @property |
| 450 | + def native_value(self) -> StateType: |
| 451 | + """Return native value of sensor.""" |
| 452 | + return self.entity_description.value_fn(self._appliance, self.cavity) |
0 commit comments