Live Streams Component (#21473)
* initial commit of streams * refactor stream component * refactor so stream formats are not considered a platform * initial test and minor refactor * fix linting * update requirements * need av in tests as well * fix import in class def vs method * fix travis and docker builds * address code review comments * fix logger, add stream start/stop logs, listen to HASS stop * address additional code review comments * beef up tests * fix tests * fix lint * add stream_source to onvif camera * address pr comments * add keepalive to camera play_stream service * remove keepalive and move import * implement registry and have output provider remove itself from stream after idle, set libav log level to error
This commit is contained in:
parent
0a6ba14444
commit
7ccd0bba9a
18 changed files with 993 additions and 5 deletions
|
@ -1,12 +1,12 @@
|
|||
"""The tests for the camera component."""
|
||||
import asyncio
|
||||
import base64
|
||||
from unittest.mock import patch, mock_open
|
||||
from unittest.mock import patch, mock_open, PropertyMock
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.setup import setup_component, async_setup_component
|
||||
from homeassistant.const import ATTR_ENTITY_PICTURE
|
||||
from homeassistant.const import (ATTR_ENTITY_ID, ATTR_ENTITY_PICTURE)
|
||||
from homeassistant.components import camera, http
|
||||
from homeassistant.components.websocket_api.const import TYPE_RESULT
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
@ -16,6 +16,7 @@ from tests.common import (
|
|||
get_test_home_assistant, get_test_instance_port, assert_setup_component,
|
||||
mock_coro)
|
||||
from tests.components.camera import common
|
||||
from tests.components.stream.common import generate_h264_video
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -32,6 +33,14 @@ def mock_camera(hass):
|
|||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_stream(hass):
|
||||
"""Initialize a demo camera platform with streaming."""
|
||||
assert hass.loop.run_until_complete(async_setup_component(hass, 'stream', {
|
||||
'stream': {}
|
||||
}))
|
||||
|
||||
|
||||
class TestSetupCamera:
|
||||
"""Test class for setup camera."""
|
||||
|
||||
|
@ -156,3 +165,88 @@ async def test_webocket_camera_thumbnail(hass, hass_ws_client, mock_camera):
|
|||
assert msg['result']['content_type'] == 'image/jpeg'
|
||||
assert msg['result']['content'] == \
|
||||
base64.b64encode(b'Test').decode('utf-8')
|
||||
|
||||
|
||||
async def test_webocket_stream_no_source(hass, hass_ws_client,
|
||||
mock_camera, mock_stream):
|
||||
"""Test camera/stream websocket command."""
|
||||
await async_setup_component(hass, 'camera')
|
||||
|
||||
with patch('homeassistant.components.camera.request_stream',
|
||||
return_value='http://home.assistant/playlist.m3u8') \
|
||||
as mock_request_stream:
|
||||
# Request playlist through WebSocket
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json({
|
||||
'id': 6,
|
||||
'type': 'camera/stream',
|
||||
'entity_id': 'camera.demo_camera',
|
||||
})
|
||||
msg = await client.receive_json()
|
||||
|
||||
# Assert WebSocket response
|
||||
assert not mock_request_stream.called
|
||||
assert msg['id'] == 6
|
||||
assert msg['type'] == TYPE_RESULT
|
||||
assert not msg['success']
|
||||
|
||||
|
||||
async def test_webocket_camera_stream(hass, hass_ws_client, hass_client,
|
||||
mock_camera, mock_stream):
|
||||
"""Test camera/stream websocket command."""
|
||||
await async_setup_component(hass, 'camera')
|
||||
|
||||
with patch('homeassistant.components.camera.request_stream',
|
||||
return_value='http://home.assistant/playlist.m3u8'
|
||||
) as mock_request_stream, \
|
||||
patch('homeassistant.components.camera.demo.DemoCamera.stream_source',
|
||||
new_callable=PropertyMock) as mock_stream_source:
|
||||
mock_stream_source.return_value = generate_h264_video()
|
||||
# Request playlist through WebSocket
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json({
|
||||
'id': 6,
|
||||
'type': 'camera/stream',
|
||||
'entity_id': 'camera.demo_camera',
|
||||
})
|
||||
msg = await client.receive_json()
|
||||
|
||||
# Assert WebSocket response
|
||||
assert mock_request_stream.called
|
||||
assert msg['id'] == 6
|
||||
assert msg['type'] == TYPE_RESULT
|
||||
assert msg['success']
|
||||
assert msg['result']['url'][-13:] == 'playlist.m3u8'
|
||||
|
||||
|
||||
async def test_play_stream_service_no_source(hass, mock_camera, mock_stream):
|
||||
"""Test camera play_stream service."""
|
||||
data = {
|
||||
ATTR_ENTITY_ID: 'camera.demo_camera',
|
||||
camera.ATTR_MEDIA_PLAYER: 'media_player.test'
|
||||
}
|
||||
with patch('homeassistant.components.camera.request_stream'), \
|
||||
pytest.raises(HomeAssistantError):
|
||||
# Call service
|
||||
await hass.services.async_call(
|
||||
camera.DOMAIN, camera.SERVICE_PLAY_STREAM, data, blocking=True)
|
||||
|
||||
|
||||
async def test_handle_play_stream_service(hass, mock_camera, mock_stream):
|
||||
"""Test camera play_stream service."""
|
||||
await async_setup_component(hass, 'media_player')
|
||||
data = {
|
||||
ATTR_ENTITY_ID: 'camera.demo_camera',
|
||||
camera.ATTR_MEDIA_PLAYER: 'media_player.test'
|
||||
}
|
||||
with patch('homeassistant.components.camera.request_stream'
|
||||
) as mock_request_stream, \
|
||||
patch('homeassistant.components.camera.demo.DemoCamera.stream_source',
|
||||
new_callable=PropertyMock) as mock_stream_source:
|
||||
mock_stream_source.return_value = generate_h264_video()
|
||||
# Call service
|
||||
await hass.services.async_call(
|
||||
camera.DOMAIN, camera.SERVICE_PLAY_STREAM, data, blocking=True)
|
||||
# So long as we request the stream, the rest should be covered
|
||||
# by the play_media service tests.
|
||||
assert mock_request_stream.called
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue