Files
home-assistant-ecocito/custom_components/ecocito/sensor.py
Xavier Morel 67016339b3 feat: make the sync of garbage types optional
If the selected type is "Skip synchro", the ecocito data won't contain the related coordinator(s)
and any sync of that type will be skipped.
2025-04-03 15:35:36 +02:00

243 lines
7.8 KiB
Python

"""Support for Lidarr."""
from __future__ import annotations
import dataclasses
from collections.abc import Callable
from datetime import datetime
from typing import Any, Generic
from homeassistant.components.sensor import (
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import UnitOfMass
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import EcocitoConfigEntry
from .client import CollectionEvent, EcocitoEvent
from .const import DEVICE_ATTRIBUTION
from .coordinator import T
from .entity import EcocitoEntity
def get_count(data: list[Any]) -> int:
"""Return the size of the given list."""
return len(data)
def get_event_collections_weight(data: list[CollectionEvent]) -> int:
"""Return the sum of the events quantities."""
result = 0
for row in data:
result += row.quantity
return result
def get_latest_date(data: list[EcocitoEvent]) -> datetime | None:
"""Return the date of the latest collection event."""
if not data:
return None
return max(data, key=lambda event: event.date).date
def get_latest_event_collection_weight(data: list[CollectionEvent]) -> int:
"""Return the weight of the latest event."""
if not data:
return 0
latest_event = max(data, key=lambda event: event.date)
latest_date = latest_event.date.date()
return sum(event.quantity for event in data if event.date.date() == latest_date)
@dataclasses.dataclass
class EcocitoSensorEntityDescription(SensorEntityDescription, Generic[T]):
"""Class to describe a Ecocito sensor."""
def __init__(
self,
value_fn: Callable[[T], str | int],
last_updated_fn: Callable[[T], datetime],
*args: tuple,
**kwargs: dict[str, any],
) -> None:
"""Build a Ecocito sensor."""
self.value_fn = value_fn
self.last_updated_fn = last_updated_fn
super().__init__(*args, **kwargs)
SENSOR_TYPES: tuple[tuple[str, EcocitoSensorEntityDescription]] = (
(
"garbage_collections",
EcocitoSensorEntityDescription(
key="garbage_collections_count",
translation_key="garbage_collections_count",
value_fn=get_count,
last_updated_fn=get_latest_date,
icon="mdi:trash-can",
state_class=SensorStateClass.TOTAL,
),
),
(
"garbage_collections",
EcocitoSensorEntityDescription(
key="garbage_collections_total",
translation_key="garbage_collections_total",
icon="mdi:trash-can",
value_fn=get_event_collections_weight,
last_updated_fn=get_latest_date,
unit_of_measurement=UnitOfMass.KILOGRAMS,
state_class=SensorStateClass.TOTAL,
suggested_display_precision=0,
),
),
(
"garbage_collections",
EcocitoSensorEntityDescription(
key="latest_garbage_collections",
translation_key="latest_garbage_collection",
icon="mdi:trash-can",
value_fn=get_latest_event_collection_weight,
last_updated_fn=get_latest_date,
unit_of_measurement=UnitOfMass.KILOGRAMS,
state_class=SensorStateClass.TOTAL,
suggested_display_precision=0,
),
),
(
"garbage_collections_previous",
EcocitoSensorEntityDescription(
key="garbage_collections_count_previous",
translation_key="previous_garbage_collections_count",
icon="mdi:trash-can",
value_fn=get_count,
last_updated_fn=get_latest_date,
state_class=SensorStateClass.TOTAL,
),
),
(
"garbage_collections_previous",
EcocitoSensorEntityDescription(
key="garbage_collections_total_previous",
translation_key="previous_garbage_collections_total",
icon="mdi:trash-can",
value_fn=get_event_collections_weight,
last_updated_fn=get_latest_date,
unit_of_measurement=UnitOfMass.KILOGRAMS,
state_class=SensorStateClass.TOTAL,
suggested_display_precision=0,
),
),
(
"recycling_collections",
EcocitoSensorEntityDescription(
key="recycling_collections_count",
translation_key="recycling_collections_count",
icon="mdi:recycle",
value_fn=get_count,
last_updated_fn=get_latest_date,
state_class=SensorStateClass.TOTAL,
),
),
(
"recycling_collections",
EcocitoSensorEntityDescription(
key="recycling_collections_total",
translation_key="recycling_collections_total",
icon="mdi:recycle",
value_fn=get_event_collections_weight,
last_updated_fn=get_latest_date,
unit_of_measurement=UnitOfMass.KILOGRAMS,
state_class=SensorStateClass.TOTAL,
suggested_display_precision=0,
),
),
(
"recycling_collections",
EcocitoSensorEntityDescription(
key="latest_recycling_collections",
translation_key="latest_recycling_collection",
icon="mdi:recycle",
value_fn=get_latest_event_collection_weight,
last_updated_fn=get_latest_date,
unit_of_measurement=UnitOfMass.KILOGRAMS,
state_class=SensorStateClass.TOTAL,
suggested_display_precision=0,
),
),
(
"recycling_collections_previous",
EcocitoSensorEntityDescription(
key="recycling_collections_count_previous",
translation_key="previous_recycling_collections_count",
icon="mdi:recycle",
value_fn=get_count,
last_updated_fn=get_latest_date,
state_class=SensorStateClass.TOTAL,
),
),
(
"recycling_collections_previous",
EcocitoSensorEntityDescription(
key="recycling_collections_total_previous",
translation_key="previous_recycling_collections_total",
icon="mdi:recycle",
value_fn=get_event_collections_weight,
last_updated_fn=get_latest_date,
unit_of_measurement=UnitOfMass.KILOGRAMS,
state_class=SensorStateClass.TOTAL,
suggested_display_precision=0,
),
),
(
"waste_depot_visits",
EcocitoSensorEntityDescription(
key="waste_deposit_visit",
translation_key="waste_deposit_visit",
icon="mdi:car",
value_fn=get_count,
last_updated_fn=get_latest_date,
state_class=SensorStateClass.TOTAL,
),
),
)
class EcocitoSensor(EcocitoEntity[T], SensorEntity):
"""Implementation of the Ecocito sensor."""
_attr_attribution = DEVICE_ATTRIBUTION
_attr_has_entity_name = True
@property
def native_value(self) -> str | int:
"""Return the state of the sensor."""
return self.entity_description.value_fn(self.coordinator.data)
@property
def extra_state_attributes(self) -> dict[str, str] | None:
"""Return the state attributes of the sensor."""
return {
"last_updated": self.entity_description.last_updated_fn(
self.coordinator.data
),
}
async def async_setup_entry(
hass: HomeAssistant,
entry: EcocitoConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Ecocito sensors based on a config entry."""
entities: list[EcocitoSensor[Any]] = []
for coordinator_type, description in SENSOR_TYPES:
coordinator = getattr(entry.runtime_data, coordinator_type)
if coordinator:
entities.append(EcocitoSensor(coordinator, description))
async_add_entities(entities)