Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions homeassistant/components/recorder/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from homeassistant.components import recorder
from homeassistant.components.websocket_api.const import (
COMPRESSED_STATE_LAST_CHANGED,
COMPRESSED_STATE_LAST_UPDATED,
COMPRESSED_STATE_STATE,
)
from homeassistant.core import HomeAssistant, State, split_entity_id
Expand Down Expand Up @@ -662,12 +662,12 @@ def _sorted_states_to_dict(
_process_timestamp: Callable[
[datetime], float | str
] = process_datetime_to_timestamp
attr_last_changed = COMPRESSED_STATE_LAST_CHANGED
attr_time = COMPRESSED_STATE_LAST_UPDATED
attr_state = COMPRESSED_STATE_STATE
else:
state_class = LazyState # type: ignore[assignment]
_process_timestamp = process_timestamp_to_utc_isoformat
attr_last_changed = LAST_CHANGED_KEY
attr_time = LAST_CHANGED_KEY
attr_state = STATE_KEY

result: dict[str, list[State | dict[str, Any]]] = defaultdict(list)
Expand Down Expand Up @@ -742,7 +742,7 @@ def _sorted_states_to_dict(
#
# We use last_updated for for last_changed since its the same
#
attr_last_changed: _process_timestamp(row.last_updated),
attr_time: _process_timestamp(row.last_updated),
}
)
prev_state = state
Expand Down
28 changes: 13 additions & 15 deletions homeassistant/components/recorder/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,23 +798,21 @@ def row_to_compressed_state(
start_time: datetime | None = None,
) -> dict[str, Any]:
"""Convert a database row to a compressed state."""
comp_state = {
COMPRESSED_STATE_STATE: row.state,
COMPRESSED_STATE_ATTRIBUTES: decode_attributes_from_row(row, attr_cache),
}
if start_time:
last_changed = last_updated = start_time.timestamp()
comp_state[COMPRESSED_STATE_LAST_UPDATED] = start_time.timestamp()
else:
row_last_updated: datetime = row.last_updated
comp_state[COMPRESSED_STATE_LAST_UPDATED] = process_datetime_to_timestamp(
row_last_updated
)
if (
not (row_changed_changed := row.last_changed)
or row_last_updated == row_changed_changed
):
last_changed = last_updated = process_datetime_to_timestamp(
row_last_updated
row_changed_changed := row.last_changed
) and row_last_updated != row_changed_changed:
comp_state[COMPRESSED_STATE_LAST_CHANGED] = process_datetime_to_timestamp(
row_changed_changed
)
else:
last_changed = process_datetime_to_timestamp(row_changed_changed)
last_updated = process_datetime_to_timestamp(row_last_updated)
return {
COMPRESSED_STATE_STATE: row.state,
COMPRESSED_STATE_ATTRIBUTES: decode_attributes_from_row(row, attr_cache),
COMPRESSED_STATE_LAST_CHANGED: last_changed,
COMPRESSED_STATE_LAST_UPDATED: last_updated,
}
return comp_state
31 changes: 18 additions & 13 deletions tests/components/history/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -1133,11 +1133,12 @@ async def test_history_during_period(hass, hass_ws_client, recorder_mock):
assert sensor_test_history[0]["s"] == "on"
assert sensor_test_history[0]["a"] == {}
assert isinstance(sensor_test_history[0]["lu"], float)
assert isinstance(sensor_test_history[0]["lc"], float)
assert "lc" not in sensor_test_history[0] # skipped if the same a last_updated (lu)

assert "a" not in sensor_test_history[1]
assert sensor_test_history[1]["s"] == "off"
assert isinstance(sensor_test_history[1]["lc"], float)
assert isinstance(sensor_test_history[1]["lu"], float)
assert "lc" not in sensor_test_history[1] # skipped if the same a last_updated (lu)

assert sensor_test_history[2]["s"] == "on"
assert sensor_test_history[2]["a"] == {}
Expand All @@ -1163,10 +1164,11 @@ async def test_history_during_period(hass, hass_ws_client, recorder_mock):
assert sensor_test_history[0]["s"] == "on"
assert sensor_test_history[0]["a"] == {"any": "attr"}
assert isinstance(sensor_test_history[0]["lu"], float)
assert isinstance(sensor_test_history[0]["lc"], float)
assert "lc" not in sensor_test_history[0] # skipped if the same a last_updated (lu)

