Beispiel #1
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        image = None

        if self.device.capabilities.snapshot:
            try:
                image = await self.device.device.get_snapshot(
                    self.profile.token, self._basic_auth)
            except ONVIFError as err:
                LOGGER.error(
                    "Fetch snapshot image failed from %s, falling back to FFmpeg; %s",
                    self.device.name,
                    err,
                )

        if image is None:
            ffmpeg = ImageFrame(self.hass.data[DATA_FFMPEG].binary)
            image = await asyncio.shield(
                ffmpeg.get_image(
                    self._stream_uri,
                    output_format=IMAGE_JPEG,
                    extra_cmd=self.device.config_entry.options.get(
                        CONF_EXTRA_ARGUMENTS),
                ))

        return image
Beispiel #2
0
    async def async_camera_image(self):
        """Return a frame from the camera stream."""
        ffmpeg = ImageFrame(self._ffmpeg.binary, loop=self.hass.loop)

        image = await asyncio.shield(
            ffmpeg.get_image(self._rtsp_stream, output_format=IMAGE_JPEG))
        return image
Beispiel #3
0
 async def async_camera_image(self):
     ffmpeg = ImageFrame(self._ffmpeg.binary)
     streaming_url = self.getStreamSource()
     image = await asyncio.shield(
         ffmpeg.get_image(streaming_url, output_format=IMAGE_JPEG,)
     )
     return image
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        from haffmpeg.tools import ImageFrame, IMAGE_JPEG
        ffmpeg = ImageFrame(self._manager.binary, loop=self.hass.loop)

        image = await asyncio.shield(ffmpeg.get_image(
            self._input, output_format=IMAGE_JPEG,
            extra_cmd=self._extra_arguments), loop=self.hass.loop)
        return image
Beispiel #5
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        from haffmpeg.tools import ImageFrame, IMAGE_JPEG
        ffmpeg = ImageFrame(self._manager.binary, loop=self.hass.loop)

        image = await asyncio.shield(ffmpeg.get_image(
            self._input, output_format=IMAGE_JPEG,
            extra_cmd=self._extra_arguments), loop=self.hass.loop)
        return image
Beispiel #6
0
 async def async_camera_image(self, width=None, height=None):
     ffmpeg = ImageFrame(self._ffmpeg.binary)
     streaming_url = self.getStreamSource()
     image = await asyncio.shield(
         ffmpeg.get_image(
             streaming_url,
             output_format=IMAGE_JPEG,
             extra_cmd=self._extra_arguments,
         ))
     return image
Beispiel #7
0
async def isRtspStreamWorking(hass, host, username, password):
    _ffmpeg = hass.data[DATA_FFMPEG]
    ffmpeg = ImageFrame(_ffmpeg.binary)
    username = urllib.parse.quote_plus(username)
    password = urllib.parse.quote_plus(password)
    streaming_url = f"rtsp://{username}:{password}@{host}:554/stream1"
    image = await asyncio.shield(
        ffmpeg.get_image(streaming_url, output_format=IMAGE_JPEG,)
    )
    return not image == b""
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        self.renew_live_stream_session()

        from haffmpeg.tools import ImageFrame, IMAGE_JPEG
        ffmpeg = ImageFrame(self._ffmpeg.binary, loop=self.hass.loop)
        image = await asyncio.shield(ffmpeg.get_image(
            self._live_stream_session.live_stream_url,
            output_format=IMAGE_JPEG,
            extra_cmd=self._ffmpeg_arguments), loop=self.hass.loop)
        return image
Beispiel #9
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""

        #self._hass.async_create_task(async_reader_job(self._named_pipe, self._reader))

        from haffmpeg.tools import ImageFrame, IMAGE_JPEG
        ffmpeg = ImageFrame(self._ffmpeg_manager.binary, loop=self.hass.loop)

        image = await asyncio.shield(
            ffmpeg.get_image(self._named_pipe, output_format=IMAGE_JPEG))
        return image
