diff --git a/homeassistant/components/logbook/__init__.py b/homeassistant/components/logbook/__init__.py index fb1b9d78b89..ee2ae3da4d9 100644 --- a/homeassistant/components/logbook/__init__.py +++ b/homeassistant/components/logbook/__init__.py @@ -19,7 +19,7 @@ from homeassistant.const import ( ATTR_NAME, EVENT_LOGBOOK_ENTRY, ) -from homeassistant.core import Context, Event, HomeAssistant, ServiceCall, callback +from homeassistant.core import Context, HomeAssistant, ServiceCall, callback from homeassistant.helpers import config_validation as cv from homeassistant.helpers.entityfilter import ( INCLUDE_EXCLUDE_BASE_FILTER_SCHEMA, @@ -35,7 +35,6 @@ from . import rest_api, websocket_api from .const import ( # noqa: F401 ATTR_MESSAGE, DOMAIN, - LOGBOOK_ENTITIES_FILTER, LOGBOOK_ENTRY_CONTEXT_ID, LOGBOOK_ENTRY_DOMAIN, LOGBOOK_ENTRY_ENTITY_ID, @@ -43,9 +42,8 @@ from .const import ( # noqa: F401 LOGBOOK_ENTRY_MESSAGE, LOGBOOK_ENTRY_NAME, LOGBOOK_ENTRY_SOURCE, - LOGBOOK_FILTERS, ) -from .models import LazyEventPartialState # noqa: F401 +from .models import LazyEventPartialState, LogbookConfig CONFIG_SCHEMA = vol.Schema( {DOMAIN: INCLUDE_EXCLUDE_BASE_FILTER_SCHEMA}, extra=vol.ALLOW_EXTRA @@ -97,7 +95,6 @@ def async_log_entry( async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Logbook setup.""" - hass.data[DOMAIN] = {} @callback def log_message(service: ServiceCall) -> None: @@ -134,8 +131,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: else: filters = None entities_filter = None - hass.data[LOGBOOK_FILTERS] = filters - hass.data[LOGBOOK_ENTITIES_FILTER] = entities_filter + + external_events: dict[ + str, tuple[str, Callable[[LazyEventPartialState], dict[str, Any]]] + ] = {} + hass.data[DOMAIN] = LogbookConfig(external_events, filters, entities_filter) websocket_api.async_setup(hass) rest_api.async_setup(hass, config, filters, entities_filter) hass.services.async_register(DOMAIN, "log", log_message, schema=LOG_MESSAGE_SCHEMA) @@ -149,14 +149,16 @@ async def _process_logbook_platform( hass: HomeAssistant, domain: str, platform: Any ) -> None: """Process a logbook platform.""" + logbook_config: LogbookConfig = hass.data[DOMAIN] + external_events = logbook_config.external_events @callback def _async_describe_event( domain: str, event_name: str, - describe_callback: Callable[[Event], dict[str, Any]], + describe_callback: Callable[[LazyEventPartialState], dict[str, Any]], ) -> None: """Teach logbook how to describe a new event.""" - hass.data[DOMAIN][event_name] = (domain, describe_callback) + external_events[event_name] = (domain, describe_callback) platform.async_describe_events(hass, _async_describe_event) diff --git a/homeassistant/components/logbook/const.py b/homeassistant/components/logbook/const.py index e1abd987659..2d9911117f9 100644 --- a/homeassistant/components/logbook/const.py +++ b/homeassistant/components/logbook/const.py @@ -44,6 +44,3 @@ AUTOMATION_EVENTS = {EVENT_AUTOMATION_TRIGGERED, EVENT_SCRIPT_STARTED} # Events that are built-in to the logbook or core BUILT_IN_EVENTS = {EVENT_LOGBOOK_ENTRY, EVENT_CALL_SERVICE} - -LOGBOOK_FILTERS = "logbook_filters" -LOGBOOK_ENTITIES_FILTER = "entities_filter" diff --git a/homeassistant/components/logbook/helpers.py b/homeassistant/components/logbook/helpers.py index 221612e1e97..c8f55331de1 100644 --- a/homeassistant/components/logbook/helpers.py +++ b/homeassistant/components/logbook/helpers.py @@ -27,7 +27,7 @@ from homeassistant.helpers.entityfilter import EntityFilter from homeassistant.helpers.event import async_track_state_change_event from .const import ALWAYS_CONTINUOUS_DOMAINS, AUTOMATION_EVENTS, BUILT_IN_EVENTS, DOMAIN -from .models import LazyEventPartialState +from .models import LogbookConfig def async_filter_entities(hass: HomeAssistant, entity_ids: list[str]) -> list[str]: @@ -63,9 +63,8 @@ def async_determine_event_types( hass: HomeAssistant, entity_ids: list[str] | None, device_ids: list[str] | None ) -> tuple[str, ...]: """Reduce the event types based on the entity ids and device ids.""" - external_events: dict[ - str, tuple[str, Callable[[LazyEventPartialState], dict[str, Any]]] - ] = hass.data.get(DOMAIN, {}) + logbook_config: LogbookConfig = hass.data[DOMAIN] + external_events = logbook_config.external_events if not entity_ids and not device_ids: return (*BUILT_IN_EVENTS, *external_events) diff --git a/homeassistant/components/logbook/models.py b/homeassistant/components/logbook/models.py index a5ce9eddcec..ab073f296f7 100644 --- a/homeassistant/components/logbook/models.py +++ b/homeassistant/components/logbook/models.py @@ -1,11 +1,13 @@ """Event parser and human readable log generator.""" from __future__ import annotations +from collections.abc import Callable from dataclasses import dataclass from typing import Any, cast from sqlalchemy.engine.row import Row +from homeassistant.components.recorder.filters import Filters from homeassistant.components.recorder.models import ( bytes_to_ulid_or_none, bytes_to_uuid_hex_or_none, @@ -14,11 +16,23 @@ from homeassistant.components.recorder.models import ( ) from homeassistant.const import ATTR_ICON, EVENT_STATE_CHANGED from homeassistant.core import Context, Event, State, callback +from homeassistant.helpers.entityfilter import EntityFilter import homeassistant.util.dt as dt_util from homeassistant.util.json import json_loads from homeassistant.util.ulid import ulid_to_bytes +@dataclass +class LogbookConfig: + """Configuration for the logbook integration.""" + + external_events: dict[ + str, tuple[str, Callable[[LazyEventPartialState], dict[str, Any]]] + ] + sqlalchemy_filter: Filters | None = None + entity_filter: EntityFilter | None = None + + class LazyEventPartialState: """A lazy version of core Event with limited State joined in.""" diff --git a/homeassistant/components/logbook/processor.py b/homeassistant/components/logbook/processor.py index 39d8e920aa4..f816064ba69 100644 --- a/homeassistant/components/logbook/processor.py +++ b/homeassistant/components/logbook/processor.py @@ -52,10 +52,9 @@ from .const import ( LOGBOOK_ENTRY_SOURCE, LOGBOOK_ENTRY_STATE, LOGBOOK_ENTRY_WHEN, - LOGBOOK_FILTERS, ) from .helpers import is_sensor_continuous -from .models import EventAsRow, LazyEventPartialState, async_event_to_row +from .models import EventAsRow, LazyEventPartialState, LogbookConfig, async_event_to_row from .queries import statement_for_request from .queries.common import PSEUDO_EVENT_STATE_CHANGED @@ -97,16 +96,14 @@ class EventProcessor: self.entity_ids = entity_ids self.device_ids = device_ids self.context_id = context_id - self.filters: Filters | None = hass.data[LOGBOOK_FILTERS] + logbook_config: LogbookConfig = hass.data[DOMAIN] + self.filters: Filters | None = logbook_config.sqlalchemy_filter format_time = ( _row_time_fired_timestamp if timestamp else _row_time_fired_isoformat ) - external_events: dict[ - str, tuple[str, Callable[[LazyEventPartialState], dict[str, Any]]] - ] = hass.data.get(DOMAIN, {}) self.logbook_run = LogbookRun( context_lookup=ContextLookup(hass), - external_events=external_events, + external_events=logbook_config.external_events, event_cache=EventCache({}), entity_name_cache=EntityNameCache(self.hass), include_entity_name=include_entity_name, diff --git a/homeassistant/components/logbook/websocket_api.py b/homeassistant/components/logbook/websocket_api.py index dac0da83c36..6d24285ba11 100644 --- a/homeassistant/components/logbook/websocket_api.py +++ b/homeassistant/components/logbook/websocket_api.py @@ -20,13 +20,13 @@ from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.helpers.json import JSON_DUMP import homeassistant.util.dt as dt_util -from .const import LOGBOOK_ENTITIES_FILTER +from .const import DOMAIN from .helpers import ( async_determine_event_types, async_filter_entities, async_subscribe_events, ) -from .models import async_event_to_row +from .models import LogbookConfig, async_event_to_row from .processor import EventProcessor MAX_PENDING_LOGBOOK_EVENTS = 2048 @@ -361,7 +361,8 @@ async def ws_event_stream( entities_filter: EntityFilter | None = None if not event_processor.limited_select: - entities_filter = hass.data[LOGBOOK_ENTITIES_FILTER] + logbook_config: LogbookConfig = hass.data[DOMAIN] + entities_filter = logbook_config.entity_filter async_subscribe_events( hass, diff --git a/tests/components/logbook/common.py b/tests/components/logbook/common.py index d08366e2f1b..b8d00681112 100644 --- a/tests/components/logbook/common.py +++ b/tests/components/logbook/common.py @@ -6,6 +6,7 @@ from typing import Any from homeassistant.components import logbook from homeassistant.components.logbook import processor +from homeassistant.components.logbook.models import LogbookConfig from homeassistant.components.recorder.models import ( process_timestamp_to_utc_isoformat, ulid_to_bytes_or_none, @@ -64,7 +65,8 @@ def mock_humanify(hass_, rows): ent_reg = er.async_get(hass_) event_cache = processor.EventCache({}) context_lookup = processor.ContextLookup(hass_) - external_events = hass_.data.get(logbook.DOMAIN, {}) + logbook_config = hass_.data.get(logbook.DOMAIN, LogbookConfig({}, None, None)) + external_events = logbook_config.external_events logbook_run = processor.LogbookRun( context_lookup, external_events,