mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +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."""
|
"""Provides a sensor for Home Connect."""
|
||||||
|
|
||||||
import contextlib
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from homeconnect.api import HomeConnectError
|
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
@ -22,6 +19,7 @@ import homeassistant.util.dt as dt_util
|
|||||||
|
|
||||||
from . import HomeConnectConfigEntry
|
from . import HomeConnectConfigEntry
|
||||||
from .const import (
|
from .const import (
|
||||||
|
APPLIANCES_WITH_PROGRAMS,
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
BSH_DOOR_STATE,
|
BSH_DOOR_STATE,
|
||||||
BSH_OPERATION_STATE,
|
BSH_OPERATION_STATE,
|
||||||
@ -51,27 +49,35 @@ class HomeConnectSensorEntityDescription(SensorEntityDescription):
|
|||||||
|
|
||||||
default_value: str | None = None
|
default_value: str | None = None
|
||||||
appliance_types: tuple[str, ...] | None = None
|
appliance_types: tuple[str, ...] | None = None
|
||||||
sign: int = 1
|
|
||||||
|
|
||||||
|
|
||||||
BSH_PROGRAM_SENSORS = (
|
BSH_PROGRAM_SENSORS = (
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="BSH.Common.Option.RemainingProgramTime",
|
key="BSH.Common.Option.RemainingProgramTime",
|
||||||
device_class=SensorDeviceClass.TIMESTAMP,
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
sign=1,
|
|
||||||
translation_key="program_finish_time",
|
translation_key="program_finish_time",
|
||||||
|
appliance_types=(
|
||||||
|
"CoffeMaker",
|
||||||
|
"CookProcessor",
|
||||||
|
"Dishwasher",
|
||||||
|
"Dryer",
|
||||||
|
"Hood",
|
||||||
|
"Oven",
|
||||||
|
"Washer",
|
||||||
|
"WasherDryer",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="BSH.Common.Option.Duration",
|
key="BSH.Common.Option.Duration",
|
||||||
device_class=SensorDeviceClass.DURATION,
|
device_class=SensorDeviceClass.DURATION,
|
||||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||||
sign=1,
|
appliance_types=("Oven",),
|
||||||
),
|
),
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="BSH.Common.Option.ProgramProgress",
|
key="BSH.Common.Option.ProgramProgress",
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
sign=1,
|
|
||||||
translation_key="program_progress",
|
translation_key="program_progress",
|
||||||
|
appliance_types=APPLIANCES_WITH_PROGRAMS,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -269,10 +275,11 @@ async def async_setup_entry(
|
|||||||
if description.appliance_types
|
if description.appliance_types
|
||||||
and device.appliance.type in description.appliance_types
|
and device.appliance.type in description.appliance_types
|
||||||
)
|
)
|
||||||
with contextlib.suppress(HomeConnectError):
|
|
||||||
if device.appliance.get_programs_available():
|
|
||||||
entities.extend(
|
entities.extend(
|
||||||
HomeConnectSensor(device, desc) for desc in BSH_PROGRAM_SENSORS
|
HomeConnectProgramSensor(device, desc)
|
||||||
|
for desc in BSH_PROGRAM_SENSORS
|
||||||
|
if desc.appliance_types
|
||||||
|
and device.appliance.type in desc.appliance_types
|
||||||
)
|
)
|
||||||
entities.extend(
|
entities.extend(
|
||||||
HomeConnectSensor(device, description)
|
HomeConnectSensor(device, description)
|
||||||
@ -289,11 +296,6 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
|||||||
|
|
||||||
entity_description: HomeConnectSensorEntityDescription
|
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:
|
async def async_update(self) -> None:
|
||||||
"""Update the sensor's status."""
|
"""Update the sensor's status."""
|
||||||
appliance_status = self.device.appliance.status
|
appliance_status = self.device.appliance.status
|
||||||
@ -311,30 +313,17 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
|||||||
self._attr_native_value = None
|
self._attr_native_value = None
|
||||||
elif (
|
elif (
|
||||||
self._attr_native_value is not None
|
self._attr_native_value is not None
|
||||||
and self.entity_description.sign == 1
|
|
||||||
and isinstance(self._attr_native_value, datetime)
|
and isinstance(self._attr_native_value, datetime)
|
||||||
and self._attr_native_value < dt_util.utcnow()
|
and self._attr_native_value < dt_util.utcnow()
|
||||||
):
|
):
|
||||||
# if the date is supposed to be in the future but we're
|
# if the date is supposed to be in the future but we're
|
||||||
# already past it, set state to None.
|
# already past it, set state to None.
|
||||||
self._attr_native_value = None
|
self._attr_native_value = None
|
||||||
elif (
|
else:
|
||||||
BSH_OPERATION_STATE
|
seconds = float(status[ATTR_VALUE])
|
||||||
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])
|
|
||||||
self._attr_native_value = dt_util.utcnow() + timedelta(
|
self._attr_native_value = dt_util.utcnow() + timedelta(
|
||||||
seconds=seconds
|
seconds=seconds
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
self._attr_native_value = None
|
|
||||||
case SensorDeviceClass.ENUM:
|
case SensorDeviceClass.ENUM:
|
||||||
# Value comes back as an enum, we only really care about the
|
# Value comes back as an enum, we only really care about the
|
||||||
# last part, so split it off
|
# last part, so split it off
|
||||||
@ -345,3 +334,34 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
|||||||
case _:
|
case _:
|
||||||
self._attr_native_value = status.get(ATTR_VALUE)
|
self._attr_native_value = status.get(ATTR_VALUE)
|
||||||
_LOGGER.debug("Updated, new state: %s", self._attr_native_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