1
mirror of https://github.com/home-assistant/core synced 2024-09-06 10:29:55 +02:00

Fix ONVIF camera snapshot with auth (#33241)

This commit is contained in:
Franck Nijhof 2020-03-25 13:32:28 +01:00 committed by GitHub
parent 2a3c94bad0
commit 1fa996ed68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,13 +5,13 @@ import logging
import os
from typing import Optional
from aiohttp import ClientError
from aiohttp.client_exceptions import ClientConnectionError, ServerDisconnectedError
import async_timeout
from haffmpeg.camera import CameraMjpeg
from haffmpeg.tools import IMAGE_JPEG, ImageFrame
import onvif
from onvif import ONVIFCamera, exceptions
import requests
from requests.auth import HTTPDigestAuth
import voluptuous as vol
from zeep.asyncio import AsyncTransport
from zeep.exceptions import Fault
@ -412,17 +412,12 @@ class ONVIFHassCamera(Camera):
req.ProfileToken = profiles[self._profile_index].token
snapshot_uri = await media_service.GetSnapshotUri(req)
uri_no_auth = snapshot_uri.Uri
uri_for_log = uri_no_auth.replace("http://", "http://<user>:<password>@", 1)
# Same authentication as rtsp
self._snapshot = uri_no_auth.replace(
"http://", f"http://{self._username}:{self._password}@", 1
)
self._snapshot = snapshot_uri.Uri
_LOGGER.debug(
"ONVIF Camera Using the following URL for %s snapshot: %s",
self._name,
uri_for_log,
self._snapshot,
)
except exceptions.ONVIFError as err:
_LOGGER.error("Couldn't setup camera '%s'. Error: %s", self._name, err)
@ -509,25 +504,33 @@ class ONVIFHassCamera(Camera):
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:
try:
websession = async_get_clientsession(self.hass)
with async_timeout.timeout(10):
response = await websession.get(self._snapshot)
image = await response.read()
except asyncio.TimeoutError:
_LOGGER.error("Timeout getting image from: %s", self._name)
image = None
except ClientError as err:
_LOGGER.error("Error getting new camera image: %s", err)
image = 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)
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,
)
image = await self.hass.async_add_job(fetch)
if image is None:
# Don't keep trying the snapshot URL
self._snapshot = None
if self._snapshot is None or image is None:
ffmpeg = ImageFrame(self.hass.data[DATA_FFMPEG].binary, loop=self.hass.loop)
image = await asyncio.shield(
ffmpeg.get_image(
self._input,