Speed up responding to states being polled via API (#99621)

* Speed up responding to states being polled via API

Switch to using `as_dict_json` to avoid serializing states over and over when the
states api is polled since the mobile app is already building the cache as it also
polls the states via the websocket_api

* Speed up responding to states being polled via API

Switch to using `as_dict_json` to avoid serializing states over and over when the
states api is polled since the mobile app is already building the cache as it also
polls the states via the websocket_api

* fix json

* cover
This commit is contained in:
J. Nick Koston 2023-09-04 15:51:19 -05:00 committed by GitHub
parent 47c20495bd
commit d2a52230ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 11 deletions

View File

@ -14,6 +14,7 @@ from homeassistant.auth.permissions.const import POLICY_READ
from homeassistant.bootstrap import DATA_LOGGING from homeassistant.bootstrap import DATA_LOGGING
from homeassistant.components.http import HomeAssistantView, require_admin from homeassistant.components.http import HomeAssistantView, require_admin
from homeassistant.const import ( from homeassistant.const import (
CONTENT_TYPE_JSON,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
MATCH_ALL, MATCH_ALL,
URL_API, URL_API,
@ -195,15 +196,19 @@ class APIStatesView(HomeAssistantView):
user: User = request["hass_user"] user: User = request["hass_user"]
hass: HomeAssistant = request.app["hass"] hass: HomeAssistant = request.app["hass"]
if user.is_admin: if user.is_admin:
return self.json([state.as_dict() for state in hass.states.async_all()]) states = (state.as_dict_json() for state in hass.states.async_all())
entity_perm = user.permissions.check_entity else:
return self.json( entity_perm = user.permissions.check_entity
[ states = (
state.as_dict() state.as_dict_json()
for state in hass.states.async_all() for state in hass.states.async_all()
if entity_perm(state.entity_id, "read") if entity_perm(state.entity_id, "read")
] )
response = web.Response(
body=f'[{",".join(states)}]', content_type=CONTENT_TYPE_JSON
) )
response.enable_compression()
return response
class APIEntityStateView(HomeAssistantView): class APIEntityStateView(HomeAssistantView):
@ -213,14 +218,18 @@ class APIEntityStateView(HomeAssistantView):
name = "api:entity-state" name = "api:entity-state"
@ha.callback @ha.callback
def get(self, request, entity_id): def get(self, request: web.Request, entity_id: str) -> web.Response:
"""Retrieve state of entity.""" """Retrieve state of entity."""
user = request["hass_user"] user: User = request["hass_user"]
hass: HomeAssistant = request.app["hass"]
if not user.permissions.check_entity(entity_id, POLICY_READ): if not user.permissions.check_entity(entity_id, POLICY_READ):
raise Unauthorized(entity_id=entity_id) raise Unauthorized(entity_id=entity_id)
if state := request.app["hass"].states.get(entity_id): if state := hass.states.get(entity_id):
return self.json(state) return web.Response(
body=state.as_dict_json(),
content_type=CONTENT_TYPE_JSON,
)
return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND) return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND)
async def post(self, request, entity_id): async def post(self, request, entity_id):

View File

@ -575,11 +575,13 @@ async def test_states(
) -> None: ) -> None:
"""Test fetching all states as admin.""" """Test fetching all states as admin."""
hass.states.async_set("test.entity", "hello") hass.states.async_set("test.entity", "hello")
hass.states.async_set("test.entity2", "hello")
resp = await mock_api_client.get(const.URL_API_STATES) resp = await mock_api_client.get(const.URL_API_STATES)
assert resp.status == HTTPStatus.OK assert resp.status == HTTPStatus.OK
json = await resp.json() json = await resp.json()
assert len(json) == 1 assert len(json) == 2
assert json[0]["entity_id"] == "test.entity" assert json[0]["entity_id"] == "test.entity"
assert json[1]["entity_id"] == "test.entity2"
async def test_states_view_filters( async def test_states_view_filters(