Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/asuswrt/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["aioasuswrt", "asusrouter", "asyncssh"],
"requirements": ["aioasuswrt==1.4.0", "asusrouter==1.19.0"]
"requirements": ["aioasuswrt==1.4.0", "asusrouter==1.20.0"]
}
69 changes: 68 additions & 1 deletion homeassistant/components/miele/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pymiele import MieleDevice, MieleTemperature

from homeassistant.components.sensor import (
RestoreSensor,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
Expand All @@ -18,13 +19,14 @@
from homeassistant.const import (
PERCENTAGE,
REVOLUTIONS_PER_MINUTE,
STATE_UNKNOWN,
EntityCategory,
UnitOfEnergy,
UnitOfTemperature,
UnitOfTime,
UnitOfVolume,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
Expand Down Expand Up @@ -105,6 +107,7 @@ class MieleSensorDescription(SensorEntityDescription):
"""Class describing Miele sensor entities."""

value_fn: Callable[[MieleDevice], StateType]
end_value_fn: Callable[[StateType], StateType] | None = None
extra_attributes: dict[str, Callable[[MieleDevice], StateType]] | None = None
zone: int | None = None
unique_id_fn: Callable[[str, MieleSensorDescription], str] | None = None
Expand Down Expand Up @@ -386,6 +389,7 @@ class MieleSensorDefinition:
key="state_elapsed_time",
translation_key="elapsed_time",
value_fn=lambda value: _convert_duration(value.state_elapsed_time),
end_value_fn=lambda last_value: last_value,
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.MINUTES,
entity_category=EntityCategory.DIAGNOSTIC,
Expand Down Expand Up @@ -609,6 +613,7 @@ def _get_entity_class(definition: MieleSensorDefinition) -> type[MieleSensor]:
"state_program_id": MieleProgramIdSensor,
"state_program_phase": MielePhaseSensor,
"state_plate_step": MielePlateSensor,
"state_elapsed_time": MieleTimeSensor,
}.get(definition.description.key, MieleSensor)

def _is_entity_registered(unique_id: str) -> bool:
Expand Down Expand Up @@ -745,6 +750,36 @@ def extra_state_attributes(self) -> Mapping[str, Any] | None:
return attr


class MieleRestorableSensor(MieleSensor, RestoreSensor):
"""Representation of a Sensor whose internal state can be restored."""

_last_value: StateType

def __init__(
self,
coordinator: MieleDataUpdateCoordinator,
device_id: str,
description: MieleSensorDescription,
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator, device_id, description)
self._last_value = None

async def async_added_to_hass(self) -> None:
"""When entity is added to hass."""
await super().async_added_to_hass()

# recover last value from cache
last_value = await self.async_get_last_state()
if last_value and last_value.state != STATE_UNKNOWN:
self._last_value = last_value.state

@property
def native_value(self) -> StateType:
"""Return the state of the sensor."""
return self._last_value


class MielePlateSensor(MieleSensor):
"""Representation of a Sensor."""

Expand Down Expand Up @@ -846,3 +881,35 @@ def native_value(self) -> StateType:
def options(self) -> list[str]:
"""Return the options list for the actual device type."""
return sorted(set(STATE_PROGRAM_ID.get(self.device.device_type, {}).values()))


class MieleTimeSensor(MieleRestorableSensor):
"""Representation of time sensors keeping state from cache."""

@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""

current_value = self.entity_description.value_fn(self.device)
current_status = StateStatus(self.device.state_status)

# report end-specific value when program ends (some devices are immediately reporting 0...)
if (
current_status == StateStatus.PROGRAM_ENDED
and self.entity_description.end_value_fn is not None
):
self._last_value = self.entity_description.end_value_fn(self._last_value)

# keep value when program ends if no function is specified
elif current_status == StateStatus.PROGRAM_ENDED:
pass

# force unknown when appliance is not working (some devices are keeping last value until a new cycle starts)
elif current_status in (StateStatus.OFF, StateStatus.ON, StateStatus.IDLE):
self._last_value = None

# otherwise, cache value and return it
else:
self._last_value = current_value

super()._handle_coordinator_update()
2 changes: 1 addition & 1 deletion requirements_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion requirements_test_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading