From c08ceb67eaade0201f72176e78c7585317c52a1a Mon Sep 17 00:00:00 2001 From: "Kurt G. Nielsen" <17993863+kgn3400@users.noreply.github.com> Date: Sat, 1 Jun 2024 17:23:03 +0200 Subject: [PATCH] Creating issue if template rendering fails --- custom_components/carousel/base_classes.py | 75 ++++++++++++++----- custom_components/carousel/binary_sensor.py | 18 ++--- custom_components/carousel/const.py | 1 + custom_components/carousel/manifest.json | 2 +- custom_components/carousel/sensor.py | 11 ++- .../carousel/translations/da.json | 4 + .../carousel/translations/en.json | 4 + 7 files changed, 83 insertions(+), 32 deletions(-) diff --git a/custom_components/carousel/base_classes.py b/custom_components/carousel/base_classes.py index f584a32..5ee40ec 100644 --- a/custom_components/carousel/base_classes.py +++ b/custom_components/carousel/base_classes.py @@ -21,6 +21,7 @@ State, callback, ) +from homeassistant.exceptions import TemplateError from homeassistant.helpers import ( config_validation as cv, entity_platform, @@ -52,6 +53,7 @@ SERVICE_SHOW_FOR, SERVICE_SHOW_X_TIMES, TRANSLATION_KEY_MISSING_ENTITY, + TRANSLATION_KEY_TEMPLATE_ERROR, RefreshType, ) from .timer_trigger import TimerTrigger @@ -115,6 +117,9 @@ def __init__( self.timer_trigger: TimerTrigger + self.last_error_template: str = "" + self.last_error_txt_template: str = "" + self.coordinator: DataUpdateCoordinator = DataUpdateCoordinator( self.hass, LOGGER, @@ -329,25 +334,28 @@ async def async_refresh_entity(): if len(self.entities_list) > 0 and self.entry.options.get( CONF_SHOW_IF_TEMPLATE, "" ): - while tmp_res != "True" and any( - item.is_visible for item in self.entities_list - ): - # self.async_write_ha_state() + tmp_pos: int = 1 + + while tmp_res != "True" and tmp_pos <= len(self.entities_list): tmp_state: State = self.hass.states.get(self.current_entity.entity_id) template_values: dict = { "state": tmp_state.state, "state_attributes": tmp_state.attributes.copy(), } - value_template: Template | None = Template( - str(self.entry.options.get(CONF_SHOW_IF_TEMPLATE)), self.hass - ) + try: + value_template: Template | None = Template( + str(self.entry.options.get(CONF_SHOW_IF_TEMPLATE)), self.hass + ) + + tmp_res = str(value_template.async_render(template_values)) - tmp_res = str( - value_template.async_render_with_possible_json_value( - "", variables=template_values + except (TypeError, TemplateError) as e: + await self.async_create_issue_template( + str(e), TRANSLATION_KEY_TEMPLATE_ERROR ) - ) + tmp_res = "" + break if tmp_res == "True": self.entities_list[self.current_entity_pos].is_visible = True @@ -356,7 +364,9 @@ async def async_refresh_entity(): self.entities_list[self.current_entity_pos].is_visible = False await async_refresh_entity() - if not any(item.is_visible for item in self.entities_list): + tmp_pos += 1 + + if tmp_res != "True": self.current_entity = None return @@ -403,11 +413,12 @@ async def async_refresh_common_first_part(self) -> None: async def async_refresh_common_last_part(self) -> None: """Refresh common last part.""" - self.cancel_state_listener = async_track_state_change_event( - self.hass, - self.current_entity.entity_id, - self.sensor_state_listener, - ) + if self.current_entity is not None: + self.cancel_state_listener = async_track_state_change_event( + self.hass, + self.current_entity.entity_id, + self.sensor_state_listener, + ) # ------------------------------------------------------ @callback @@ -441,6 +452,36 @@ async def async_create_issue_entity( }, ) + # ------------------------------------------------------------------ + async def async_create_issue_template( + self, error_txt: str, translation_key: str + ) -> None: + """Create issue on entity.""" + + if ( + self.last_error_template + != self.entry.options.get(CONF_SHOW_IF_TEMPLATE, "") + or error_txt != self.last_error_txt_template + ): + LOGGER.warning(error_txt) + + ir.async_create_issue( + self.hass, + DOMAIN, + DOMAIN_NAME + datetime.now().isoformat(), + issue_domain=DOMAIN, + is_fixable=False, + severity=ir.IssueSeverity.WARNING, + translation_key=translation_key, + translation_placeholders={ + "error_txt": error_txt, + "template": self.entry.options.get(CONF_SHOW_IF_TEMPLATE, ""), + "carousel_helper": self.entity_id, + }, + ) + self.last_error_template = self.entry.options.get(CONF_SHOW_IF_TEMPLATE, "") + self.last_error_txt_template = error_txt + # ------------------------------------------------------ async def async_will_remove_from_hass(self) -> None: """Run when entity will be removed from hass.""" diff --git a/custom_components/carousel/binary_sensor.py b/custom_components/carousel/binary_sensor.py index 1661c86..019b1aa 100644 --- a/custom_components/carousel/binary_sensor.py +++ b/custom_components/carousel/binary_sensor.py @@ -82,16 +82,6 @@ async def async_refresh(self) -> None: await self.async_refresh_common() - # await self.async_refresh_common_first_part() - - # self.current_entity = self.entities_list[ - # self.current_entity_pos - # ] = await self.async_get_entity_info(self.current_entity) - - # self.device_class = self.current_entity.device_class - - # await self.async_refresh_common_last_part() - # ------------------------------------------------------ @property def name(self) -> str: @@ -156,6 +146,14 @@ def extra_state_attributes(self) -> dict: if self.current_entity is not None and self.current_entity.state is not None: attr = self.current_entity.state.attributes.copy() + tmp_count: int = 0 + + for item in self.entities_list: + if item.is_visible: + tmp_count += 1 + + attr["entities visible"] = tmp_count + return attr # ------------------------------------------------------ diff --git a/custom_components/carousel/const.py b/custom_components/carousel/const.py index 2d9d92e..7d46c2f 100644 --- a/custom_components/carousel/const.py +++ b/custom_components/carousel/const.py @@ -10,6 +10,7 @@ TRANSLATION_KEY = DOMAIN TRANSLATION_KEY_MISSING_ENTITY = "missing_entity" TRANSLATION_KEY_MISSING__TIMER_ENTITY = "missing_timer_entity" +TRANSLATION_KEY_TEMPLATE_ERROR = "template_error" CONF_ENTITY_IDS = "entity_ids" CONF_ROTATE_EVERY_MINUTES = "rotate_every_minutes" diff --git a/custom_components/carousel/manifest.json b/custom_components/carousel/manifest.json index 7e7353a..6b55c4d 100644 --- a/custom_components/carousel/manifest.json +++ b/custom_components/carousel/manifest.json @@ -13,6 +13,6 @@ "issue_tracker": "https://github.com/kgn3400/carousel/issues", "requirements": [], "ssdp": [], - "version": "1.0.4", + "version": "1.0.5", "zeroconf": [] } \ No newline at end of file diff --git a/custom_components/carousel/sensor.py b/custom_components/carousel/sensor.py index 13e778a..f4e090b 100644 --- a/custom_components/carousel/sensor.py +++ b/custom_components/carousel/sensor.py @@ -210,10 +210,13 @@ def extra_state_attributes(self) -> dict: if self.current_entity is not None and self.current_entity.state is not None: attr = self.current_entity.state.attributes.copy() - if any(item.is_visible for item in self.entities_list): - attr["any entities visible"] = True - else: - attr["any entities visible"] = False + tmp_count: int = 0 + + for item in self.entities_list: + if item.is_visible: + tmp_count += 1 + + attr["entities visible"] = tmp_count return attr diff --git a/custom_components/carousel/translations/da.json b/custom_components/carousel/translations/da.json index 390556c..6b69d3a 100644 --- a/custom_components/carousel/translations/da.json +++ b/custom_components/carousel/translations/da.json @@ -134,6 +134,10 @@ "missing_timer_entity": { "description": "Det ser ud til, at Timer hjælpefunktionen `{timer_entity}` enten er blevet slettet eller omdøbt som brug i Karrusel hjælpefunktionen `{entity}`.\n\n Venligst ret dette problem.", "title": "Karrusel hjælper: Timer hjælper slettet eller omdøbt" + }, + "template_error": { + "description": "Behandling af vis hvis skabelon `{template}` fejler.\nFejl: `{error_txt}` \n\n Venligst ret dette problem.", + "title": "Karrusel hjælper: Skabelon fejl" } }, "services": { diff --git a/custom_components/carousel/translations/en.json b/custom_components/carousel/translations/en.json index 3fadc2b..450d941 100644 --- a/custom_components/carousel/translations/en.json +++ b/custom_components/carousel/translations/en.json @@ -134,6 +134,10 @@ "missing_timer_entity": { "description": "It looks like either the Timer helper `{timer_entity}` has been deleted or renamed for use in Carousel helper `{entity}`. \n\n Please fix this problem.", "title": "Carousel helper: Timer helper deleted or renamed" + }, + "template_error": { + "description": "Rendering show if template `{template}` ends in error.\nError: `{error_txt}` \n\n Please fix this problem.", + "title": "Carousel helper: Template error" } }, "services": {