Generate json for history and logbook websocket responses in the executor (#71813)
This commit is contained in:
parent
4885331509
commit
9bd508c0bf
2 changed files with 138 additions and 46 deletions
|
@ -1,12 +1,12 @@
|
|||
"""Provide pre-made queries on top of the recorder component."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable, MutableMapping
|
||||
from collections.abc import Iterable
|
||||
from datetime import datetime as dt, timedelta
|
||||
from http import HTTPStatus
|
||||
import logging
|
||||
import time
|
||||
from typing import Any, cast
|
||||
from typing import Any, Literal, cast
|
||||
|
||||
from aiohttp import web
|
||||
from sqlalchemy import not_, or_
|
||||
|
@ -24,8 +24,10 @@ from homeassistant.components.recorder.statistics import (
|
|||
statistics_during_period,
|
||||
)
|
||||
from homeassistant.components.recorder.util import session_scope
|
||||
from homeassistant.components.websocket_api import messages
|
||||
from homeassistant.components.websocket_api.const import JSON_DUMP
|
||||
from homeassistant.const import CONF_DOMAINS, CONF_ENTITIES, CONF_EXCLUDE, CONF_INCLUDE
|
||||
from homeassistant.core import HomeAssistant, State
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.deprecation import deprecated_class, deprecated_function
|
||||
from homeassistant.helpers.entityfilter import (
|
||||
|
@ -104,6 +106,23 @@ class LazyState(history_models.LazyState):
|
|||
"""A lazy version of core State."""
|
||||
|
||||
|
||||
def _ws_get_statistics_during_period(
|
||||
hass: HomeAssistant,
|
||||
msg_id: int,
|
||||
start_time: dt,
|
||||
end_time: dt | None = None,
|
||||
statistic_ids: list[str] | None = None,
|
||||
period: Literal["5minute", "day", "hour", "month"] = "hour",
|
||||
) -> str:
|
||||
"""Fetch statistics and convert them to json in the executor."""
|
||||
return JSON_DUMP(
|
||||
messages.result_message(
|
||||
msg_id,
|
||||
statistics_during_period(hass, start_time, end_time, statistic_ids, period),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required("type"): "history/statistics_during_period",
|
||||
|
@ -136,15 +155,28 @@ async def ws_get_statistics_during_period(
|
|||
else:
|
||||
end_time = None
|
||||
|
||||
statistics = await get_instance(hass).async_add_executor_job(
|
||||
statistics_during_period,
|
||||
hass,
|
||||
start_time,
|
||||
end_time,
|
||||
msg.get("statistic_ids"),
|
||||
msg.get("period"),
|
||||
connection.send_message(
|
||||
await get_instance(hass).async_add_executor_job(
|
||||
_ws_get_statistics_during_period,
|
||||
hass,
|
||||
msg["id"],
|
||||
start_time,
|
||||
end_time,
|
||||
msg.get("statistic_ids"),
|
||||
msg.get("period"),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _ws_get_list_statistic_ids(
|
||||
hass: HomeAssistant,
|
||||
msg_id: int,
|
||||
statistic_type: Literal["mean"] | Literal["sum"] | None = None,
|
||||
) -> str:
|
||||
"""Fetch a list of available statistic_id and convert them to json in the executor."""
|
||||
return JSON_DUMP(
|
||||
messages.result_message(msg_id, list_statistic_ids(hass, None, statistic_type))
|
||||
)
|
||||
connection.send_result(msg["id"], statistics)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
|
@ -158,13 +190,46 @@ async def ws_get_list_statistic_ids(
|
|||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
|
||||
) -> None:
|
||||
"""Fetch a list of available statistic_id."""
|
||||
statistic_ids = await get_instance(hass).async_add_executor_job(
|
||||
list_statistic_ids,
|
||||
hass,
|
||||
None,
|
||||
msg.get("statistic_type"),
|
||||
connection.send_message(
|
||||
await get_instance(hass).async_add_executor_job(
|
||||
_ws_get_list_statistic_ids,
|
||||
hass,
|
||||
msg["id"],
|
||||
msg.get("statistic_type"),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _ws_get_significant_states(
|
||||
hass: HomeAssistant,
|
||||
msg_id: int,
|
||||
start_time: dt,
|
||||
end_time: dt | None = None,
|
||||
entity_ids: list[str] | None = None,
|
||||
filters: Any | None = None,
|
||||
include_start_time_state: bool = True,
|
||||
significant_changes_only: bool = True,
|
||||
minimal_response: bool = False,
|
||||
no_attributes: bool = False,
|
||||
) -> str:
|
||||
"""Fetch history significant_states and convert them to json in the executor."""
|
||||
return JSON_DUMP(
|
||||
messages.result_message(
|
||||
msg_id,
|
||||
history.get_significant_states(
|
||||
hass,
|
||||
start_time,
|
||||
end_time,
|
||||
entity_ids,
|
||||
filters,
|
||||
include_start_time_state,
|
||||
significant_changes_only,
|
||||
minimal_response,
|
||||
no_attributes,
|
||||
True,
|
||||
),
|
||||
)
|
||||
)
|
||||
connection.send_result(msg["id"], statistic_ids)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
|
@ -220,24 +285,22 @@ async def ws_get_history_during_period(
|
|||
significant_changes_only = msg["significant_changes_only"]
|
||||
no_attributes = msg["no_attributes"]
|
||||
minimal_response = msg["minimal_response"]
|
||||
compressed_state_format = True
|
||||
|
||||
history_during_period: MutableMapping[
|
||||
str, list[State | dict[str, Any]]
|
||||
] = await get_instance(hass).async_add_executor_job(
|
||||
history.get_significant_states,
|
||||
hass,
|
||||
start_time,
|
||||
end_time,
|
||||
entity_ids,
|
||||
hass.data[HISTORY_FILTERS],
|
||||
include_start_time_state,
|
||||
significant_changes_only,
|
||||
minimal_response,
|
||||
no_attributes,
|
||||
compressed_state_format,
|
||||
connection.send_message(
|
||||
await get_instance(hass).async_add_executor_job(
|
||||
_ws_get_significant_states,
|
||||
hass,
|
||||
msg["id"],
|
||||
start_time,
|
||||
end_time,
|
||||
entity_ids,
|
||||
hass.data[HISTORY_FILTERS],
|
||||
include_start_time_state,
|
||||
significant_changes_only,
|
||||
minimal_response,
|
||||
no_attributes,
|
||||
)
|
||||
)
|
||||
connection.send_result(msg["id"], history_during_period)
|
||||
|
||||
|
||||
class HistoryPeriodView(HomeAssistantView):
|
||||
|
|
|
@ -30,6 +30,8 @@ from homeassistant.components.recorder.models import (
|
|||
from homeassistant.components.recorder.util import session_scope
|
||||
from homeassistant.components.script import EVENT_SCRIPT_STARTED
|
||||
from homeassistant.components.sensor import ATTR_STATE_CLASS, DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.components.websocket_api import messages
|
||||
from homeassistant.components.websocket_api.const import JSON_DUMP
|
||||
from homeassistant.const import (
|
||||
ATTR_DOMAIN,
|
||||
ATTR_ENTITY_ID,
|
||||
|
@ -210,6 +212,34 @@ async def _process_logbook_platform(
|
|||
platform.async_describe_events(hass, _async_describe_event)
|
||||
|
||||
|
||||
def _ws_formatted_get_events(
|
||||
hass: HomeAssistant,
|
||||
msg_id: int,
|
||||
start_day: dt,
|
||||
end_day: dt,
|
||||
entity_ids: list[str] | None = None,
|
||||
filters: Filters | None = None,
|
||||
entities_filter: EntityFilter | Callable[[str], bool] | None = None,
|
||||
context_id: str | None = None,
|
||||
) -> str:
|
||||
"""Fetch events and convert them to json in the executor."""
|
||||
return JSON_DUMP(
|
||||
messages.result_message(
|
||||
msg_id,
|
||||
_get_events(
|
||||
hass,
|
||||
start_day,
|
||||
end_day,
|
||||
entity_ids,
|
||||
filters,
|
||||
entities_filter,
|
||||
context_id,
|
||||
True,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required("type"): "logbook/get_events",
|
||||
|
@ -249,20 +279,19 @@ async def ws_get_events(
|
|||
entity_ids = msg.get("entity_ids")
|
||||
context_id = msg.get("context_id")
|
||||
|
||||
logbook_events: list[dict[str, Any]] = await get_instance(
|
||||
hass
|
||||
).async_add_executor_job(
|
||||
_get_events,
|
||||
hass,
|
||||
start_time,
|
||||
end_time,
|
||||
entity_ids,
|
||||
hass.data[LOGBOOK_FILTERS],
|
||||
hass.data[LOGBOOK_ENTITIES_FILTER],
|
||||
context_id,
|
||||
True,
|
||||
connection.send_message(
|
||||
await get_instance(hass).async_add_executor_job(
|
||||
_ws_formatted_get_events,
|
||||
hass,
|
||||
msg["id"],
|
||||
start_time,
|
||||
end_time,
|
||||
entity_ids,
|
||||
hass.data[LOGBOOK_FILTERS],
|
||||
hass.data[LOGBOOK_ENTITIES_FILTER],
|
||||
context_id,
|
||||
)
|
||||
)
|
||||
connection.send_result(msg["id"], logbook_events)
|
||||
|
||||
|
||||
class LogbookView(HomeAssistantView):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue