Convert stream source to method (#23905)

* Convert stream source to method

* Use async with
pull/24135/head
Paulus Schoutsen 2019-05-23 09:45:30 -07:00 committed by GitHub
parent 8d22479d24
commit 1de0a0bbb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 50 additions and 39 deletions

View File

@ -203,8 +203,7 @@ class AmcrestCam(Camera):
"""Return the camera model."""
return self._model
@property
def stream_source(self):
async def stream_source(self):
"""Return the source of the stream."""
return self._api.rtsp_url(typeno=self._resolution)

View File

@ -58,8 +58,7 @@ class AxisCamera(AxisEntityBase, MjpegCamera):
"""Return supported features."""
return SUPPORT_STREAM
@property
def stream_source(self):
async def stream_source(self):
"""Return the stream source."""
return AXIS_STREAM.format(
self.device.config_entry.data[CONF_DEVICE][CONF_USERNAME],

View File

@ -107,11 +107,14 @@ async def async_request_stream(hass, entity_id, fmt):
camera = _get_camera_from_entity_id(hass, entity_id)
camera_prefs = hass.data[DATA_CAMERA_PREFS].get(entity_id)
if not camera.stream_source:
async with async_timeout.timeout(10):
source = await camera.stream_source()
if not source:
raise HomeAssistantError("{} does not support play stream service"
.format(camera.entity_id))
return request_stream(hass, camera.stream_source, fmt=fmt,
return request_stream(hass, source, fmt=fmt,
keepalive=camera_prefs.preload_stream)
@ -121,7 +124,7 @@ async def async_get_image(hass, entity_id, timeout=10):
camera = _get_camera_from_entity_id(hass, entity_id)
with suppress(asyncio.CancelledError, asyncio.TimeoutError):
with async_timeout.timeout(timeout):
async with async_timeout.timeout(timeout):
image = await camera.async_camera_image()
if image:
@ -221,8 +224,16 @@ async def async_setup(hass, config):
async def preload_stream(hass, _):
for camera in component.entities:
camera_prefs = prefs.get(camera.entity_id)
if camera.stream_source and camera_prefs.preload_stream:
request_stream(hass, camera.stream_source, keepalive=True)
if not camera_prefs.preload_stream:
continue
async with async_timeout.timeout(10):
source = await camera.stream_source()
if not source:
continue
request_stream(hass, source, keepalive=True)
async_when_setup(hass, DOMAIN_STREAM, preload_stream)
@ -328,8 +339,7 @@ class Camera(Entity):
"""Return the interval between frames of the mjpeg stream."""
return 0.5
@property
def stream_source(self):
async def stream_source(self):
"""Return the source of the stream."""
return None
@ -481,7 +491,7 @@ class CameraImageView(CameraView):
async def handle(self, request, camera):
"""Serve camera image."""
with suppress(asyncio.CancelledError, asyncio.TimeoutError):
with async_timeout.timeout(10):
async with async_timeout.timeout(10):
image = await camera.async_camera_image()
if image:
@ -547,18 +557,25 @@ async def ws_camera_stream(hass, connection, msg):
camera = _get_camera_from_entity_id(hass, entity_id)
camera_prefs = hass.data[DATA_CAMERA_PREFS].get(entity_id)
if not camera.stream_source:
async with async_timeout.timeout(10):
source = await camera.stream_source()
if not source:
raise HomeAssistantError("{} does not support play stream service"
.format(camera.entity_id))
fmt = msg['format']
url = request_stream(hass, camera.stream_source, fmt=fmt,
url = request_stream(hass, source, fmt=fmt,
keepalive=camera_prefs.preload_stream)
connection.send_result(msg['id'], {'url': url})
except HomeAssistantError as ex:
_LOGGER.error(ex)
_LOGGER.error("Error requesting stream: %s", ex)
connection.send_error(
msg['id'], 'start_stream_failed', str(ex))
except asyncio.TimeoutError:
_LOGGER.error("Timeout getting stream source")
connection.send_error(
msg['id'], 'start_stream_failed', "Timeout getting stream source")
@websocket_api.async_response
@ -622,7 +639,10 @@ async def async_handle_snapshot_service(camera, service):
async def async_handle_play_stream_service(camera, service_call):
"""Handle play stream services calls."""
if not camera.stream_source:
async with async_timeout.timeout(10):
source = await camera.stream_source()
if not source:
raise HomeAssistantError("{} does not support play stream service"
.format(camera.entity_id))
@ -631,7 +651,7 @@ async def async_handle_play_stream_service(camera, service_call):
fmt = service_call.data[ATTR_FORMAT]
entity_ids = service_call.data[ATTR_MEDIA_PLAYER]
url = request_stream(hass, camera.stream_source, fmt=fmt,
url = request_stream(hass, source, fmt=fmt,
keepalive=camera_prefs.preload_stream)
data = {
ATTR_ENTITY_ID: entity_ids,
@ -646,7 +666,10 @@ async def async_handle_play_stream_service(camera, service_call):
async def async_handle_record_service(camera, call):
"""Handle stream recording service calls."""
if not camera.stream_source:
async with async_timeout.timeout(10):
source = await camera.stream_source()
if not source:
raise HomeAssistantError("{} does not support record service"
.format(camera.entity_id))
@ -657,7 +680,7 @@ async def async_handle_record_service(camera, call):
variables={ATTR_ENTITY_ID: camera})
data = {
CONF_STREAM_SOURCE: camera.stream_source,
CONF_STREAM_SOURCE: source,
CONF_FILENAME: video_path,
CONF_DURATION: call.data[CONF_DURATION],
CONF_LOOKBACK: call.data[CONF_LOOKBACK],

View File

@ -57,8 +57,7 @@ class DoorBirdCamera(Camera):
self._last_update = datetime.datetime.min
super().__init__()
@property
def stream_source(self):
async def stream_source(self):
"""Return the stream source."""
return self._stream_url

View File

@ -47,8 +47,7 @@ class FFmpegCamera(Camera):
"""Return supported features."""
return SUPPORT_STREAM
@property
def stream_source(self):
async def stream_source(self):
"""Return the stream source."""
return self._input.split(' ')[-1]

View File

@ -77,8 +77,7 @@ class FoscamCam(Camera):
return SUPPORT_STREAM
return 0
@property
def stream_source(self):
async def stream_source(self):
"""Return the stream source."""
if self._rtsp_port:
return 'rtsp://{}:{}@{}:{}/videoMain'.format(

View File

@ -146,7 +146,6 @@ class GenericCamera(Camera):
"""Return the name of this device."""
return self._name
@property
def stream_source(self):
async def stream_source(self):
"""Return the source of the stream."""
return self._stream_source

View File

@ -123,8 +123,7 @@ class NetatmoCamera(Camera):
"""Return supported features."""
return SUPPORT_STREAM
@property
def stream_source(self):
async def stream_source(self):
"""Return the stream source."""
url = '{0}/live/files/{1}/index.m3u8'
if self._localurl:

View File

@ -339,8 +339,7 @@ class ONVIFHassCamera(Camera):
return SUPPORT_STREAM
return 0
@property
def stream_source(self):
async def stream_source(self):
"""Return the stream source."""
return self._input

View File

@ -209,8 +209,7 @@ async def test_websocket_camera_stream(hass, hass_ws_client,
return_value='http://home.assistant/playlist.m3u8'
) as mock_request_stream, \
patch('homeassistant.components.demo.camera.DemoCamera.stream_source',
new_callable=PropertyMock) as mock_stream_source:
mock_stream_source.return_value = io.BytesIO()
return_value=mock_coro('http://example.com')):
# Request playlist through WebSocket
client = await hass_ws_client(hass)
await client.send_json({
@ -289,8 +288,7 @@ async def test_handle_play_stream_service(hass, mock_camera, mock_stream):
with patch('homeassistant.components.camera.request_stream'
) as mock_request_stream, \
patch('homeassistant.components.demo.camera.DemoCamera.stream_source',
new_callable=PropertyMock) as mock_stream_source:
mock_stream_source.return_value = io.BytesIO()
return_value=mock_coro('http://example.com')):
# Call service
await hass.services.async_call(
camera.DOMAIN, camera.SERVICE_PLAY_STREAM, data, blocking=True)
@ -331,8 +329,7 @@ async def test_preload_stream(hass, mock_stream):
patch('homeassistant.components.camera.prefs.CameraPreferences.get',
return_value=demo_prefs), \
patch('homeassistant.components.demo.camera.DemoCamera.stream_source',
new_callable=PropertyMock) as mock_stream_source:
mock_stream_source.return_value = io.BytesIO()
return_value=mock_coro("http://example.com")):
await async_setup_component(hass, 'camera', {
DOMAIN: {
'platform': 'demo'
@ -364,12 +361,11 @@ async def test_record_service(hass, mock_camera, mock_stream):
}
with patch('homeassistant.components.demo.camera.DemoCamera.stream_source',
new_callable=PropertyMock) as mock_stream_source, \
return_value=mock_coro("http://example.com")), \
patch(
'homeassistant.components.stream.async_handle_record_service',
return_value=mock_coro()) as mock_record_service, \
patch.object(hass.config, 'is_allowed_path', return_value=True):
mock_stream_source.return_value = io.BytesIO()
# Call service
await hass.services.async_call(
camera.DOMAIN, camera.SERVICE_RECORD, data, blocking=True)