Allow get_states to recover (#67146)
parent
79bdd71da7
commit
a42547c0e5
|
@ -34,6 +34,10 @@ from homeassistant.helpers.json import ExtendedJSONEncoder
|
||||||
from homeassistant.helpers.service import async_get_all_descriptions
|
from homeassistant.helpers.service import async_get_all_descriptions
|
||||||
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
||||||
from homeassistant.setup import DATA_SETUP_TIME, async_get_loaded_integrations
|
from homeassistant.setup import DATA_SETUP_TIME, async_get_loaded_integrations
|
||||||
|
from homeassistant.util.json import (
|
||||||
|
find_paths_unserializable_data,
|
||||||
|
format_unserializable_data,
|
||||||
|
)
|
||||||
|
|
||||||
from . import const, decorators, messages
|
from . import const, decorators, messages
|
||||||
from .connection import ActiveConnection
|
from .connection import ActiveConnection
|
||||||
|
@ -225,7 +229,35 @@ def handle_get_states(
|
||||||
if entity_perm(state.entity_id, "read")
|
if entity_perm(state.entity_id, "read")
|
||||||
]
|
]
|
||||||
|
|
||||||
connection.send_result(msg["id"], states)
|
# JSON serialize here so we can recover if it blows up due to the
|
||||||
|
# state machine containing unserializable data. This command is required
|
||||||
|
# to succeed for the UI to show.
|
||||||
|
response = messages.result_message(msg["id"], states)
|
||||||
|
try:
|
||||||
|
connection.send_message(const.JSON_DUMP(response))
|
||||||
|
return
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
connection.logger.error(
|
||||||
|
"Unable to serialize to JSON. Bad data found at %s",
|
||||||
|
format_unserializable_data(
|
||||||
|
find_paths_unserializable_data(response, dump=const.JSON_DUMP)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
del response
|
||||||
|
|
||||||
|
# If we can't serialize, we'll filter out unserializable states
|
||||||
|
serialized = []
|
||||||
|
for state in states:
|
||||||
|
try:
|
||||||
|
serialized.append(const.JSON_DUMP(state))
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
# Error is already logged above
|
||||||
|
pass
|
||||||
|
|
||||||
|
# We now have partially serialized states. Craft some JSON.
|
||||||
|
response2 = const.JSON_DUMP(messages.result_message(msg["id"], ["TO_REPLACE"]))
|
||||||
|
response2 = response2.replace('"TO_REPLACE"', ", ".join(serialized))
|
||||||
|
connection.send_message(response2)
|
||||||
|
|
||||||
|
|
||||||
@decorators.websocket_command({vol.Required("type"): "get_services"})
|
@decorators.websocket_command({vol.Required("type"): "get_services"})
|
||||||
|
|
|
@ -587,13 +587,20 @@ async def test_states_filters_visible(hass, hass_admin_user, websocket_client):
|
||||||
|
|
||||||
async def test_get_states_not_allows_nan(hass, websocket_client):
|
async def test_get_states_not_allows_nan(hass, websocket_client):
|
||||||
"""Test get_states command not allows NaN floats."""
|
"""Test get_states command not allows NaN floats."""
|
||||||
hass.states.async_set("greeting.hello", "world", {"hello": float("NaN")})
|
hass.states.async_set("greeting.hello", "world")
|
||||||
|
hass.states.async_set("greeting.bad", "data", {"hello": float("NaN")})
|
||||||
|
hass.states.async_set("greeting.bye", "universe")
|
||||||
|
|
||||||
await websocket_client.send_json({"id": 5, "type": "get_states"})
|
await websocket_client.send_json({"id": 5, "type": "get_states"})
|
||||||
|
|
||||||
msg = await websocket_client.receive_json()
|
msg = await websocket_client.receive_json()
|
||||||
assert not msg["success"]
|
assert msg["id"] == 5
|
||||||
assert msg["error"]["code"] == const.ERR_UNKNOWN_ERROR
|
assert msg["type"] == const.TYPE_RESULT
|
||||||
|
assert msg["success"]
|
||||||
|
assert msg["result"] == [
|
||||||
|
hass.states.get("greeting.hello").as_dict(),
|
||||||
|
hass.states.get("greeting.bye").as_dict(),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
async def test_subscribe_unsubscribe_events_whitelist(
|
async def test_subscribe_unsubscribe_events_whitelist(
|
||||||
|
|
|
@ -76,7 +76,8 @@ async def test_non_json_message(hass, websocket_client, caplog):
|
||||||
msg = await websocket_client.receive_json()
|
msg = await websocket_client.receive_json()
|
||||||
assert msg["id"] == 5
|
assert msg["id"] == 5
|
||||||
assert msg["type"] == const.TYPE_RESULT
|
assert msg["type"] == const.TYPE_RESULT
|
||||||
assert not msg["success"]
|
assert msg["success"]
|
||||||
|
assert msg["result"] == []
|
||||||
assert (
|
assert (
|
||||||
f"Unable to serialize to JSON. Bad data found at $.result[0](State: test_domain.entity).attributes.bad={bad_data}(<class 'object'>"
|
f"Unable to serialize to JSON. Bad data found at $.result[0](State: test_domain.entity).attributes.bad={bad_data}(<class 'object'>"
|
||||||
in caplog.text
|
in caplog.text
|
||||||
|
|
Loading…
Reference in New Issue