Beispiel #10
0
    async def async_camera_image(self):
        """Return a frame from the camera stream."""
        ffmpeg = ImageFrame(self._ffmpeg.binary)

        image = await asyncio.shield(
            ffmpeg.get_image(
                self._rtsp_stream,
                output_format=IMAGE_JPEG,
                extra_cmd=self._ffmpeg_arguments,
            ))
        return image
Beispiel #11
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        self.renew_live_stream_session()

        from haffmpeg.tools import ImageFrame, IMAGE_JPEG
        ffmpeg = ImageFrame(self._ffmpeg.binary, loop=self.hass.loop)
        image = await asyncio.shield(ffmpeg.get_image(
            self._live_stream_session.live_stream_url,
            output_format=IMAGE_JPEG,
            extra_cmd=self._ffmpeg_arguments))
        return image
Beispiel #12
0
 async def async_camera_image(self):
     url = await self.stream_source()
     if url:
         ffmpeg = ImageFrame(self._manager.binary)
         self._last_image = await asyncio.shield(
             ffmpeg.get_image(
                 url,
                 output_format=IMAGE_JPEG,
                 extra_cmd=self._extra_arguments,
                 timeout=60,
             ))
     return self._last_image
Beispiel #13
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        await self.hass.async_add_executor_job(self.renew_live_stream_session)

        ffmpeg = ImageFrame(self._ffmpeg.binary, loop=self.hass.loop)
        image = await asyncio.shield(
            ffmpeg.get_image(
                self._live_stream_session.live_stream_url,
                output_format=IMAGE_JPEG,
                extra_cmd=self._ffmpeg_arguments,
            ))
        return image
Beispiel #14
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        from haffmpeg.tools import ImageFrame, IMAGE_JPEG

        _LOGGER.debug("Retrieving image from camera '%s'", self._name)

        ffmpeg = ImageFrame(
            self.hass.data[DATA_FFMPEG].binary, loop=self.hass.loop)

        image = await asyncio.shield(ffmpeg.get_image(
            self._input, output_format=IMAGE_JPEG,
            extra_cmd=self._ffmpeg_arguments), loop=self.hass.loop)
        return image
Beispiel #15
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        url = await self._get_latest_video_url()
        if url and url != self._last_url:
            ffmpeg = ImageFrame(self._manager.binary)
            self._last_image = await asyncio.shield(
                ffmpeg.get_image(
                    url, output_format=IMAGE_JPEG, extra_cmd=self._extra_arguments
                ),
            )
            self._last_url = url

        return self._last_image
Beispiel #16
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        from haffmpeg.tools import ImageFrame, IMAGE_JPEG

        url = await self.hass.async_add_job(self.get_latest_video_url)
        if url != self._last_url:
            ffmpeg = ImageFrame(self._manager.binary, loop=self.hass.loop)
            self._last_image = await asyncio.shield(ffmpeg.get_image(
                url, output_format=IMAGE_JPEG,
                extra_cmd=self._extra_arguments), loop=self.hass.loop)
            self._last_url = url

        return self._last_image
Beispiel #17
0
def cli(ffmpeg, source, format_img, output, extra):
    """FFMPEG capture frame as image."""
    loop = asyncio.get_event_loop()

    stream = ImageFrame(ffmpeg_bin=ffmpeg, loop=loop)
    future = asyncio.ensure_future(
        stream.get_image(input_source=source, output_format=format_img, extra_cmd=extra)
    )
    image = loop.run_until_complete(future)

    if image is not None:
        with open(output, "wb") as fh_img:
            fh_img.write(image)
Beispiel #18
0
async def async_get_image(
    hass: HomeAssistant,
    input_source: str,
    output_format: str = IMAGE_JPEG,
    extra_cmd: str | None = None,
) -> bytes | None:
    """Get an image from a frame of an RTSP stream."""
    manager = hass.data[DATA_FFMPEG]
    ffmpeg = ImageFrame(manager.binary)
    image = await asyncio.shield(
        ffmpeg.get_image(input_source, output_format=output_format, extra_cmd=extra_cmd)
    )
    return image
Beispiel #19
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""

        _LOGGER.debug("Retrieving image from camera '%s'", self._name)

        ffmpeg = ImageFrame(self.hass.data[DATA_FFMPEG].binary, loop=self.hass.loop)

        image = await asyncio.shield(
            ffmpeg.get_image(
                self._input, output_format=IMAGE_JPEG, extra_cmd=self._ffmpeg_arguments
            )
        )
        return image
Beispiel #20
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        ffmpeg = ImageFrame(self._ffmpeg.binary)

        if self._video_url is None:
            return

        image = await asyncio.shield(
            ffmpeg.get_image(
                self._video_url,
                output_format=IMAGE_JPEG,
            ))
        return image
Beispiel #21
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        from haffmpeg.tools import ImageFrame, IMAGE_JPEG
        ffmpeg = ImageFrame(self._ffmpeg.binary, loop=self.hass.loop)

        if self._video_url is None:
            return

        image = await asyncio.shield(
            ffmpeg.get_image(self._video_url,
                             output_format=IMAGE_JPEG,
                             extra_cmd=self._ffmpeg_arguments))
        return image
Beispiel #22
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        from haffmpeg.tools import ImageFrame, IMAGE_JPEG

        url = await self.hass.async_add_job(self.get_latest_video_url)
        if url != self._last_url:
            ffmpeg = ImageFrame(self._manager.binary, loop=self.hass.loop)
            self._last_image = await asyncio.shield(
                ffmpeg.get_image(url,
                                 output_format=IMAGE_JPEG,
                                 extra_cmd=self._extra_arguments))
            self._last_url = url

        return self._last_image
Beispiel #23
0
async def async_get_image(
    opp: OpenPeerPower,
    input_source: str,
    output_format: str = IMAGE_JPEG,
    extra_cmd: str | None = None,
):
    """Get an image from a frame of an RTSP stream."""
    manager = opp.data[DATA_FFMPEG]
    ffmpeg = ImageFrame(manager.binary)
    image = await asyncio.shield(
        ffmpeg.get_image(input_source,
                         output_format=output_format,
                         extra_cmd=extra_cmd))
    return image
Beispiel #24
0
def cli(ffmpeg, source, format_img, output, extra):
    """FFMPEG capture frame as image."""
    loop = asyncio.get_event_loop()

    stream = ImageFrame(ffmpeg_bin=ffmpeg, loop=loop)
    future = asyncio.ensure_future(
        stream.get_image(input_source=source,
                         output_format=format_img,
                         extra_cmd=extra))
    image = loop.run_until_complete(future)

    if image is not None:
        with open(output, "wb") as fh_img:
            fh_img.write(image)
Beispiel #25
0
    async def async_camera_image(self) -> bytes | None:
        """Return a still image response from the camera."""
        await self.opp.async_add_executor_job(self.renew_live_stream_session)
        live_stream_url = await self.opp.async_add_executor_job(
            getattr, self._live_stream_session, "live_stream_url")

        ffmpeg = ImageFrame(self._ffmpeg.binary)
        image: bytes | None = await asyncio.shield(
            ffmpeg.get_image(
                live_stream_url,
                output_format=IMAGE_JPEG,
                extra_cmd=self._ffmpeg_arguments,
            ))
        return image
Beispiel #26
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        from haffmpeg.tools import ImageFrame, IMAGE_JPEG

        if not self._input:
            await self.hass.async_add_executor_job(self.obtain_input_uri)
            if not self._input:
                return None

        ffmpeg = ImageFrame(
            self.hass.data[DATA_FFMPEG].binary, loop=self.hass.loop)

        image = await asyncio.shield(ffmpeg.get_image(
            self._input, output_format=IMAGE_JPEG,
            extra_cmd=self._ffmpeg_arguments), loop=self.hass.loop)
        return image
Beispiel #27
0
    async def async_camera_image(self):
        """Return bytes of camera image."""
        _LOGGER.debug("Handling image from camera %s", self.device.name)
        stream_uri = await self.stream_source()

        ffmpeg = ImageFrame(self.hass.data[DATA_FFMPEG].binary,
                            loop=self.hass.loop)
        image = await asyncio.shield(
            ffmpeg.get_image(
                stream_uri,
                output_format=IMAGE_JPEG,
                extra_cmd=self.device.config_entry.options.get(
                    CONF_EXTRA_ARGUMENTS),
            ))

        return image
Beispiel #28
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        image = None

        if self.device.capabilities.snapshot:
            if self._snapshot_uri is None:
                self._snapshot_uri = await self.device.async_get_snapshot_uri(
                    self.profile)

            auth = None
            if self.device.username and self.device.password:
                auth = HTTPDigestAuth(self.device.username,
                                      self.device.password)

            def fetch():
                """Read image from a URL."""
                try:
                    response = requests.get(self._snapshot_uri,
                                            timeout=5,
                                            auth=auth)
                    if response.status_code < 300:
                        return response.content
                except requests.exceptions.RequestException as error:
                    LOGGER.error(
                        "Fetch snapshot image failed from %s, falling back to FFmpeg; %s",
                        self.device.name,
                        error,
                    )

                return None

            image = await self.hass.async_add_executor_job(fetch)

        if image is None:
            ffmpeg = ImageFrame(self.hass.data[DATA_FFMPEG].binary,
                                loop=self.hass.loop)
            image = await asyncio.shield(
                ffmpeg.get_image(
                    self._stream_uri,
                    output_format=IMAGE_JPEG,
                    extra_cmd=self.device.config_entry.options.get(
                        CONF_EXTRA_ARGUMENTS),
                ))

        return image
Beispiel #29
0
    async def async_camera_image(self,
                                 width: int | None = None,
                                 height: int | None = None) -> bytes | None:
        """Return a still image response from the camera."""
        """Ignore width and height when the image is fetched from url."""
        """Camera component will resize it."""
        image = None

        if self._still_image_url:
            auth = None
            if self._user or self._password:
                auth = HTTPBasicAuth(self._user, self._password)

            def fetch():
                """Read image from a URL."""
                try:
                    response = requests.get(self._still_image_url,
                                            timeout=HTTP_TIMEOUT,
                                            auth=auth)
                    if response.status_code < 300:
                        return response.content
                except requests.exceptions.RequestException as error:
                    _LOGGER.error(
                        "Fetch snapshot image failed from %s, falling back to FFmpeg; %s",
                        self._name,
                        error,
                    )

                return None

            image = await self.hass.async_add_executor_job(fetch)

        if image is None:
            stream_source = await self.stream_source()
            if stream_source:
                ffmpeg = ImageFrame(self.hass.data[DATA_FFMPEG].binary)
                image = await asyncio.shield(
                    ffmpeg.get_image(stream_source,
                                     output_format=IMAGE_JPEG,
                                     extra_cmd=self._extra_arguments,
                                     width=width,
                                     height=height))

        return image
Beispiel #30
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""
        _LOGGER.debug("Retrieving image from camera '%s'", self._name)
        image = None

        if self._snapshot is not None:
            auth = None
            if self._username and self._password:
                auth = HTTPDigestAuth(self._username, self._password)

            def fetch():
                """Read image from a URL."""
                try:
                    response = requests.get(self._snapshot,
                                            timeout=5,
                                            auth=auth)
                    if response.status_code < 300:
                        return response.content
                except requests.exceptions.RequestException as error:
                    _LOGGER.error(
                        "Fetch snapshot image failed from %s, falling back to FFmpeg; %s",
                        self._name,
                        error,
                    )

                return None

            image = await self.hass.async_add_job(fetch)

        if image is None:
            # Don't keep trying the snapshot URL
            self._snapshot = None

            ffmpeg = ImageFrame(self.hass.data[DATA_FFMPEG].binary,
                                loop=self.hass.loop)
            image = await asyncio.shield(
                ffmpeg.get_image(
                    self._input,
                    output_format=IMAGE_JPEG,
                    extra_cmd=self._ffmpeg_arguments,
                ))

        return image
Beispiel #31
0
    async def async_camera_image(self):
        """Return a still image response from the camera."""

        try:
            host = self.host.async_render()
        except TemplateError as exc:
            _LOGGER.error("Error parsing template %s: %s", self.host, exc)
            return self._last_image

        url = await self.hass.async_add_executor_job(self.get_latest_video_url,
                                                     host)
        if url != self._last_url:
            ffmpeg = ImageFrame(self._manager.binary, loop=self.hass.loop)
            self._last_image = await asyncio.shield(
                ffmpeg.get_image(url,
                                 output_format=IMAGE_JPEG,
                                 extra_cmd=self._extra_arguments))
            self._last_url = url

        return self._last_image
