home_assistant/custom_components/anniversaries/calendar.py

137 lines
4.9 KiB
Python

"""Anniversaries calendar."""
import logging
from datetime import datetime, timedelta
from homeassistant.components.calendar import CalendarEntity, CalendarEvent
from homeassistant.core import HomeAssistant
from homeassistant.util import Throttle
from .const import CALENDAR_NAME, CALENDAR_PLATFORM, DOMAIN, SENSOR_PLATFORM
_LOGGER = logging.getLogger(__name__)
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None
) -> None:
"""Add calendar entities to HA, of there are calendar instances."""
# pylint: disable=unused-argument
# Only single instance allowed
if not AnniversariesCalendar.instances:
async_add_entities([AnniversariesCalendar()], True)
class AnniversariesCalendar(CalendarEntity):
"""The Anniversaries collection calendar class."""
instances = False
def __init__(self) -> None:
"""Create empty calendar."""
self._cal_data: dict = {}
self._attr_name = CALENDAR_NAME
AnniversariesCalendar.instances = True
@property
def event(self) -> CalendarEvent | None:
"""Return the next upcoming event."""
return self.hass.data[DOMAIN][CALENDAR_PLATFORM].event
@property
def name(self) -> str | None:
"""Return the name of the entity."""
return self._attr_name
async def async_update(self) -> None:
"""Update all calendars."""
await self.hass.data[DOMAIN][CALENDAR_PLATFORM].async_update()
async def async_get_events(
self, hass: HomeAssistant, start_date: datetime, end_date: datetime
) -> list[CalendarEvent]:
"""Get all events in a specific time frame."""
return await self.hass.data[DOMAIN][CALENDAR_PLATFORM].async_get_events(
hass, start_date, end_date
)
@property
def extra_state_attributes(self) -> dict | None:
"""Return the device state attributes."""
if self.hass.data[DOMAIN][CALENDAR_PLATFORM].event is None:
# No tasks, we don't need to show anything.
return None
return {}
class EntitiesCalendarData:
"""Class used by the Entities Calendar class to hold all entity events."""
__slots__ = "_hass", "event", "entities", "_throttle"
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize an Entities Calendar Data."""
self._hass = hass
self.event: CalendarEvent | None = None
self.entities: list[str] = []
def add_entity(self, entity_id: str) -> None:
"""Append entity ID to the calendar."""
if entity_id not in self.entities:
self.entities.append(entity_id)
def remove_entity(self, entity_id: str) -> None:
"""Remove entity ID from the calendar."""
if entity_id in self.entities:
self.entities.remove(entity_id)
async def async_get_events(
self, hass: HomeAssistant, start_datetime: datetime, end_datetime: datetime
) -> list[CalendarEvent]:
"""Get all events in a specific time frame."""
events: list[CalendarEvent] = []
_LOGGER.debug("Anniversaries Calendar - Get Events")
if SENSOR_PLATFORM not in hass.data[DOMAIN]:
return events
start_date = start_datetime.date()
end_date = end_datetime.date()
for ent in self.entities:
_LOGGER.debug("Get Events: Entity Name: " + str(ent))
if (ent not in hass.data[DOMAIN][SENSOR_PLATFORM]):
continue
entity = self._hass.data[DOMAIN][SENSOR_PLATFORM][ent]
if (
entity
and entity.name
and entity._next_date.date()
and start_date <= entity._next_date.date() <= end_date
):
event = CalendarEvent(
summary=entity.name,
start=entity._next_date.date(),
end=entity._next_date.date() + timedelta(days=1),
description=entity.extra_state_attributes["description"]
if "description" in entity.extra_state_attributes
else None,
)
events.append(event)
return events
@Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self) -> None:
"""Get the latest data."""
_LOGGER.debug("Update anniversary calendar")
for ent in self.entities:
_LOGGER.debug("Update Entity Name: " + str(ent))
entity = self._hass.data[DOMAIN][SENSOR_PLATFORM][ent]
if entity and entity.name and entity._date:
self.event = CalendarEvent(
summary=entity.name,
start=entity._next_date.date(),
end=entity._next_date.date() + timedelta(days=1),
description=entity.extra_state_attributes["description"]
if "description" in entity.extra_state_attributes
else None,
)