Refactor logbook helpers to reduce splits and lookups (#108933)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
61c6c70a7d
commit
5dac5d5c7e
3 changed files with 36 additions and 29 deletions
|
@ -39,7 +39,8 @@ def async_filter_entities(hass: HomeAssistant, entity_ids: list[str]) -> list[st
|
||||||
return [
|
return [
|
||||||
entity_id
|
entity_id
|
||||||
for entity_id in entity_ids
|
for entity_id in entity_ids
|
||||||
if not _is_entity_id_filtered(hass, ent_reg, entity_id)
|
if split_entity_id(entity_id)[0] not in ALWAYS_CONTINUOUS_DOMAINS
|
||||||
|
and not is_sensor_continuous(hass, ent_reg, entity_id)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,18 +217,37 @@ def async_subscribe_events(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_sensor_continuous(ent_reg: er.EntityRegistry, entity_id: str) -> bool:
|
def is_sensor_continuous(
|
||||||
"""Determine if a sensor is continuous by checking its state class.
|
hass: HomeAssistant, ent_reg: er.EntityRegistry, entity_id: str
|
||||||
|
) -> bool:
|
||||||
|
"""Determine if a sensor is continuous.
|
||||||
|
|
||||||
Sensors with a unit_of_measurement are also considered continuous, but are filtered
|
Sensors with a unit_of_measurement or state_class are considered continuous.
|
||||||
already by the SQL query generated by _get_events
|
|
||||||
|
The unit_of_measurement check will already happen if this is
|
||||||
|
called for historical data because the SQL query generated by _get_events
|
||||||
|
will filter out any sensors with a unit_of_measurement.
|
||||||
|
|
||||||
|
If the state still exists in the state machine, this function still
|
||||||
|
checks for ATTR_UNIT_OF_MEASUREMENT since the live mode is not filtered
|
||||||
|
by the SQL query.
|
||||||
"""
|
"""
|
||||||
if not (entry := ent_reg.async_get(entity_id)):
|
# If it is in the state machine we can quick check if it
|
||||||
# Entity not registered, so can't have a state class
|
# has a unit_of_measurement or state_class, and filter if
|
||||||
return False
|
# it does
|
||||||
return (
|
if (state := hass.states.get(entity_id)) and (attributes := state.attributes):
|
||||||
entry.capabilities is not None
|
return ATTR_UNIT_OF_MEASUREMENT in attributes or ATTR_STATE_CLASS in attributes
|
||||||
and entry.capabilities.get(ATTR_STATE_CLASS) is not None
|
# If its not in the state machine, we need to check
|
||||||
|
# the entity registry to see if its a sensor
|
||||||
|
# filter with a state class. We do not check
|
||||||
|
# for unit_of_measurement since the SQL query
|
||||||
|
# will filter out any sensors with a unit_of_measurement
|
||||||
|
# and we should never get here in live mode because
|
||||||
|
# the state machine will always have the state.
|
||||||
|
return bool(
|
||||||
|
(entry := ent_reg.async_get(entity_id))
|
||||||
|
and entry.capabilities
|
||||||
|
and entry.capabilities.get(ATTR_STATE_CLASS)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,24 +259,8 @@ def _is_state_filtered(new_state: State, old_state: State) -> bool:
|
||||||
"""
|
"""
|
||||||
return bool(
|
return bool(
|
||||||
new_state.state == old_state.state
|
new_state.state == old_state.state
|
||||||
or split_entity_id(new_state.entity_id)[0] in ALWAYS_CONTINUOUS_DOMAINS
|
|
||||||
or new_state.last_changed != new_state.last_updated
|
or new_state.last_changed != new_state.last_updated
|
||||||
|
or new_state.domain in ALWAYS_CONTINUOUS_DOMAINS
|
||||||
or ATTR_UNIT_OF_MEASUREMENT in new_state.attributes
|
or ATTR_UNIT_OF_MEASUREMENT in new_state.attributes
|
||||||
or ATTR_STATE_CLASS in new_state.attributes
|
or ATTR_STATE_CLASS in new_state.attributes
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _is_entity_id_filtered(
|
|
||||||
hass: HomeAssistant, ent_reg: er.EntityRegistry, entity_id: str
|
|
||||||
) -> bool:
|
|
||||||
"""Check if the logbook should filter an entity.
|
|
||||||
|
|
||||||
Used to setup listeners and which entities to select
|
|
||||||
from the database when a list of entities is requested.
|
|
||||||
"""
|
|
||||||
return bool(
|
|
||||||
split_entity_id(entity_id)[0] in ALWAYS_CONTINUOUS_DOMAINS
|
|
||||||
or (state := hass.states.get(entity_id))
|
|
||||||
and (ATTR_UNIT_OF_MEASUREMENT in state.attributes)
|
|
||||||
or is_sensor_continuous(ent_reg, entity_id)
|
|
||||||
)
|
|
||||||
|
|
|
@ -175,6 +175,7 @@ class EventProcessor:
|
||||||
"""Humanify rows."""
|
"""Humanify rows."""
|
||||||
return list(
|
return list(
|
||||||
_humanify(
|
_humanify(
|
||||||
|
self.hass,
|
||||||
rows,
|
rows,
|
||||||
self.ent_reg,
|
self.ent_reg,
|
||||||
self.logbook_run,
|
self.logbook_run,
|
||||||
|
@ -184,6 +185,7 @@ class EventProcessor:
|
||||||
|
|
||||||
|
|
||||||
def _humanify(
|
def _humanify(
|
||||||
|
hass: HomeAssistant,
|
||||||
rows: Generator[EventAsRow, None, None] | Sequence[Row] | Result,
|
rows: Generator[EventAsRow, None, None] | Sequence[Row] | Result,
|
||||||
ent_reg: er.EntityRegistry,
|
ent_reg: er.EntityRegistry,
|
||||||
logbook_run: LogbookRun,
|
logbook_run: LogbookRun,
|
||||||
|
@ -219,7 +221,7 @@ def _humanify(
|
||||||
if (
|
if (
|
||||||
is_continuous := continuous_sensors.get(entity_id)
|
is_continuous := continuous_sensors.get(entity_id)
|
||||||
) is None and split_entity_id(entity_id)[0] == SENSOR_DOMAIN:
|
) is None and split_entity_id(entity_id)[0] == SENSOR_DOMAIN:
|
||||||
is_continuous = is_sensor_continuous(ent_reg, entity_id)
|
is_continuous = is_sensor_continuous(hass, ent_reg, entity_id)
|
||||||
continuous_sensors[entity_id] = is_continuous
|
continuous_sensors[entity_id] = is_continuous
|
||||||
if is_continuous:
|
if is_continuous:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -77,6 +77,7 @@ def mock_humanify(hass_, rows):
|
||||||
context_augmenter = processor.ContextAugmenter(logbook_run)
|
context_augmenter = processor.ContextAugmenter(logbook_run)
|
||||||
return list(
|
return list(
|
||||||
processor._humanify(
|
processor._humanify(
|
||||||
|
hass_,
|
||||||
rows,
|
rows,
|
||||||
ent_reg,
|
ent_reg,
|
||||||
logbook_run,
|
logbook_run,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue