1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 12:59:34 +00:00

Mark camera unavailable when keepalive stream fails (#62294)

* Mark camera unavailable when keepalive stream fails

Add a listener in stream that notifies camera when the stream state has changed, and
use that to inform the camera `available` property. Update the property to be set
only from the main loop where it is read to reduce thread safety races.

Issue #54659

* Fix pylint import related errors

* Address lint naming errors

* Apply suggestions from code review

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
Allen Porter
2021-12-19 09:09:59 -08:00
committed by GitHub
parent 1ec8619687
commit 647febd7d8
4 changed files with 107 additions and 9 deletions

View File

@@ -16,7 +16,11 @@ from homeassistant.components.camera.const import (
from homeassistant.components.camera.prefs import CameraEntityPreferences
from homeassistant.components.websocket_api.const import TYPE_RESULT
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START
from homeassistant.const import (
ATTR_ENTITY_ID,
EVENT_HOMEASSISTANT_START,
STATE_UNAVAILABLE,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.setup import async_setup_component
@@ -633,3 +637,56 @@ async def test_websocket_web_rtc_offer_invalid_stream_type(
assert response["type"] == TYPE_RESULT
assert not response["success"]
assert response["error"]["code"] == "web_rtc_offer_failed"
async def test_state_streaming(hass, hass_ws_client, mock_camera):
"""Camera state."""
demo_camera = hass.states.get("camera.demo_camera")
assert demo_camera is not None
assert demo_camera.state == camera.STATE_STREAMING
async def test_stream_unavailable(hass, hass_ws_client, mock_camera, mock_stream):
"""Camera state."""
await async_setup_component(hass, "camera", {})
with patch(
"homeassistant.components.camera.Stream.endpoint_url",
return_value="http://home.assistant/playlist.m3u8",
), patch(
"homeassistant.components.demo.camera.DemoCamera.stream_source",
return_value="http://example.com",
), patch(
"homeassistant.components.camera.Stream.set_update_callback",
) as mock_update_callback:
# Request playlist through WebSocket. We just want to create the stream
# but don't care about the result.
client = await hass_ws_client(hass)
await client.send_json(
{"id": 10, "type": "camera/stream", "entity_id": "camera.demo_camera"}
)
await client.receive_json()
assert mock_update_callback.called
# Simluate the stream going unavailable
callback = mock_update_callback.call_args.args[0]
with patch(
"homeassistant.components.camera.Stream.available", new_callable=lambda: False
):
callback()
await hass.async_block_till_done()
demo_camera = hass.states.get("camera.demo_camera")
assert demo_camera is not None
assert demo_camera.state == STATE_UNAVAILABLE
# Simulate stream becomes available
with patch(
"homeassistant.components.camera.Stream.available", new_callable=lambda: True
):
callback()
await hass.async_block_till_done()
demo_camera = hass.states.get("camera.demo_camera")
assert demo_camera is not None
assert demo_camera.state == camera.STATE_STREAMING