Exclude last_changed when same as last_updated for history websocket api (#71886)

This commit is contained in:
J. Nick Koston 2022-05-15 01:03:56 -05:00 committed by GitHub
parent 6a6d31180b
commit 65f44bd80b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 34 deletions

View File

@ -19,7 +19,7 @@ from sqlalchemy.sql.expression import literal
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
@ -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)
@ -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

View File

@ -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."""
if start_time:
last_changed = last_updated = start_time.timestamp()
else:
row_last_updated: datetime = 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
)
else:
last_changed = process_datetime_to_timestamp(row_changed_changed)
last_updated = process_datetime_to_timestamp(row_last_updated)
return {
comp_state = {
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,
}
if start_time:
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 (
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
)
return comp_state

View File

@ -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"] == {}
@ -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"
@ -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"
@ -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"] == {}
@ -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"
@ -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"
@ -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(