assert sensor_test_history[1]["s"] == "off"
assert isinstance(sensor_test_history[1]["lc"], float)
assert isinstance(sensor_test_history[1]["lu"], float)
assert "lc" not in sensor_test_history[1] # skipped if the same a last_updated (lu)
assert sensor_test_history[1]["a"] == {"any": "attr"}

assert sensor_test_history[4]["s"] == "on"
Expand All @@ -1193,10 +1195,11 @@ async def test_history_during_period(hass, hass_ws_client, recorder_mock):
assert sensor_test_history[0]["s"] == "on"
assert sensor_test_history[0]["a"] == {"any": "attr"}
assert isinstance(sensor_test_history[0]["lu"], float)
assert isinstance(sensor_test_history[0]["lc"], float)
assert "lc" not in sensor_test_history[0] # skipped if the same a last_updated (lu)

assert sensor_test_history[1]["s"] == "off"
assert isinstance(sensor_test_history[1]["lc"], float)
assert isinstance(sensor_test_history[1]["lu"], float)
assert "lc" not in sensor_test_history[1] # skipped if the same a last_updated (lu)
assert sensor_test_history[1]["a"] == {"any": "attr"}

assert sensor_test_history[2]["s"] == "on"
Expand Down Expand Up @@ -1331,11 +1334,11 @@ async def test_history_during_period_significant_domain(
assert sensor_test_history[0]["s"] == "on"
assert sensor_test_history[0]["a"] == {}
assert isinstance(sensor_test_history[0]["lu"], float)
assert isinstance(sensor_test_history[0]["lc"], float)
assert "lc" not in sensor_test_history[0] # skipped if the same a last_updated (lu)

assert "a" in sensor_test_history[1]
assert sensor_test_history[1]["s"] == "off"
assert isinstance(sensor_test_history[1]["lc"], float)
assert "lc" not in sensor_test_history[1] # skipped if the same a last_updated (lu)

assert sensor_test_history[4]["s"] == "on"
assert sensor_test_history[4]["a"] == {}
Expand All @@ -1361,10 +1364,11 @@ async def test_history_during_period_significant_domain(
assert sensor_test_history[0]["s"] == "on"
assert sensor_test_history[0]["a"] == {"temperature": "1"}
assert isinstance(sensor_test_history[0]["lu"], float)
assert isinstance(sensor_test_history[0]["lc"], float)
assert "lc" not in sensor_test_history[0] # skipped if the same a last_updated (lu)

assert sensor_test_history[1]["s"] == "off"
assert isinstance(sensor_test_history[1]["lc"], float)
assert isinstance(sensor_test_history[1]["lu"], float)
assert "lc" not in sensor_test_history[1] # skipped if the same a last_updated (lu)
assert sensor_test_history[1]["a"] == {"temperature": "2"}

assert sensor_test_history[4]["s"] == "on"
Expand All @@ -1391,10 +1395,11 @@ async def test_history_during_period_significant_domain(
assert sensor_test_history[0]["s"] == "on"
assert sensor_test_history[0]["a"] == {"temperature": "1"}
assert isinstance(sensor_test_history[0]["lu"], float)
assert isinstance(sensor_test_history[0]["lc"], float)
assert "lc" not in sensor_test_history[0] # skipped if the same a last_updated (lu)

assert sensor_test_history[1]["s"] == "off"
assert isinstance(sensor_test_history[1]["lc"], float)
assert isinstance(sensor_test_history[1]["lu"], float)
assert "lc" not in sensor_test_history[1] # skipped if the same a last_updated (lu)
assert sensor_test_history[1]["a"] == {"temperature": "2"}

assert sensor_test_history[2]["s"] == "off"
Expand Down Expand Up @@ -1429,7 +1434,7 @@ async def test_history_during_period_significant_domain(
assert sensor_test_history[0]["s"] == "on"
assert sensor_test_history[0]["a"] == {"temperature": "5"}
assert sensor_test_history[0]["lu"] == later.timestamp()
assert sensor_test_history[0]["lc"] == later.timestamp()
assert "lc" not in sensor_test_history[0] # skipped if the same a last_updated (lu)


async def test_history_during_period_bad_start_time(
Expand Down