diff --git a/homeassistant/components/camera/__init__.py b/homeassistant/components/camera/__init__.py index c1f92965198..60f8979bb16 100644 --- a/homeassistant/components/camera/__init__.py +++ b/homeassistant/components/camera/__init__.py @@ -256,6 +256,11 @@ class Camera(Entity): """Return the camera model.""" return None + @property + def frame_interval(self): + """Return the interval between frames of the mjpeg stream.""" + return 0.5 + def camera_image(self): """Return bytes of camera image.""" raise NotImplementedError() @@ -272,10 +277,6 @@ class Camera(Entity): This method must be run in the event loop. """ - if interval < MIN_STREAM_INTERVAL: - raise ValueError("Stream interval must be be > {}" - .format(MIN_STREAM_INTERVAL)) - response = web.StreamResponse() response.content_type = ('multipart/x-mixed-replace; ' 'boundary=--frameboundary') @@ -325,8 +326,7 @@ class Camera(Entity): a direct stream from the camera. This method must be run in the event loop. """ - await self.handle_async_still_stream(request, - FALLBACK_STREAM_INTERVAL) + await self.handle_async_still_stream(request, self.frame_interval) @property def state(self): @@ -448,6 +448,9 @@ class CameraMjpegStream(CameraView): try: # Compose camera stream from stills interval = float(request.query.get('interval')) + if interval < MIN_STREAM_INTERVAL: + raise ValueError("Stream interval must be be > {}" + .format(MIN_STREAM_INTERVAL)) await camera.handle_async_still_stream(request, interval) return except ValueError: diff --git a/homeassistant/components/camera/generic.py b/homeassistant/components/camera/generic.py index 2f5d8d28979..e11bd599e45 100644 --- a/homeassistant/components/camera/generic.py +++ b/homeassistant/components/camera/generic.py @@ -28,6 +28,7 @@ _LOGGER = logging.getLogger(__name__) CONF_CONTENT_TYPE = 'content_type' CONF_LIMIT_REFETCH_TO_URL_CHANGE = 'limit_refetch_to_url_change' CONF_STILL_IMAGE_URL = 'still_image_url' +CONF_FRAMERATE = 'framerate' DEFAULT_NAME = 'Generic Camera' @@ -40,6 +41,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_PASSWORD): cv.string, vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_CONTENT_TYPE, default=DEFAULT_CONTENT_TYPE): cv.string, + vol.Optional(CONF_FRAMERATE, default=2): cv.positive_int, }) @@ -62,6 +64,7 @@ class GenericCamera(Camera): self._still_image_url = device_info[CONF_STILL_IMAGE_URL] self._still_image_url.hass = hass self._limit_refetch = device_info[CONF_LIMIT_REFETCH_TO_URL_CHANGE] + self._frame_interval = 1 / device_info[CONF_FRAMERATE] self.content_type = device_info[CONF_CONTENT_TYPE] username = device_info.get(CONF_USERNAME) @@ -78,6 +81,11 @@ class GenericCamera(Camera): self._last_url = None self._last_image = None + @property + def frame_interval(self): + """Return the interval between frames of the mjpeg stream.""" + return self._frame_interval + def camera_image(self): """Return bytes of camera image.""" return run_coroutine_threadsafe(