Home Assistant Unofficial Reference 2024.12.1
legacy.py
Go to the documentation of this file.
1 """Models for Recorder."""
2 
3 from __future__ import annotations
4 
5 from datetime import datetime
6 from typing import Any
7 
8 from sqlalchemy.engine.row import Row
9 
10 from homeassistant.const import (
11  COMPRESSED_STATE_ATTRIBUTES,
12  COMPRESSED_STATE_LAST_CHANGED,
13  COMPRESSED_STATE_LAST_UPDATED,
14  COMPRESSED_STATE_STATE,
15 )
16 from homeassistant.core import Context, State
17 import homeassistant.util.dt as dt_util
18 
19 from .state_attributes import decode_attributes_from_source
20 from .time import process_timestamp
21 
22 
24  """A lazy version of core State after schema 31."""
25 
26  __slots__ = [
27  "_row",
28  "_attributes",
29  "_last_changed_ts",
30  "_last_updated_ts",
31  "_last_reported_ts",
32  "_context",
33  "attr_cache",
34  ]
35 
36  def __init__( # pylint: disable=super-init-not-called
37  self,
38  row: Row,
39  attr_cache: dict[str, dict[str, Any]],
40  start_time: datetime | None,
41  entity_id: str | None = None,
42  ) -> None:
43  """Init the lazy state."""
44  self._row_row = row
45  self.entity_identity_identity_id = entity_id or self._row_row.entity_id
46  self.statestatestate = self._row_row.state or ""
47  self._attributes_attributes: dict[str, Any] | None = None
48  self._last_updated_ts_last_updated_ts: float | None = self._row_row.last_updated_ts or (
49  dt_util.utc_to_timestamp(start_time) if start_time else None
50  )
51  self._last_changed_ts_last_changed_ts: float | None = (
52  self._row_row.last_changed_ts or self._last_updated_ts_last_updated_ts
53  )
54  self._last_reported_ts_last_reported_ts: float | None = self._last_updated_ts_last_updated_ts
55  self._context_context: Context | None = None
56  self.attr_cacheattr_cache = attr_cache
57 
58  @property # type: ignore[override]
59  def attributes(self) -> dict[str, Any]:
60  """State attributes."""
61  if self._attributes_attributes is None:
63  self._row_row, self.attr_cacheattr_cache
64  )
65  return self._attributes_attributes
66 
67  @attributes.setter
68  def attributes(self, value: dict[str, Any]) -> None:
69  """Set attributes."""
70  self._attributes_attributes = value
71 
72  @property
73  def context(self) -> Context:
74  """State context."""
75  if self._context_context is None:
76  self._context_context = Context(id=None)
77  return self._context_context
78 
79  @context.setter
80  def context(self, value: Context) -> None:
81  """Set context."""
82  self._context_context = value
83 
84  @property
85  def last_changed(self) -> datetime:
86  """Last changed datetime."""
87  assert self._last_changed_ts_last_changed_ts is not None
88  return dt_util.utc_from_timestamp(self._last_changed_ts_last_changed_ts)
89 
90  @last_changed.setter
91  def last_changed(self, value: datetime) -> None:
92  """Set last changed datetime."""
93  self._last_changed_ts_last_changed_ts = process_timestamp(value).timestamp()
94 
95  @property
96  def last_reported(self) -> datetime:
97  """Last reported datetime."""
98  assert self._last_reported_ts_last_reported_ts is not None
99  return dt_util.utc_from_timestamp(self._last_reported_ts_last_reported_ts)
100 
101  @last_reported.setter
102  def last_reported(self, value: datetime) -> None:
103  """Set last reported datetime."""
104  self._last_reported_ts_last_reported_ts = process_timestamp(value).timestamp()
105 
106  @property
107  def last_updated(self) -> datetime:
108  """Last updated datetime."""
109  assert self._last_updated_ts_last_updated_ts is not None
110  return dt_util.utc_from_timestamp(self._last_updated_ts_last_updated_ts)
111 
112  @last_updated.setter
113  def last_updated(self, value: datetime) -> None:
114  """Set last updated datetime."""
115  self._last_updated_ts_last_updated_ts = process_timestamp(value).timestamp()
116 
117  def as_dict(self) -> dict[str, Any]: # type: ignore[override]
118  """Return a dict representation of the LazyState.
119 
120  Async friendly.
121  To be used for JSON serialization.
122  """
123  last_updated_isoformat = self.last_updatedlast_updatedlast_updatedlast_updated.isoformat()
124  if self._last_changed_ts_last_changed_ts == self._last_updated_ts_last_updated_ts:
125  last_changed_isoformat = last_updated_isoformat
126  else:
127  last_changed_isoformat = self.last_changedlast_changedlast_changedlast_changed.isoformat()
128  return {
129  "entity_id": self.entity_identity_identity_id,
130  "state": self.statestatestate,
131  "attributes": self._attributes_attributes or self.attributesattributesattributesattributes,
132  "last_changed": last_changed_isoformat,
133  "last_updated": last_updated_isoformat,
134  }
135 
136 
138  row: Row,
139  attr_cache: dict[str, dict[str, Any]],
140  start_time: datetime | None,
141  entity_id: str | None = None,
142 ) -> dict[str, Any]:
143  """Convert a database row to a compressed state schema 31 and later."""
144  comp_state = {
145  COMPRESSED_STATE_STATE: row.state,
146  COMPRESSED_STATE_ATTRIBUTES: decode_attributes_from_row_legacy(row, attr_cache),
147  }
148  if start_time:
149  comp_state[COMPRESSED_STATE_LAST_UPDATED] = dt_util.utc_to_timestamp(start_time)
150  else:
151  row_last_updated_ts: float = row.last_updated_ts
152  comp_state[COMPRESSED_STATE_LAST_UPDATED] = row_last_updated_ts
153  if (
154  row_last_changed_ts := row.last_changed_ts
155  ) and row_last_updated_ts != row_last_changed_ts:
156  comp_state[COMPRESSED_STATE_LAST_CHANGED] = row_last_changed_ts
157  return comp_state
158 
159 
161  row: Row, attr_cache: dict[str, dict[str, Any]]
162 ) -> dict[str, Any]:
163  """Decode attributes from a database row."""
165  getattr(row, "shared_attrs", None) or getattr(row, "attributes", None),
166  attr_cache,
167  )
None __init__(self, Row row, dict[str, dict[str, Any]] attr_cache, datetime|None start_time, str|None entity_id=None)
Definition: legacy.py:42
dict[str, Any] legacy_row_to_compressed_state(Row row, dict[str, dict[str, Any]] attr_cache, datetime|None start_time, str|None entity_id=None)
Definition: legacy.py:142
dict[str, Any] decode_attributes_from_row_legacy(Row row, dict[str, dict[str, Any]] attr_cache)
Definition: legacy.py:162
dict[str, Any] decode_attributes_from_source(Any source, dict[str, dict[str, Any]] attr_cache)