mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Improve program related sensors at Home Connect (#135929)
This commit is contained in:
parent
33d552e3f7
commit
ac58494b55
@ -1,13 +1,10 @@
|
||||
"""Provides a sensor for Home Connect."""
|
||||
|
||||
import contextlib
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from typing import cast
|
||||
|
||||
from homeconnect.api import HomeConnectError
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
@ -22,6 +19,7 @@ import homeassistant.util.dt as dt_util
|
||||
|
||||
from . import HomeConnectConfigEntry
|
||||
from .const import (
|
||||
APPLIANCES_WITH_PROGRAMS,
|
||||
ATTR_VALUE,
|
||||
BSH_DOOR_STATE,
|
||||
BSH_OPERATION_STATE,
|
||||
@ -51,27 +49,35 @@ class HomeConnectSensorEntityDescription(SensorEntityDescription):
|
||||
|
||||
default_value: str | None = None
|
||||
appliance_types: tuple[str, ...] | None = None
|
||||
sign: int = 1
|
||||
|
||||
|
||||
BSH_PROGRAM_SENSORS = (
|
||||
HomeConnectSensorEntityDescription(
|
||||
key="BSH.Common.Option.RemainingProgramTime",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
sign=1,
|
||||
translation_key="program_finish_time",
|
||||
appliance_types=(
|
||||
"CoffeMaker",
|
||||
"CookProcessor",
|
||||
"Dishwasher",
|
||||
"Dryer",
|
||||
"Hood",
|
||||
"Oven",
|
||||
"Washer",
|
||||
"WasherDryer",
|
||||
),
|
||||
),
|
||||
HomeConnectSensorEntityDescription(
|
||||
key="BSH.Common.Option.Duration",
|
||||
device_class=SensorDeviceClass.DURATION,
|
||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||
sign=1,
|
||||
appliance_types=("Oven",),
|
||||
),
|
||||
HomeConnectSensorEntityDescription(
|
||||
key="BSH.Common.Option.ProgramProgress",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
sign=1,
|
||||
translation_key="program_progress",
|
||||
appliance_types=APPLIANCES_WITH_PROGRAMS,
|
||||
),
|
||||
)
|
||||
|
||||
@ -269,11 +275,12 @@ async def async_setup_entry(
|
||||
if description.appliance_types
|
||||
and device.appliance.type in description.appliance_types
|
||||
)
|
||||
with contextlib.suppress(HomeConnectError):
|
||||
if device.appliance.get_programs_available():
|
||||
entities.extend(
|
||||
HomeConnectSensor(device, desc) for desc in BSH_PROGRAM_SENSORS
|
||||
)
|
||||
entities.extend(
|
||||
HomeConnectProgramSensor(device, desc)
|
||||
for desc in BSH_PROGRAM_SENSORS
|
||||
if desc.appliance_types
|
||||
and device.appliance.type in desc.appliance_types
|
||||
)
|
||||
entities.extend(
|
||||
HomeConnectSensor(device, description)
|
||||
for description in SENSORS
|
||||
@ -289,11 +296,6 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
||||
|
||||
entity_description: HomeConnectSensorEntityDescription
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return true if the sensor is available."""
|
||||
return self._attr_native_value is not None
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Update the sensor's status."""
|
||||
appliance_status = self.device.appliance.status
|
||||
@ -311,30 +313,17 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
||||
self._attr_native_value = None
|
||||
elif (
|
||||
self._attr_native_value is not None
|
||||
and self.entity_description.sign == 1
|
||||
and isinstance(self._attr_native_value, datetime)
|
||||
and self._attr_native_value < dt_util.utcnow()
|
||||
):
|
||||
# if the date is supposed to be in the future but we're
|
||||
# already past it, set state to None.
|
||||
self._attr_native_value = None
|
||||
elif (
|
||||
BSH_OPERATION_STATE
|
||||
in (appliance_status := self.device.appliance.status)
|
||||
and ATTR_VALUE in appliance_status[BSH_OPERATION_STATE]
|
||||
and appliance_status[BSH_OPERATION_STATE][ATTR_VALUE]
|
||||
in [
|
||||
BSH_OPERATION_STATE_RUN,
|
||||
BSH_OPERATION_STATE_PAUSE,
|
||||
BSH_OPERATION_STATE_FINISHED,
|
||||
]
|
||||
):
|
||||
seconds = self.entity_description.sign * float(status[ATTR_VALUE])
|
||||
else:
|
||||
seconds = float(status[ATTR_VALUE])
|
||||
self._attr_native_value = dt_util.utcnow() + timedelta(
|
||||
seconds=seconds
|
||||
)
|
||||
else:
|
||||
self._attr_native_value = None
|
||||
case SensorDeviceClass.ENUM:
|
||||
# Value comes back as an enum, we only really care about the
|
||||
# last part, so split it off
|
||||
@ -345,3 +334,34 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
||||
case _:
|
||||
self._attr_native_value = status.get(ATTR_VALUE)
|
||||
_LOGGER.debug("Updated, new state: %s", self._attr_native_value)
|
||||
|
||||
|
||||
class HomeConnectProgramSensor(HomeConnectSensor):
|
||||
"""Sensor class for Home Connect sensors that reports information related to the running program."""
|
||||
|
||||
program_running: bool = False
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return true if the sensor is available."""
|
||||
# These sensors are only available if the program is running, paused or finished.
|
||||
# Otherwise, some sensors report erroneous values.
|
||||
return super().available and self.program_running
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Update the sensor's status."""
|
||||
self.program_running = (
|
||||
BSH_OPERATION_STATE in (appliance_status := self.device.appliance.status)
|
||||
and ATTR_VALUE in appliance_status[BSH_OPERATION_STATE]
|
||||
and appliance_status[BSH_OPERATION_STATE][ATTR_VALUE]
|
||||
in [
|
||||
BSH_OPERATION_STATE_RUN,
|
||||
BSH_OPERATION_STATE_PAUSE,
|
||||
BSH_OPERATION_STATE_FINISHED,
|
||||
]
|
||||
)
|
||||
if self.program_running:
|
||||
await super().async_update()
|
||||
else:
|
||||
# reset the value when the program is not running, paused or finished
|
||||
self._attr_native_value = None
|
||||
|
Loading…
x
Reference in New Issue
Block a user