diff --git a/custom_components/calendar_merge/calendar_handler.py b/custom_components/calendar_merge/calendar_handler.py index dc6944f..54aad40 100644 --- a/custom_components/calendar_merge/calendar_handler.py +++ b/custom_components/calendar_merge/calendar_handler.py @@ -13,13 +13,14 @@ from homeassistant.components.calendar import CalendarEvent from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_ENTITY_ID -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, State from homeassistant.exceptions import TemplateError -from homeassistant.helpers import issue_registry as ir +from homeassistant.helpers import entity_registry as er, issue_registry as ir from homeassistant.helpers.template import Template from homeassistant.util import dt as dt_util from .const import ( + CONF_CALENDAR_ENTITY_IDS, CONF_DAYS_AHEAD, CONF_FORMAT_LANGUAGE, CONF_MAX_EVENTS, @@ -32,6 +33,7 @@ DOMAIN, DOMAIN_NAME, LOGGER, + TRANSLATION_KEY_MISSING_ENTITY, TRANSLATION_KEY_TEMPLATE_ERROR, ) @@ -167,66 +169,68 @@ def __init__( CONF_FORMAT_LANGUAGE, self.hass.config.language ) + registry = er.async_get(hass) + self.calendar_entities: list[str] = er.async_validate_entity_ids( + registry, entry.options[CONF_CALENDAR_ENTITY_IDS] + ) + self.last_error_template: str = "" self.last_error_txt_template: str = "" - self.next_update: datetime = datetime.now() self.supress_update_listener: bool = False + self.show_event_as_time_to: bool = entry.options.get( + CONF_SHOW_EVENT_AS_TIME_TO, False + ) + # ------------------------------------------------------ async def merge_calendar_events( self, - calendar_entities: list[str], - force_update: bool = False, ) -> None: - """Process calendar events.""" - - if force_update or self.next_update < datetime.now(): - self.events = [] - - try: - tmp_events: dict = await self.hass.services.async_call( - "calendar", - "get_events", - service_data={ - ATTR_ENTITY_ID: calendar_entities, - "end_date_time": ( - dt_util.now() - + timedelta( - days=self.entry.options.get(CONF_DAYS_AHEAD, 30) - ) - ).isoformat(), - "start_date_time": dt_util.now().isoformat(), - }, - blocking=True, - return_response=True, - ) - # except (ServiceValidationError, ServiceNotFound, vol.Invalid) as err: - except Exception as err: # noqa: BLE001 - LOGGER.error(err) - return - - for key in tmp_events: - for event in tmp_events[key]["events"]: - self.events.append( - CalendarMergeEvent( - str(key) - .replace("calendar.", "") - .replace("_", " ") - .capitalize(), - event["start"], - event["end"], - event.get("summary", ""), - event.get("description", ""), - event.get("location", ""), - ) + """Merge calendar events.""" + + self.events = [] + + try: + tmp_events: dict = await self.hass.services.async_call( + "calendar", + "get_events", + service_data={ + ATTR_ENTITY_ID: self.calendar_entities, + "end_date_time": ( + dt_util.now() + + timedelta(days=self.entry.options.get(CONF_DAYS_AHEAD, 30)) + ).isoformat(), + "start_date_time": dt_util.now().isoformat(), + }, + blocking=True, + return_response=True, + ) + # except (ServiceValidationError, ServiceNotFound, vol.Invalid) as err: + except Exception as err: # noqa: BLE001 + LOGGER.error(err) + return + + for key in tmp_events: + for event in tmp_events[key]["events"]: + self.events.append( + CalendarMergeEvent( + str(key) + .replace("calendar.", "") + .replace("_", " ") + .capitalize(), + event["start"], + event["end"], + event.get("summary", ""), + event.get("description", ""), + event.get("location", ""), ) + ) - if self.entry.options.get(CONF_REMOVE_RECURRING_EVENTS, True): - self.remove_recurring_events() + if self.entry.options.get(CONF_REMOVE_RECURRING_EVENTS, True): + self.remove_recurring_events() - self.events.sort(key=lambda x: x.start_datetime_local.isoformat()) - self.events = self.events[: int(self.entry.options.get(CONF_MAX_EVENTS, 5))] - self.next_update = datetime.now() + timedelta(minutes=5) + self.events.sort(key=lambda x: x.start_datetime_local.isoformat()) + self.events = self.events[: int(self.entry.options.get(CONF_MAX_EVENTS, 5))] # ------------------------------------------------------ def remove_recurring_events(self) -> None: @@ -303,7 +307,7 @@ async def async_format_event(self, event_num: int) -> str | None: get_locale(self.language).timeframes.get("now", "now").capitalize() ) - elif self.entry.options.get(CONF_SHOW_EVENT_AS_TIME_TO, False): + elif self.show_event_as_time_to: formatted_event_str: str = await self.hass.async_add_executor_job( partial( format_timedelta, @@ -427,3 +431,25 @@ def create_issue_template( ) self.last_error_template = template self.last_error_txt_template = error_txt + + # ------------------------------------------------------ + async def async_verify_calendar_entities_exist(self) -> bool: + """Verify calendar entities exist.""" + res: bool = True + + for index, calendar_entity in reversed(list(enumerate(self.calendar_entities))): + state: State | None = self.hass.states.get(calendar_entity) + + if state is None: + self.create_issue( + calendar_entity, + TRANSLATION_KEY_MISSING_ENTITY, + { + "entity": calendar_entity, + "calendar_merge_helper": calendar_entity, + }, + ) + del self.calendar_entities[index] + res = False + + return res diff --git a/custom_components/calendar_merge/manifest.json b/custom_components/calendar_merge/manifest.json index 2618ab3..10a1ba5 100644 --- a/custom_components/calendar_merge/manifest.json +++ b/custom_components/calendar_merge/manifest.json @@ -16,6 +16,6 @@ "arrow" ], "ssdp": [], - "version": "1.0.4", + "version": "1.0.5", "zeroconf": [] } \ No newline at end of file diff --git a/custom_components/calendar_merge/sensor.py b/custom_components/calendar_merge/sensor.py index e91a387..820aa28 100644 --- a/custom_components/calendar_merge/sensor.py +++ b/custom_components/calendar_merge/sensor.py @@ -11,7 +11,7 @@ from homeassistant.components.fan import FanEntityFeature from homeassistant.components.sensor import SensorEntity from homeassistant.config_entries import ConfigEntry -from homeassistant.core import Event, HomeAssistant, ServiceCall, State +from homeassistant.core import Event, HomeAssistant, ServiceCall from homeassistant.helpers import ( config_validation as cv, entity_platform, @@ -32,7 +32,6 @@ DOMAIN_NAME, SERVICE_SAVE_SETTINGS, TRANSLATION_KEY, - TRANSLATION_KEY_MISSING_ENTITY, ) @@ -58,7 +57,6 @@ async def async_setup_entry( CalendarMergeEventsSensor( hass, entry, - calendar_entities, x, ) for x in range(int(entry.options.get(CONF_MAX_EVENTS, 5))) @@ -149,13 +147,15 @@ async def async_toggle_show_as_time_to_dispatcher( async def async_toggle_show_as_time_to(self, service_data: ServiceCall) -> None: """Toggle show time as time to.""" - tmp_entry_options: dict[str, Any] = self.entry.options.copy() - - tmp_entry_options[CONF_SHOW_EVENT_AS_TIME_TO] = not self.entry.options.get( - CONF_SHOW_EVENT_AS_TIME_TO, False + self.calendar_handler.show_event_as_time_to = ( + not self.calendar_handler.show_event_as_time_to ) if service_data.data.get(SERVICE_SAVE_SETTINGS, False): + tmp_entry_options: dict[str, Any] = self.entry.options.copy() + tmp_entry_options[CONF_SHOW_EVENT_AS_TIME_TO] = ( + self.calendar_handler.show_event_as_time_to + ) self.update_settings(tmp_entry_options) await self.coordinator.async_refresh() @@ -173,7 +173,7 @@ def update_settings(self, entry_options: dict[str, Any]) -> None: # ------------------------------------------------------------------ async def async_refresh(self) -> None: """Refresh.""" - await self.calendar_handler.merge_calendar_events(self.calendar_entities, True) + await self.calendar_handler.merge_calendar_events() for event_sensor in self.events_sensors: await event_sensor.async_refresh() @@ -204,7 +204,8 @@ async def async_added_to_hass(self) -> None: async def async_hass_started(self, _event: Event) -> None: """Hass started.""" - await self.calendar_handler.merge_calendar_events(self.calendar_entities, True) + await self.calendar_handler.async_verify_calendar_entities_exist() + await self.calendar_handler.merge_calendar_events() self.async_schedule_update_ha_state() await self.coordinator.async_refresh() @@ -295,27 +296,27 @@ def create_issue( translation_placeholders=translation_placeholders, ) - # ------------------------------------------------------ - async def async_verify_calendar_entities_exist(self) -> bool: - """Verify calendar entities exist.""" - res: bool = True + # # ------------------------------------------------------ + # async def async_verify_calendar_entities_exist(self) -> bool: + # """Verify calendar entities exist.""" + # res: bool = True - for index, calendar_entity in reversed(list(enumerate(self.calendar_entities))): - state: State | None = self.hass.states.get(calendar_entity) + # for index, calendar_entity in reversed(list(enumerate(self.calendar_entities))): + # state: State | None = self.hass.states.get(calendar_entity) - if state is None: - self.create_issue( - calendar_entity, - TRANSLATION_KEY_MISSING_ENTITY, - { - "entity": calendar_entity, - "calendar_merge_helper": self.entity_id, - }, - ) - del self.calendar_entities[index] - res = False + # if state is None: + # self.create_issue( + # calendar_entity, + # TRANSLATION_KEY_MISSING_ENTITY, + # { + # "entity": calendar_entity, + # "calendar_merge_helper": self.entity_id, + # }, + # ) + # del self.calendar_entities[index] + # res = False - return res + # return res # ------------------------------------------------------ @@ -328,7 +329,6 @@ def __init__( self, hass: HomeAssistant, entry: ConfigEntry, - calendar_entities: list[str], event_num: int = 0, ) -> None: """Calendar merge events sensor.""" @@ -336,7 +336,6 @@ def __init__( self.hass: HomeAssistant = hass self.entry: ConfigEntry = entry - self.calendar_entities: list[str] = calendar_entities self.calendar_handler: CalendarHandler = hass.data[DOMAIN][entry.entry_id][ "calendar_handler" ]