From 6ce0e756d0f979e6ddb48c692f08e98d8f04293c Mon Sep 17 00:00:00 2001 From: Snuffy2 Date: Thu, 4 Jul 2024 18:05:06 -0400 Subject: [PATCH] Use _unrecorded_attributes instead of recorder_history_prefilter --- custom_components/variable/binary_sensor.py | 39 ++-- custom_components/variable/device_tracker.py | 42 ++-- custom_components/variable/manifest.json | 6 +- .../recorder_history_prefilter/.gitattributes | 2 - .../recorder_history_prefilter/LICENSE | 21 -- .../recorder_history_prefilter/README.md | 121 ----------- .../recorder_prefilter.py | 199 ------------------ custom_components/variable/sensor.py | 41 ++-- 8 files changed, 51 insertions(+), 420 deletions(-) delete mode 100644 custom_components/variable/recorder_history_prefilter/.gitattributes delete mode 100644 custom_components/variable/recorder_history_prefilter/LICENSE delete mode 100644 custom_components/variable/recorder_history_prefilter/README.md delete mode 100644 custom_components/variable/recorder_history_prefilter/recorder_prefilter.py diff --git a/custom_components/variable/binary_sensor.py b/custom_components/variable/binary_sensor.py index 50f2ae4..9a05cba 100644 --- a/custom_components/variable/binary_sensor.py +++ b/custom_components/variable/binary_sensor.py @@ -3,7 +3,6 @@ import logging from homeassistant.components.binary_sensor import PLATFORM_SCHEMA, BinarySensorEntity -from homeassistant.components.recorder import DATA_INSTANCE as RECORDER_INSTANCE from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_FRIENDLY_NAME, @@ -11,6 +10,7 @@ CONF_DEVICE_CLASS, CONF_ICON, CONF_NAME, + MATCH_ALL, STATE_OFF, STATE_ON, Platform, @@ -35,10 +35,10 @@ CONF_VALUE, CONF_VARIABLE_ID, CONF_YAML_VARIABLE, + DEFAULT_EXCLUDE_FROM_RECORDER, DEFAULT_REPLACE_ATTRIBUTES, DOMAIN, ) -from .recorder_history_prefilter import recorder_prefilter _LOGGER = logging.getLogger(__name__) @@ -103,7 +103,14 @@ async def async_setup_entry( # _LOGGER.debug(f"[async_setup_entry] config: {config}") # _LOGGER.debug(f"[async_setup_entry] unique_id: {unique_id}") - async_add_entities([Variable(hass, config, config_entry, unique_id)]) + if config.get(CONF_EXCLUDE_FROM_RECORDER, DEFAULT_EXCLUDE_FROM_RECORDER): + _LOGGER.debug( + f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID, None))}) " + "Excluding from Recorder" + ) + async_add_entities([VariableNoRecorder(hass, config, config_entry, unique_id)]) + else: + async_add_entities([Variable(hass, config, config_entry, unique_id)]) return True @@ -119,9 +126,7 @@ def __init__( unique_id, ): """Initialize a Binary Sensor Variable.""" - _LOGGER.debug( - f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID))}) [init] config: {config}" - ) + # _LOGGER.debug(f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID))}) [init] config: {config}") if config.get(CONF_VALUE) is None or ( isinstance(config.get(CONF_VALUE), str) and config.get(CONF_VALUE).lower() in ["", "none", "unknown", "unavailable"] @@ -140,10 +145,7 @@ def __init__( self._attr_has_entity_name = True self._variable_id = slugify(config.get(CONF_VARIABLE_ID).lower()) self._attr_unique_id = unique_id - if config.get(CONF_NAME) is not None: - self._attr_name = config.get(CONF_NAME) - else: - self._attr_name = config.get(CONF_VARIABLE_ID) + self._attr_name = config.get(CONF_NAME, config.get(CONF_VARIABLE_ID, None)) self._attr_icon = config.get(CONF_ICON) self._attr_device_class = config.get(CONF_DEVICE_CLASS) self._restore = config.get(CONF_RESTORE) @@ -174,11 +176,6 @@ def __init__( if self._exclude_from_recorder: self.disable_recorder() - def disable_recorder(self): - if RECORDER_INSTANCE in self._hass.data: - _LOGGER.info(f"({self._attr_name}) [disable_recorder] Disabling Recorder") - recorder_prefilter.add_filter(self._hass, self.entity_id) - async def async_added_to_hass(self): """Run when entity about to be added.""" await super().async_added_to_hass() @@ -229,14 +226,6 @@ async def async_added_to_hass(self): + f"{self._config_entry.data.get(CONF_UPDATED)}" ) - async def async_will_remove_from_hass(self) -> None: - """Run when entity will be removed from hass.""" - if RECORDER_INSTANCE in self._hass.data and self._exclude_from_recorder: - _LOGGER.debug( - f"({self._attr_name}) Removing entity exclusion from recorder: {self.entity_id}" - ) - recorder_prefilter.remove_filter(self._hass, self.entity_id) - @property def should_poll(self): """If entity should be polled.""" @@ -387,3 +376,7 @@ async def async_toggle_variable(self, **kwargs) -> None: ) self.async_write_ha_state() + + +class VariableNoRecorder(Variable): + _unrecorded_attributes = frozenset({MATCH_ALL}) diff --git a/custom_components/variable/device_tracker.py b/custom_components/variable/device_tracker.py index 670798d..d5df447 100644 --- a/custom_components/variable/device_tracker.py +++ b/custom_components/variable/device_tracker.py @@ -10,7 +10,6 @@ SourceType, TrackerEntity, ) -from homeassistant.components.recorder import DATA_INSTANCE as RECORDER_INSTANCE from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_BATTERY_LEVEL, @@ -21,6 +20,7 @@ ATTR_LONGITUDE, CONF_ICON, CONF_NAME, + MATCH_ALL, Platform, ) from homeassistant.core import HomeAssistant @@ -44,10 +44,10 @@ CONF_UPDATED, CONF_VARIABLE_ID, CONF_YAML_VARIABLE, + DEFAULT_EXCLUDE_FROM_RECORDER, DEFAULT_REPLACE_ATTRIBUTES, DOMAIN, ) -from .recorder_history_prefilter import recorder_prefilter _LOGGER = logging.getLogger(__name__) @@ -103,7 +103,14 @@ async def async_setup_entry( # _LOGGER.debug(f"[async_setup_entry] config: {config}") # _LOGGER.debug(f"[async_setup_entry] unique_id: {unique_id}") - async_add_entities([Variable(hass, config, config_entry, unique_id)]) + if config.get(CONF_EXCLUDE_FROM_RECORDER, DEFAULT_EXCLUDE_FROM_RECORDER): + _LOGGER.debug( + f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID, None))}) " + "Excluding from Recorder." + ) + async_add_entities([VariableNoRecorder(hass, config, config_entry, unique_id)]) + else: + async_add_entities([Variable(hass, config, config_entry, unique_id)]) return True @@ -119,20 +126,14 @@ def __init__( unique_id, ): """Initialize a Device Tracker Variable.""" - _LOGGER.debug( - f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID))}) [init] config: {config}" - ) - + # _LOGGER.debug(f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID))}) [init] config: {config}") self._hass = hass self._config = config self._config_entry = config_entry self._attr_has_entity_name = True self._variable_id = slugify(config.get(CONF_VARIABLE_ID).lower()) self._attr_unique_id = unique_id - if config.get(CONF_NAME) is not None: - self._attr_name = config.get(CONF_NAME) - else: - self._attr_name = config.get(CONF_VARIABLE_ID) + self._attr_name = config.get(CONF_NAME, config.get(CONF_VARIABLE_ID, None)) self._attr_icon = config.get(CONF_ICON) self._restore = config.get(CONF_RESTORE) self._force_update = config.get(CONF_FORCE_UPDATE) @@ -165,13 +166,6 @@ def __init__( self._attr_battery_level = config.get(ATTR_BATTERY_LEVEL) self._attr_location_name = config.get(ATTR_LOCATION_NAME) self._attr_gps_accuracy = config.get(ATTR_GPS_ACCURACY) - if self._exclude_from_recorder: - self.disable_recorder() - - def disable_recorder(self): - if RECORDER_INSTANCE in self._hass.data: - _LOGGER.info(f"({self._attr_name}) [disable_recorder] Disabling Recorder") - recorder_prefilter.add_filter(self._hass, self.entity_id) async def async_added_to_hass(self): """Run when entity about to be added.""" @@ -207,14 +201,6 @@ async def async_added_to_hass(self): + f"{self._config_entry.data.get(CONF_UPDATED)}" ) - async def async_will_remove_from_hass(self) -> None: - """Run when entity will be removed from hass.""" - if RECORDER_INSTANCE in self._hass.data and self._exclude_from_recorder: - _LOGGER.debug( - f"({self._attr_name}) Removing entity exclusion from recorder: {self.entity_id}" - ) - recorder_prefilter.remove_filter(self._hass, self.entity_id) - def _update_attr_settings(self, new_attributes=None, just_pop=False): if new_attributes is not None: _LOGGER.debug( @@ -355,3 +341,7 @@ def state_attributes(self) -> dict[str, StateType]: if self._attr_location_name is not None: attr[ATTR_LOCATION_NAME] = self._attr_location_name return attr + + +class VariableNoRecorder(Variable): + _unrecorded_attributes = frozenset({MATCH_ALL}) diff --git a/custom_components/variable/manifest.json b/custom_components/variable/manifest.json index a2d0479..39f091f 100644 --- a/custom_components/variable/manifest.json +++ b/custom_components/variable/manifest.json @@ -9,9 +9,9 @@ ], "config_flow": true, "dependencies": [], - "documentation": "https://github.com/Wibias/hass-variables", + "documentation": "https://github.com/enkama/hass-variables", "iot_class": "local_push", - "issue_tracker": "https://github.com/Wibias/hass-variables/issues", - "requirements": ["iso4217==1.11.20220401"], + "issue_tracker": "https://github.com/enkama/hass-variables/issues", + "requirements": ["iso4217>=1.11.20220401"], "version": "3.4.3" } diff --git a/custom_components/variable/recorder_history_prefilter/.gitattributes b/custom_components/variable/recorder_history_prefilter/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/custom_components/variable/recorder_history_prefilter/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/custom_components/variable/recorder_history_prefilter/LICENSE b/custom_components/variable/recorder_history_prefilter/LICENSE deleted file mode 100644 index 95ea9d3..0000000 --- a/custom_components/variable/recorder_history_prefilter/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 gcobb321 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/custom_components/variable/recorder_history_prefilter/README.md b/custom_components/variable/recorder_history_prefilter/README.md deleted file mode 100644 index 7231164..0000000 --- a/custom_components/variable/recorder_history_prefilter/README.md +++ /dev/null @@ -1,121 +0,0 @@ -# Home Assistant Recorder History Prefilter - -The HA Recorder module was modified in HA 2023.6.0 to no longer allow a custom component to insert a sensor or other type of entity into the *_exclude_e* list that defined the entities that should not be added to the History database (home_assistant_v2.db). - -This module fixes that problem. - - - -## How it Works - -#### The Home Assistant Recorder Component - -When Home Assistant starts, it loads the recorder component. The recorder component gets its parameters from the HA configuration file (configuration.yaml) and builds the list of entities, globs, etc. to be filtered. It then starts a state change listener to call the filter module whenever an entity's state is changed. The filter determines if the entity should be added to the History database, - -For efficiency, Home Assistant builds the filter that is checked one time when Home Assistant is loaded. The filter can not be changed or added to by a custom_component. - -#### The Recorder History Prefilter - -This module injects its own filter (actually a copy of the recorder's filter) into the HA Recorder component, removes the HA listener that was set up by the HA Recorder and sets up a new state change listener. It is called when an entity's state changes instead of the HA Recorder filter and checks to see if the entity should be filtered. It the entity is not in its list, the entity is passed to the HA Recorder filter module as it normally would be. - -### Using the Recorder Prefilter - -Entities are added or removed from this list using function calls from a custom component. More than one custom component can use this. - -#### Adding Entities - -The recorder prefilter is contained in the *recorder_prefilter.py* module. - -- Download it and add it to your code base. - -Import it into your module that determines the entities to be filtered. This may be in *\__init__.py*, *sensor.py* or another module. - -- `import recorder_prefilter` - -A single entity or a list of entities can be added at one time using the *add_filter* function call. - -- `recorder_prefilter.add_filter(hass, 'icloud3_event_log')` -- `recorder_prefilter.add_filter(hass, ['icloud3_event_log', 'icloud3_wazehist_track', 'gary_iphone_info'])` -- `recorder_prefilter.add_filter(hass, [filtered_entities_list)` - -Notes: - -- The entity_type (*input_boolean, light, etc.* ) needs to be used if it is a non-sensor entity. -- The first custom component to use the *add_filter* function call will inject the *recorder_prefilter* into the HA Recorder component. All subsequent *add_filter* calls will update the filter list. - -#### Removing Entities - -Entities can be removed from the filter list using the *remove_filter* function call. - -A single entity or a list of entities can be removed at one time. - -- `recorder_prefilter.remove_filter(hass, 'icloud3_event_log')` - -- `recorder_prefilter.remove_filter(hass, ['icloud3_event_log', 'icloud3_wazehist_track', 'gary_iphone_info'])` - -- `recorder_prefilter.remove_filter(hass, [filtered_entities_list)` - - - -### Logging - -Normal HA Logging is available for the *recorder_prefilter* module. Enable it in configuration.yaml as you would do with any other component. - - logger: - default: info - logs: - custom_components.icloud3.support.recorder_prefilter: info - custom_components.places.recorder_prefilter: info - -**Info logging** - Add basic records to the *home-assistant.log* file - -```Recorder Prefilter Injection Started -Recorder Prefilter Injection Started -Recorder Prefilter Injection Completed -Added Recorder Prefilter Entities (icloud3)-2 -Recorder Prefilter Entities Updated, Entities Filtered-2 -... -... -Added Recorder Prefilter Entities (places)-1 -Recorder Prefilter Entities Updated, Entities Filtered-3 -... -... -Added Recorder Prefilter Entities (icloud3)-6 -Recorder Prefilter Entities Updated, Entities Filtered-9 -``` - - - -**Debug logging** - Add operational records to the *home-assistant.log* file. - - custom_components.icloud3.support.recorder_prefilter: debug - custom_components.places.recorder_prefilter: debug - -```Recorder Prefilter Injection Started -Recorder Prefilter Injection Started -Injecting Custom Exclude Entity Prefilter into Recorder -Removing Recorder Event Listener -Reinitializing Recorder Event Listener -Recorder Prefilter Injection Completed -Added Prefilter Entities-['icloud3_event_log', 'icloud3_wazehist_track'] -Added Recorder Prefilter Entities (icloud3)-2 -All Prefiltered Entities-['sensor.icloud3_event_log', 'sensor.icloud3_wazehist_track'] -Recorder Prefilter Entities Updated, Entities Filtered-2 -... -... -Added Prefilter Entities-sensor.gary_place -Added Recorder Prefilter Entities (places)-1 -All Prefiltered Entities-['sensor.gary_place', 'sensor.icloud3_event_log', 'sensor.icloud3_wazehist_track'] -Recorder Prefilter Entities Updated, Entities Filtered-3 -... -... -Added Prefilter Entities-['sensor.gary_iphone_info', 'sensor.gary_iphone_trigger', 'sensor.lillian_iphone_info', 'sensor.lillian_iphone_trigger', 'sensor.lillian_watch_info', 'sensor.lillian_watch_trigger'] -Added Recorder Prefilter Entities (icloud3)-6 -All Prefiltered Entities-['sensor.gary_iphone_info', 'sensor.gary_iphone_trigger', 'sensor.gary_place', 'sensor.icloud3_event_log', 'sensor.icloud3_wazehist_track', 'sensor.lillian_iphone_info', 'sensor.lillian_iphone_trigger', 'sensor.lillian_watch_info', 'sensor.lillian_watch_trigger'] -Recorder Prefilter Entities Updated, Entities Filtered-9 - -``` - - - -Developed by: Gary Cobb, *iCloud3 iDevice Tracker custom component*, (aka geekstergary) \ No newline at end of file diff --git a/custom_components/variable/recorder_history_prefilter/recorder_prefilter.py b/custom_components/variable/recorder_history_prefilter/recorder_prefilter.py deleted file mode 100644 index f8d0629..0000000 --- a/custom_components/variable/recorder_history_prefilter/recorder_prefilter.py +++ /dev/null @@ -1,199 +0,0 @@ -# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -# -# HA RECORDER - EXCLUDE entities FROM BEING ADDED TO HISTORY DATABASE -# -# -# The HA Recorder module was modified in HA 2023.6.0 to no longer allow a -# custom component to insert entity names in the '_exclude_e' list -# that defined entity entities to not be added to the History database -# (home_assistant_v2.db). -# -# This module fixes that problem by using a code injection process to -# provide a local prefilter to determine if an entity should be added before -# the Recorder filter. -# -# -# This injection has two methods: -# add_filter - Add entities to the filter list -# ---------- -# hass - HomeAssistant -# entities to be filtered - -# single entity - entity_id (string) -# multiple entities - list of entity ids -# -# 'sensor.' will be added to the beginning of the entity id -# if its type is not specified -# -# recorder_prefilter.add_filter(hass, 'filter_id1') -# recorder_prefilter.add_filter(hass, ['filter_entity2', 'filter_entity3']) -# -# -# ------------- -# remove_filter - Remove entities from the filter list -# ------------- -# Same arguments for add_filter -# -# recorder_prefilter.remove_filter(hass, 'filter_id1') -# recorder_prefilter.remove_filter(hass, -# ['filter_entity2', 'filter_entity3']) -# -# -# Gary Cobb, @gcobb321, geekstergary, iCloud3 developer -# iCloud3 iDevice Tracker custom component - An advanced iDevice tracker -# that uses Apple iCloud account and HA Companion App data for presence -# detection and location based automations. -# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -from inspect import getframeinfo, stack -import logging - -from homeassistant.core import HomeAssistant - -_LOGGER = logging.getLogger(__name__) - -VERSION = 1.0 - - -def add_filter(hass: HomeAssistant, entities=None): - """ - Inject the entity prefilter into the Recorder, remove Recorder listeners, - reinitialize the Recorder - - Arguments: - hass - HomeAssistant - entities - A list of entity entities - (['gary_last_update', 'lillian_last_update', '*_next_update']) - - A single entity ('gary_last_zone') - - Returns: - True - The injection was successful - False - The injection was not successful - """ - - ha_recorder = hass.data["recorder_instance"] - - if ha_recorder is None: - return False - - if hass.data.get("recorder_prefilter") is None: - rp_data = hass.data["recorder_prefilter"] = {} - rp_data["injected"] = True - rp_data["legacy"] = True - rp_data["exclude_entities"] = [] - - try: - ha_recorder.entity_filter._exclude_e.add(entities) - return True - except Exception: # nosec B110 - pass - - rp_data["legacy"] = False - - if _inject_filter(hass) is False: - return - - _update_filter(hass, entities) - - -def remove_filter(hass: HomeAssistant, entities): - if hass.data["recorder_prefilter"]["legacy"]: - try: - ha_recorder = hass.data["recorder_instance"] - ha_recorder.entity_filter._exclude_e.discard(entities) - return True - except Exception as err: - _LOGGER.exception(err) - - _update_filter(hass, entities, remove=True) - - -def _inject_filter(hass: HomeAssistant): - ha_recorder = hass.data["recorder_instance"] - recorder_entity_filter = ha_recorder.entity_filter - recorder_remove_listener = ha_recorder._event_listener - - def entity_filter(entity_id): - """ - Prefilter an entity to see if it should be excluded from - the recorder history. - - This function is injected into the recorder, replacing the - original HA recorder_entity_filter module. - - Return: - False - The entity should is in the filter list - Run the original HA recorder_entity_filter function - - The entity is not in the filter list. - """ - if ( - entity_id - and entity_id in hass.data["recorder_prefilter"]["exclude_entities"] - ): - return False - - return recorder_entity_filter(entity_id) - - try: - _LOGGER.info("Recorder Prefilter Injection Started") - _LOGGER.debug("Injecting Custom Exclude Entity Prefilter into Recorder") - ha_recorder.entity_filter = entity_filter - - _LOGGER.debug("Removing Recorder Event Listener") - recorder_remove_listener() - - _LOGGER.debug("Reinitializing Recorder Event Listener") - hass.add_job(ha_recorder.async_initialize) - - _LOGGER.info("Recorder Prefilter Injection Completed") - - return True - - except Exception as err: - _LOGGER.info(f"Recorder Prefilter Injection Failed ({err})") - _LOGGER.exception(err) - - return False - - -def _update_filter(hass: HomeAssistant, entities=None, remove=False): - """Update the filtered entity list""" - - mode = "Removed" if remove else "Added" - cust_component = _called_from() - entities_cnt = 1 if type(entities) is str else len(entities) - - _LOGGER.debug(f"{mode} Prefilter Entities ({cust_component})-{entities}") - _LOGGER.info( - f"{mode} Recorder Prefilter Entities ({cust_component})-{entities_cnt}" - ) - - entities = ( - [entities] - if type(entities) is str - else entities - if type(entities) is list - else [] - ) - - rp_data = hass.data.get("recorder_prefilter") - rp_exclude_entities = rp_data["exclude_entities"] - - for entity in entities: - if entity.find(".") == -1: - entity = f"sensor.{entity}" - if entity not in rp_exclude_entities: - if remove is False: - rp_exclude_entities.append(entity) - elif entity in rp_exclude_entities: - rp_exclude_entities.remove(entity) - - _LOGGER.debug(f"All Prefiltered Entities-{sorted(rp_exclude_entities)}") - _LOGGER.info( - f"Recorder Prefilter Entities Updated, " - f"Entities Filtered-{len(rp_exclude_entities)}" - ) - - -def _called_from(): - cust_component = getframeinfo(stack()[0][0]).filename - return cust_component.split("custom_components/")[1].split("/")[0] diff --git a/custom_components/variable/sensor.py b/custom_components/variable/sensor.py index ba99dd9..1263213 100644 --- a/custom_components/variable/sensor.py +++ b/custom_components/variable/sensor.py @@ -2,7 +2,6 @@ import copy import logging -from homeassistant.components.recorder import DATA_INSTANCE as RECORDER_INSTANCE from homeassistant.components.sensor import ( CONF_STATE_CLASS, PLATFORM_SCHEMA, @@ -16,6 +15,7 @@ CONF_ICON, CONF_NAME, CONF_UNIT_OF_MEASUREMENT, + MATCH_ALL, Platform, ) from homeassistant.core import HomeAssistant @@ -48,7 +48,6 @@ DOMAIN, ) from .helpers import value_to_type -from .recorder_history_prefilter import recorder_prefilter _LOGGER = logging.getLogger(__name__) @@ -106,7 +105,14 @@ async def async_setup_entry( config = hass.data.get(DOMAIN).get(config_entry.entry_id) unique_id = config_entry.entry_id - async_add_entities([Variable(hass, config, config_entry, unique_id)]) + if config.get(CONF_EXCLUDE_FROM_RECORDER, DEFAULT_EXCLUDE_FROM_RECORDER): + _LOGGER.debug( + f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID, None))}) " + "Excluding from Recorder" + ) + async_add_entities([VariableNoRecorder(hass, config, config_entry, unique_id)]) + else: + async_add_entities([Variable(hass, config, config_entry, unique_id)]) return True @@ -122,19 +128,14 @@ def __init__( unique_id, ): """Initialize a Sensor Variable.""" - # _LOGGER.debug( - # f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID))}) [init] config: {config}" - # ) + # _LOGGER.debug(f"({config.get(CONF_NAME, config.get(CONF_VARIABLE_ID))}) [init] config: {config}") self._hass = hass self._config = config self._config_entry = config_entry self._attr_has_entity_name = True self._variable_id = slugify(config.get(CONF_VARIABLE_ID).lower()) self._attr_unique_id = unique_id - if config.get(CONF_NAME) is not None: - self._attr_name = config.get(CONF_NAME) - else: - self._attr_name = config.get(CONF_VARIABLE_ID) + self._attr_name = config.get(CONF_NAME, config.get(CONF_VARIABLE_ID, None)) registry = er.async_get(self._hass) current_entity_id = registry.async_get_entity_id( PLATFORM, DOMAIN, self._attr_unique_id @@ -180,13 +181,7 @@ def __init__( except ValueError: self._attr_native_value = None - if self._exclude_from_recorder: - self.disable_recorder() - - def disable_recorder(self): - if RECORDER_INSTANCE in self._hass.data: - _LOGGER.info(f"({self._attr_name}) [disable_recorder] Disabling Recorder") - recorder_prefilter.add_filter(self._hass, self.entity_id) + # _LOGGER.debug(f"({self._attr_name}) [init] unrecorded_attributes: {self._unrecorded_attributes}") async def async_added_to_hass(self): """Run when entity about to be added.""" @@ -250,14 +245,6 @@ async def async_added_to_hass(self): + f"{self._config_entry.data.get(CONF_UPDATED)}" ) - async def async_will_remove_from_hass(self) -> None: - """Run when entity will be removed from hass.""" - if RECORDER_INSTANCE in self._hass.data and self._exclude_from_recorder: - _LOGGER.debug( - f"({self._attr_name}) Removing entity exclusion from recorder: {self.entity_id}" - ) - recorder_prefilter.remove_filter(self._hass, self.entity_id) - @property def should_poll(self): """If entity should be polled.""" @@ -353,3 +340,7 @@ async def async_update_variable(self, **kwargs) -> None: f"({self._attr_name}) [updated] attributes: {self._attr_extra_state_attributes}" ) self.async_write_ha_state() + + +class VariableNoRecorder(Variable): + _unrecorded_attributes = frozenset({MATCH_ALL})