async def async_get_image(
    hass: HomeAssistant,
    input_source: str,
    output_format: str = IMAGE_JPEG,
    extra_cmd: str | None = None,
    width: int | None = None,
    height: int | None = None,
) -> bytes | None:
    """Get an image from a frame of an RTSP stream."""
    manager = hass.data[DATA_FFMPEG]
    ffmpeg = ImageFrame(manager.binary)

    if width and height and (extra_cmd is None or "-s" not in extra_cmd):
        size_cmd = f"-s {width}x{height}"
        if extra_cmd is None:
            extra_cmd = size_cmd
        else:
            extra_cmd += " " + size_cmd

    image = await asyncio.shield(
        ffmpeg.get_image(input_source, output_format=output_format, extra_cmd=extra_cmd)
    )
    return image
class EufySecurityCam(Camera):
    """Define a Eufy Security camera/doorbell."""
    def __init__(self, hass, camera):
        """Initialize."""
        super().__init__()

        self._async_unsub_dispatcher_connect = None
        self._camera = camera
        self._ffmpeg = hass.data[DATA_FFMPEG]
        self._ffmpeg_arguments = DEFAULT_FFMPEG_ARGUMENTS
        self._ffmpeg_image_frame = ImageFrame(self._ffmpeg.binary,
                                              loop=hass.loop)
        self._ffmpeg_stream = CameraMjpeg(self._ffmpeg.binary, loop=hass.loop)
        self._last_image = None
        self._last_image_url = None
        self._stream_url = None

    @property
    def brand(self):
        """Return the camera brand."""
        return "Eufy Security"

    @property
    def device_state_attributes(self):
        """Return the state attributes."""
        attributes = {
            ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION,
            ATTR_HARDWARE_VERSION: self._camera.hardware_version,
            ATTR_SERIAL: self._camera.serial,
            ATTR_SOFTWARE_VERSION: self._camera.software_version,
        }
        for k, v in self._camera.params.items():
            if isinstance(k, Enum):
                attributes[k.name.lower()] = v
            else:
                attributes[str(k)] = v
        return attributes

    @property
    def model(self):
        """Return the name of this camera."""
        return self._camera.model

    @property
    def name(self):
        """Return the name of this camera."""
        return self._camera.name

    @property
    def should_poll(self):
        """Return False, updates are controlled via the hub."""
        return False

    @property
    def supported_features(self):
        """Return supported features."""
        return SUPPORT_ON_OFF | SUPPORT_STREAM

    @property
    def unique_id(self):
        """Return a unique ID."""
        return self._camera.serial

    async def async_camera_image(self):
        """Return a still image response from the camera."""
        if self._last_image_url != self._camera.last_camera_image_url:
            self._last_image = await asyncio.shield(
                self._ffmpeg_image_frame.get_image(
                    self._camera.last_camera_image_url,
                    output_format=IMAGE_JPEG,
                    extra_cmd=self._ffmpeg_arguments,
                ))
            self._last_image_url = self._camera.last_camera_image_url

        return self._last_image

    async def async_disable_motion_detection(self):
        """Disable doorbell's motion detection"""
        await self._camera.async_stop_detection()

    async def async_enable_motion_detection(self):
        """Enable doorbell's motion detection"""
        await self._camera.async_start_detection()

    async def async_turn_off(self):
        """Turn off the RTSP stream."""
        try:
            await self._camera.async_stop_stream()
            _LOGGER.info("Stream stopped for %s", self._camera.name)
        except EufySecurityError as err:
            _LOGGER.error("Unable to stop stream (%s): %s", self._camera.name,
                          err)

        self._stream_url = None

    async def async_turn_on(self):
        """Turn on the RTSP stream."""
        try:
            self._stream_url = await self._camera.async_start_stream()
            _LOGGER.info("Stream started (%s): %s", self._camera.name,
                         self._stream_url)
        except EufySecurityError as err:
            _LOGGER.error("Unable to start stream (%s): %s", self._camera.name,
                          err)

    async def handle_async_mjpeg_stream(self, request):
        """Generate an HTTP MJPEG stream from the camera."""
        if not self._stream_url:
            return await self.async_camera_image()

        await self._ffmpeg_stream.open_camera(self._stream_url,
                                              extra_cmd=self._ffmpeg_arguments)

        try:
            stream_reader = await self._ffmpeg_stream.get_reader()
            return await async_aiohttp_proxy_stream(
                self.hass,
                request,
                stream_reader,
                self._ffmpeg.ffmpeg_stream_content_type,
            )
        finally:
            await self._ffmpeg_stream.close()
Beispiel #34
0
class WyzeCamera(Camera):
    """Define a Wyze Camera."""
    def __init__(self, hass, camera):
        """Initialize."""
        super().__init__()

        self._camera = camera
        self._name = camera._friendly_name
        self._state = camera._state
        self._ssid = camera._ssid
        self._local_ip = camera._ip
        self._ssid = camera._ssid
        self._device_mac = camera._device_mac
        self._device_model = camera._device_model
        self._username = "******"
        self._password = "******"
        self.is_streaming = False
        self._ffmpeg = hass.data[DATA_FFMPEG]
        self._ffmpeg_arguments = DEFAULT_FFMPEG_ARGUMENTS
        self._ffmpeg_arguments_image = DEFAULT_FFMPEG_ARGUMENTS_IMAGE
        self._ffmpeg_image_frame = ImageFrame(self._ffmpeg.binary,
                                              loop=hass.loop)
        self._ffmpeg_stream = CameraMjpeg(self._ffmpeg.binary, loop=hass.loop)
        self._last_image = None
        self._last_image_url = None
        self._local_rtsp_port = camera._local_rtsp_port
        self._stream_url = f"rtsp://{self._username}:{self._password}@{self._local_ip}:{self._local_rtsp_port}/live"
        self.access_tokens = self.update_tokens()

    def update_tokens(self):
        """Update the used token."""
        token = hashlib.sha256(_RND.getrandbits(256).to_bytes(
            32, "little")).hexdigest()
        return token

    @property
    def brand(self):
        """Return the camera brand."""
        return "Wyze"

    @property
    def device_state_attributes(self):
        """Return the state attributes."""
        attributes = {
            ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION,
            ATTR_HARDWARE_VERSION: self._device_model,
            ATTR_SERIAL: self._device_mac,
            ATTR_SOFTWARE_VERSION: "1.0.0",
            "access_token": self.access_tokens,
        }
        return attributes

    @property
    def model(self):
        """Return the name of this camera."""
        return self._device_model

    @property
    def name(self):
        """Return the name of this camera."""
        return self._name

    @property
    def should_poll(self):
        """Return False, updates are controlled via the hub."""
        return False

    @property
    def supported_features(self):
        """Return supported features."""
        return SUPPORT_ON_OFF | SUPPORT_STREAM

    @property
    def unique_id(self):
        """Return a unique ID."""
        return self._device_mac

    async def async_camera_image(self):
        """Return a frame from the camera stream."""
        self._last_image = await asyncio.shield(
            self._ffmpeg_image_frame.get_image(
                self._stream_url,
                output_format=IMAGE_JPEG,
                extra_cmd=self._ffmpeg_arguments_image,
            ))
        _LOGGER.debug("Camera %s source image: %s", self._device_mac,
                      self._stream_url)
        return self._last_image

    async def async_disable_motion_detection(self):
        """Disable doorbell's motion detection"""

    async def async_enable_motion_detection(self):
        """Enable doorbell's motion detection"""

    async def async_turn_off(self):
        await self._camera.async_turn_off()

    async def async_turn_on(self):
        """Turn on the RTSP stream."""
        await self._camera.async_turn_on()

    async def stream_source(self):
        """Return the stream source."""
        if self._local_rtsp_port:
            rtsp_stream_source = (
                f"rtsp://{self._username}:{self._password}@"
                f"{self._local_ip}:{self._local_rtsp_port}/live")
            _LOGGER.debug("Camera %s source stream: %s", self._device_mac,
                          rtsp_stream_source)
            self._rtsp_stream = rtsp_stream_source
            self.is_streaming = True
            return rtsp_stream_source
        return None

    async def handle_async_mjpeg_stream(self, request):
        """Generate an HTTP MJPEG stream from the camera."""
        #if not self._stream_url:
        #return await self.async_camera_image()

        await self._ffmpeg_stream.open_camera(self._stream_url,
                                              extra_cmd=self._ffmpeg_arguments)

        try:
            stream_reader = await self._ffmpeg_stream.get_reader()
            _LOGGER.debug("Camera %s mjpg stream: %s", self._device_mac,
                          rtsp_stream_source)
            return await async_aiohttp_proxy_stream(
                self.hass,
                request,
                stream_reader,
                self._ffmpeg.ffmpeg_stream_content_type,
            )
        finally:
            await self._ffmpeg_stream.close()
Beispiel #35
0
class EufySecurityCam(DeviceEntity, Camera):
    """Define a Eufy Security camera/doorbell."""

    def __init__(self, ffmpeg, device, coordinator):
        """Initialize."""
        super().__init__(device, coordinator)
        Camera.__init__(self)

        self._async_unsub_dispatcher_connect = None
        self._ffmpeg = ffmpeg
        self._ffmpeg_arguments = DEFAULT_FFMPEG_ARGUMENTS
        self._ffmpeg_image_frame = ImageFrame(ffmpeg.binary)
        self._ffmpeg_stream = CameraMjpeg(ffmpeg.binary)
        self._last_image = None
        self._last_image_url = None
        self._stream_url = None

    @property
    def supported_features(self):
        """Return supported features."""
        return SUPPORT_ON_OFF | SUPPORT_STREAM

    @property
    def motion_detection_enabled(self):
        """Return the camera motion detection status."""
        return self._device.params['CAMERA_PIR']

    async def async_camera_image(self):
        """Return a still image response from the camera."""
        if self._last_image_url != self._device.last_camera_image_url:
            self._last_image = await asyncio.shield(
                self._ffmpeg_image_frame.get_image(
                    self._device.last_camera_image_url,
                    output_format=IMAGE_JPEG,
                    extra_cmd=self._ffmpeg_arguments,
                )
            )
            self._last_image_url = self._device.last_camera_image_url

        return self._last_image

    async def async_disable_motion_detection(self):
        """Disable doorbell's motion detection"""
        await self._device.async_update_param('DETECT_SWITCH', False)

    async def async_enable_motion_detection(self):
        """Enable doorbell's motion detection"""
        await self._device.async_update_param('DETECT_SWITCH', True)

    async def async_turn_off(self):
        """Turn off the RTSP stream."""
        try:
            await self._device.async_stop_stream()
            _LOGGER.info("Stream stopped for %s", self._device.name)
        except EufySecurityError as err:
            _LOGGER.error("Unable to stop stream (%s): %s", self._device.name, err)

        self._stream_url = None

    async def async_turn_on(self):
        """Turn on the RTSP stream."""
        try:
            self._stream_url = await self._device.async_start_stream()
            _LOGGER.info("Stream started (%s): %s", self._device.name, self._stream_url)
        except EufySecurityError as err:
            _LOGGER.error("Unable to start stream (%s): %s", self._device.name, err)

    async def handle_async_mjpeg_stream(self, request):
        """Generate an HTTP MJPEG stream from the camera."""
        await self.async_turn_on()
        if not self._stream_url:
            return await self.async_camera_image()

        await self._ffmpeg_stream.open_camera(
            self._stream_url, extra_cmd=self._ffmpeg_arguments
        )

        try:
            stream_reader = await self._ffmpeg_stream.get_reader()
            return await async_aiohttp_proxy_stream(
                self.hass,
                request,
                stream_reader,
                self._ffmpeg.ffmpeg_stream_content_type,
            )
        finally:
            await self._ffmpeg_stream.close()

    async def stream_source(self):
        self._stream_url = await self._device.async_start_stream()
        return self._stream_url