Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 32 additions & 39 deletions homeassistant/components/camera/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,53 @@
Proxy camera platform that enables image processing of camera data.

For more details about this platform, please refer to the documentation
https://home-assistant.io/components/proxy
https://www.home-assistant.io/components/camera.proxy/
"""
import logging
import asyncio
import logging

import aiohttp
import async_timeout

import voluptuous as vol

from homeassistant.util.async_ import run_coroutine_threadsafe
from homeassistant.components.camera import PLATFORM_SCHEMA, Camera
from homeassistant.const import CONF_ENTITY_ID, CONF_NAME, HTTP_HEADER_HA_AUTH
from homeassistant.helpers import config_validation as cv

import homeassistant.util.dt as dt_util
from homeassistant.const import (
CONF_NAME, CONF_ENTITY_ID, HTTP_HEADER_HA_AUTH)
from homeassistant.components.camera import (
PLATFORM_SCHEMA, Camera)
from homeassistant.helpers.aiohttp_client import (
async_get_clientsession, async_aiohttp_proxy_web)
async_aiohttp_proxy_web, async_get_clientsession)
from homeassistant.util.async_ import run_coroutine_threadsafe
import homeassistant.util.dt as dt_util

REQUIREMENTS = ['pillow==5.0.0']
REQUIREMENTS = ['pillow==5.2.0']

_LOGGER = logging.getLogger(__name__)

CONF_MAX_IMAGE_WIDTH = "max_image_width"
CONF_IMAGE_QUALITY = "image_quality"
CONF_IMAGE_REFRESH_RATE = "image_refresh_rate"
CONF_FORCE_RESIZE = "force_resize"
CONF_MAX_STREAM_WIDTH = "max_stream_width"
CONF_STREAM_QUALITY = "stream_quality"
CONF_CACHE_IMAGES = "cache_images"
CONF_CACHE_IMAGES = 'cache_images'
CONF_FORCE_RESIZE = 'force_resize'
CONF_IMAGE_QUALITY = 'image_quality'
CONF_IMAGE_REFRESH_RATE = 'image_refresh_rate'
CONF_MAX_IMAGE_WIDTH = 'max_image_width'
CONF_MAX_STREAM_WIDTH = 'max_stream_width'
CONF_STREAM_QUALITY = 'stream_quality'

DEFAULT_BASENAME = "Camera Proxy"
DEFAULT_QUALITY = 75

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_MAX_IMAGE_WIDTH): int,
vol.Optional(CONF_CACHE_IMAGES, False): cv.boolean,
vol.Optional(CONF_FORCE_RESIZE, False): cv.boolean,
vol.Optional(CONF_IMAGE_QUALITY): int,
vol.Optional(CONF_IMAGE_REFRESH_RATE): float,
vol.Optional(CONF_FORCE_RESIZE, False): cv.boolean,
vol.Optional(CONF_CACHE_IMAGES, False): cv.boolean,
vol.Optional(CONF_MAX_IMAGE_WIDTH): int,
vol.Optional(CONF_MAX_STREAM_WIDTH): int,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_STREAM_QUALITY): int,
})


async def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
async def async_setup_platform(
hass, config, async_add_devices, discovery_info=None):
"""Set up the Proxy camera platform."""
async_add_devices([ProxyCamera(hass, config)])

Expand All @@ -77,7 +74,7 @@ def _resize_image(image, opts):
old_size = len(image)
if old_width <= new_width:
if opts.quality is None:
_LOGGER.debug("Image is smaller-than / equal-to requested width")
_LOGGER.debug("Image is smaller-than/equal-to requested width")
return image
new_width = old_width

Expand All @@ -86,19 +83,17 @@ def _resize_image(image, opts):

img = img.resize((new_width, new_height), Image.ANTIALIAS)
imgbuf = io.BytesIO()
img.save(imgbuf, "JPEG", optimize=True, quality=quality)
img.save(imgbuf, 'JPEG', optimize=True, quality=quality)
newimage = imgbuf.getvalue()
if not opts.force_resize and len(newimage) >= old_size:
_LOGGER.debug("Using original image(%d bytes) "
"because resized image (%d bytes) is not smaller",
old_size, len(newimage))
return image

_LOGGER.debug("Resized image "
"from (%dx%d - %d bytes) "
"to (%dx%d - %d bytes)",
old_width, old_height, old_size,
new_width, new_height, len(newimage))
_LOGGER.debug(
"Resized image from (%dx%d - %d bytes) to (%dx%d - %d bytes)",
old_width, old_height, old_size, new_width, new_height, len(newimage))
return newimage


Expand All @@ -112,7 +107,7 @@ def __init__(self, max_width, quality, force_resize):
self.force_resize = force_resize

def __bool__(self):
"""Bool evalution rules."""
"""Bool evaluation rules."""
return bool(self.max_width or self.quality)


Expand All @@ -133,8 +128,7 @@ def __init__(self, hass, config):
config.get(CONF_FORCE_RESIZE))

self._stream_opts = ImageOpts(
config.get(CONF_MAX_STREAM_WIDTH),
config.get(CONF_STREAM_QUALITY),
config.get(CONF_MAX_STREAM_WIDTH), config.get(CONF_STREAM_QUALITY),
True)

self._image_refresh_rate = config.get(CONF_IMAGE_REFRESH_RATE)
Expand All @@ -145,8 +139,7 @@ def __init__(self, hass, config):
self._last_image = None
self._headers = (
{HTTP_HEADER_HA_AUTH: self.hass.config.api.api_password}
if self.hass.config.api.api_password is not None
else None)
if self.hass.config.api.api_password is not None else None)

def camera_image(self):
"""Return camera image."""
Expand Down Expand Up @@ -195,8 +188,8 @@ async def handle_async_mjpeg_stream(self, request):
self.hass, request, stream_coro)

response = aiohttp.web.StreamResponse()
response.content_type = ('multipart/x-mixed-replace; '
'boundary=--frameboundary')
response.content_type = (
'multipart/x-mixed-replace; boundary=--frameboundary')
await response.prepare(request)

async def write(img_bytes):
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ piglow==1.2.4
pilight==0.1.1

# homeassistant.components.camera.proxy
pillow==5.0.0
pillow==5.2.0

# homeassistant.components.dominos
pizzapi==0.0.3
Expand Down