Convert stream source to method (#23905)
* Convert stream source to method * Use async withpull/24135/head
parent
8d22479d24
commit
1de0a0bbb9
|
@ -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)
|
||||
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue