Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Commit

Permalink
Exclude attributes from recorder (#463)
Browse files Browse the repository at this point in the history
  • Loading branch information
edenhaus authored Nov 22, 2023
1 parent 4efceee commit 17af398
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 40 deletions.
3 changes: 0 additions & 3 deletions custom_components/deebot/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@
DEEBOT_DEVICES = f"{DOMAIN}_devices"


LAST_ERROR = "last_error"


REFRESH_STR_TO_EVENT_DTO: Mapping[str, type[Event]] = {
"battery": BatteryEvent,
"clean_logs": CleanLogEvent,
Expand Down
11 changes: 9 additions & 2 deletions custom_components/deebot/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@

_LOGGER = logging.getLogger(__name__)

_EntityGeneratorType = Callable[
[Device], Sequence[DeebotEntity[Any, EntityDescription]]
]


class DeebotController:
"""Deebot Controller."""
Expand Down Expand Up @@ -114,13 +118,16 @@ def register_platform_add_entities(
def register_platform_add_entities_generator(
self,
async_add_entities: AddEntitiesCallback,
func: Callable[[Device], Sequence[DeebotEntity[Any, EntityDescription]]],
functions: _EntityGeneratorType | tuple[_EntityGeneratorType, ...],
) -> None:
"""Add entities generated through the provided function."""
new_entites: list[DeebotEntity[Any, EntityDescription]] = []

for device in self._devices:
new_entites.extend(func(device))
if callable(functions):
functions = (functions,)
for func in functions:
new_entites.extend(func(device))

if new_entites:
async_add_entities(new_entites)
Expand Down
1 change: 0 additions & 1 deletion custom_components/deebot/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class DeebotEntityDescription(
):
"""Deebot Entity Description."""

always_available: bool = False
capability_fn: Callable[[Capabilities], CapabilityT | None]


Expand Down
114 changes: 89 additions & 25 deletions custom_components/deebot/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType

from .const import DOMAIN, LAST_ERROR
from .const import DOMAIN
from .controller import DeebotController
from .entity import DeebotEntity, DeebotEntityDescription, EventT

Expand Down Expand Up @@ -144,27 +144,6 @@ def _clean_log_event_attributes(event: CleanLogEvent) -> MutableMapping[str, Any
device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
),
DeebotSensorEntityDescription[ErrorEvent](
capability_fn=lambda caps: caps.error,
value_fn=lambda e: e.code,
extra_state_attributes_fn=lambda e: {CONF_DESCRIPTION: e.description},
always_available=True,
key=LAST_ERROR,
translation_key=LAST_ERROR,
icon="mdi:alert-circle",
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
),
DeebotSensorEntityDescription[CleanLogEvent](
capability_fn=lambda caps: caps.clean.log,
value_fn=_clean_log_event_value,
extra_state_attributes_fn=_clean_log_event_attributes,
always_available=True,
key="last_cleaning",
translation_key="last_cleaning",
icon="mdi:history",
entity_registry_enabled_default=False,
),
DeebotSensorEntityDescription[NetworkInfoEvent](
capability_fn=lambda caps: caps.network,
value_fn=lambda e: e.ip,
Expand Down Expand Up @@ -251,9 +230,21 @@ async def async_setup_entry(
DeebotSensor, ENTITY_DESCRIPTIONS, async_add_entities
)

def life_span_entity_generator(
def last_error_entity_generator(
device: Device,
) -> Sequence[LastErrorSensor]:
if capability := device.capabilities.error:
return [(LastErrorSensor(device, capability))]
return []

def last_cleaning_entity_generator(
device: Device,
) -> Sequence[LifeSpanSensor]:
) -> Sequence[LastCleaningSensor]:
if capability := device.capabilities.clean.log:
return [(LastCleaningSensor(device, capability))]
return []

def life_span_entity_generator(device: Device) -> Sequence[LifeSpanSensor]:
new_entities = []
capability = device.capabilities.life_span
for description in LIFE_SPAN_DESCRIPTIONS:
Expand All @@ -262,7 +253,12 @@ def life_span_entity_generator(
return new_entities

controller.register_platform_add_entities_generator(
async_add_entities, life_span_entity_generator
async_add_entities,
(
life_span_entity_generator,
last_error_entity_generator,
last_cleaning_entity_generator,
),
)


Expand Down Expand Up @@ -315,3 +311,71 @@ async def on_event(event: LifeSpanEvent) -> None:
self.async_on_remove(
self._device.events.subscribe(self._capability.event, on_event)
)


class LastErrorSensor(
DeebotEntity[CapabilityEvent[ErrorEvent], SensorEntityDescription],
SensorEntity, # type: ignore
):
"""Last error sensor."""

_always_available: bool = True
_unrecorded_attributes = frozenset({CONF_DESCRIPTION})
entity_description: SensorEntityDescription = SensorEntityDescription(
key="last_error",
translation_key="last_error",
icon="mdi:alert-circle",
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
)

async def async_added_to_hass(self) -> None:
"""Set up the event listeners now that hass is ready."""
await super().async_added_to_hass()

async def on_event(event: ErrorEvent) -> None:
self._attr_native_value = event.code
self._attr_extra_state_attributes = {CONF_DESCRIPTION: event.description}

self.async_write_ha_state()

self.async_on_remove(
self._device.events.subscribe(self._capability.event, on_event)
)


class LastCleaningSensor(
DeebotEntity[CapabilityEvent[CleanLogEvent], SensorEntityDescription],
SensorEntity, # type: ignore
):
"""Last cleaning sensor."""

_always_available: bool = True
entity_description: SensorEntityDescription = SensorEntityDescription(
key="last_cleaning",
translation_key="last_cleaning",
icon="mdi:history",
entity_registry_enabled_default=False,
)

async def async_added_to_hass(self) -> None:
"""Set up the event listeners now that hass is ready."""
await super().async_added_to_hass()

async def on_event(event: CleanLogEvent) -> None:
if event.logs:
log = event.logs[0]
self._attr_native_value = log.stop_reason.display_name
self._attr_extra_state_attributes = {
"timestamp": log.timestamp,
"image_url": log.image_url,
"type": log.type,
"area": log.area,
"duration": log.duration / 60,
}

self.async_write_ha_state()

self.async_on_remove(
self._device.events.subscribe(self._capability.event, on_event)
)
15 changes: 6 additions & 9 deletions custom_components/deebot/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from deebot_client.events import (
BatteryEvent,
CustomCommandEvent,
ErrorEvent,
FanSpeedEvent,
ReportStatsEvent,
RoomsEvent,
Expand Down Expand Up @@ -38,7 +37,6 @@
DOMAIN,
EVENT_CLEANING_JOB,
EVENT_CUSTOM_COMMAND,
LAST_ERROR,
REFRESH_MAP,
REFRESH_STR_TO_EVENT_DTO,
)
Expand Down Expand Up @@ -96,12 +94,17 @@ def vacuum_entity_generator(
)


_ATTR_ROOMS = "rooms"


class DeebotVacuum(
DeebotEntity[Capabilities, StateVacuumEntityDescription],
StateVacuumEntity, # type: ignore
):
"""Deebot Vacuum."""

_unrecorded_attributes = frozenset({_ATTR_ROOMS})

_attr_supported_features = (
VacuumEntityFeature.PAUSE
| VacuumEntityFeature.STOP
Expand All @@ -124,7 +127,6 @@ def __init__(self, device: Device):
)

self._rooms: list[Room] = []
self._last_error: ErrorEvent | None = None

self._attr_fan_speed_list = [
level.display_name for level in capabilities.fan_speed.types
Expand Down Expand Up @@ -204,12 +206,7 @@ def extra_state_attributes(self) -> Mapping[str, Any] | None:
rooms[room_name] = [room_values, room.id]

if rooms:
attributes["rooms"] = rooms

if self._last_error:
attributes[
LAST_ERROR
] = f"{self._last_error.description} ({self._last_error.code})"
attributes[_ATTR_ROOMS] = rooms

return attributes

Expand Down

0 comments on commit 17af398

Please sign in to comment.