1 """Event parser and human readable log generator."""
3 from __future__
import annotations
5 from collections.abc
import Callable, Mapping
6 from dataclasses
import dataclass
7 from typing
import TYPE_CHECKING, Any, Final, NamedTuple, cast
9 from propcache
import cached_property
10 from sqlalchemy.engine.row
import Row
14 bytes_to_ulid_or_none,
15 bytes_to_uuid_hex_or_none,
16 ulid_to_bytes_or_none,
17 uuid_hex_to_bytes_or_none,
26 @dataclass(slots=True)
28 """Configuration for the logbook integration."""
30 external_events: dict[
32 tuple[str, Callable[[LazyEventPartialState], dict[str, Any]]],
34 sqlalchemy_filter: Filters |
None =
None
35 entity_filter: Callable[[str], bool] |
None =
None
39 """A lazy version of core Event with limited State joined in."""
43 row: Row | EventAsRow,
44 event_data_cache: dict[str, dict[str, Any]],
46 """Init the lazy event."""
50 if type(row)
is EventAsRow:
53 self.
datadata = row[DATA_POS]
56 source = cast(str, row[EVENT_DATA_POS])
58 source = row[EVENT_DATA_POS]
61 elif event_data := event_data_cache.get(source):
62 self.
datadata = event_data
64 self.
datadata = event_data_cache[source] = cast(
70 """Return the event type."""
71 return self.
rowrow[EVENT_TYPE_POS]
75 """Return the entity id."""
76 return self.
rowrow[ENTITY_ID_POS]
80 """Return the state."""
81 return self.
rowrow[STATE_POS]
85 """Return the context id."""
86 return bytes_to_ulid_or_none(self.
rowrow[CONTEXT_ID_BIN_POS])
90 """Return the context user id."""
95 """Return the context parent id."""
96 return bytes_to_ulid_or_none(self.
rowrow[CONTEXT_PARENT_ID_BIN_POS])
101 ROW_ID_POS: Final = 0
102 EVENT_TYPE_POS: Final = 1
103 EVENT_DATA_POS: Final = 2
104 TIME_FIRED_TS_POS: Final = 3
105 CONTEXT_ID_BIN_POS: Final = 4
106 CONTEXT_USER_ID_BIN_POS: Final = 5
107 CONTEXT_PARENT_ID_BIN_POS: Final = 6
109 ENTITY_ID_POS: Final = 8
111 CONTEXT_ONLY_POS: Final = 10
114 CONTEXT_POS: Final = 12
118 """Convert an event to a row.
120 This much always match the order of the columns in queries/common.py
124 event_type: EventType[Any] | str |
None
125 event_data: str |
None
127 context_id_bin: bytes
128 context_user_id_bin: bytes |
None
129 context_parent_id_bin: bytes |
None
131 entity_id: str |
None
133 context_only: bool |
None
136 data: Mapping[str, Any]
142 """Convert an event to a row."""
143 if event.event_type != EVENT_STATE_CHANGED:
144 context = event.context
147 event_type=event.event_type,
149 time_fired_ts=event.time_fired_timestamp,
150 context_id_bin=ulid_to_bytes(context.id),
152 context_parent_id_bin=ulid_to_bytes_or_none(context.parent_id),
163 new_state: State = event.data[
"new_state"]
164 context = new_state.context
169 time_fired_ts=new_state.last_updated_timestamp,
170 context_id_bin=ulid_to_bytes(context.id),
172 context_parent_id_bin=ulid_to_bytes_or_none(context.parent_id),
173 state=new_state.state,
174 entity_id=new_state.entity_id,
175 icon=new_state.attributes.get(ATTR_ICON),
None __init__(self, Row|EventAsRow row, dict[str, dict[str, Any]] event_data_cache)
str|None context_id(self)
str|None context_user_id(self)
EventType[Any]|str|None event_type(self)
str|None context_parent_id(self)
EventAsRow async_event_to_row(Event event)
str|None bytes_to_uuid_hex_or_none(bytes|None _bytes)
bytes|None uuid_hex_to_bytes_or_none(str|None uuid_hex)