mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 14:57:09 +00:00
Use voluptuous for Raspberry Pi and local file camera (#2988)
* Migrate to voluptuous * Update const.py * Migrate to voluptuous * Remove duplicate _LOGGER entry
This commit is contained in:
parent
2accc15d41
commit
a4b90c9879
@ -1,5 +1,9 @@
|
|||||||
"""Camera that loads a picture from a local file."""
|
"""
|
||||||
|
Camera that loads a picture from a local file.
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/camera.local_file/
|
||||||
|
"""
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -9,7 +13,10 @@ from homeassistant.const import CONF_NAME
|
|||||||
from homeassistant.components.camera import Camera, PLATFORM_SCHEMA
|
from homeassistant.components.camera import Camera, PLATFORM_SCHEMA
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_FILE_PATH = 'file_path'
|
CONF_FILE_PATH = 'file_path'
|
||||||
|
|
||||||
DEFAULT_NAME = 'Local File'
|
DEFAULT_NAME = 'Local File'
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
@ -17,8 +24,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string
|
||||||
})
|
})
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Setup the Camera."""
|
"""Setup the Camera."""
|
||||||
|
@ -9,41 +9,77 @@ import subprocess
|
|||||||
import logging
|
import logging
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from homeassistant.components.camera import Camera
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.components.camera import (Camera, PLATFORM_SCHEMA)
|
||||||
|
from homeassistant.const import (CONF_NAME, CONF_FILE_PATH)
|
||||||
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
CONF_HORIZONTAL_FLIP = 'horizontal_flip'
|
||||||
|
CONF_IMAGE_HEIGHT = 'image_height'
|
||||||
|
CONF_IMAGE_QUALITY = 'image_quality'
|
||||||
|
CONF_IMAGE_ROTATION = 'image_rotation'
|
||||||
|
CONF_IMAGE_WIDTH = 'image_width'
|
||||||
|
CONF_TIMELAPSE = 'timelapse'
|
||||||
|
CONF_VERTICAL_FLIP = 'vertical_flip'
|
||||||
|
|
||||||
|
DEFAULT_HORIZONTAL_FLIP = 0
|
||||||
|
DEFAULT_IMAGE_HEIGHT = 480
|
||||||
|
DEFAULT_IMAGE_QUALITIY = 7
|
||||||
|
DEFAULT_IMAGE_ROTATION = 0
|
||||||
|
DEFAULT_IMAGE_WIDTH = 640
|
||||||
|
DEFAULT_NAME = 'Raspberry Pi Camera'
|
||||||
|
DEFAULT_TIMELAPSE = 1000
|
||||||
|
DEFAULT_VERTICAL_FLIP = 0
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_FILE_PATH): cv.isfile,
|
||||||
|
vol.Optional(CONF_HORIZONTAL_FLIP, default=DEFAULT_HORIZONTAL_FLIP):
|
||||||
|
vol.All(vol.Coerce(int), vol.Range(min=0, max=1)),
|
||||||
|
vol.Optional(CONF_IMAGE_HEIGHT, default=DEFAULT_HORIZONTAL_FLIP):
|
||||||
|
vol.Coerce(int),
|
||||||
|
vol.Optional(CONF_IMAGE_QUALITY, default=DEFAULT_IMAGE_QUALITIY):
|
||||||
|
vol.All(vol.Coerce(int), vol.Range(min=0, max=100)),
|
||||||
|
vol.Optional(CONF_IMAGE_ROTATION, default=DEFAULT_IMAGE_ROTATION):
|
||||||
|
vol.All(vol.Coerce(int), vol.Range(min=0, max=359)),
|
||||||
|
vol.Optional(CONF_IMAGE_WIDTH, default=DEFAULT_IMAGE_WIDTH):
|
||||||
|
vol.Coerce(int),
|
||||||
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
|
vol.Optional(CONF_TIMELAPSE, default=1000): vol.Coerce(int),
|
||||||
|
vol.Optional(CONF_VERTICAL_FLIP, default=DEFAULT_VERTICAL_FLIP):
|
||||||
|
vol.All(vol.Coerce(int), vol.Range(min=0, max=1)),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Setup the Raspberry Camera."""
|
"""Setup the Raspberry Camera."""
|
||||||
if shutil.which("raspistill") is None:
|
if shutil.which("raspistill") is None:
|
||||||
_LOGGER.error("Error: raspistill not found")
|
_LOGGER.error("'raspistill' was not found")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
setup_config = (
|
setup_config = (
|
||||||
{
|
{
|
||||||
"name": config.get("name", "Raspberry Pi Camera"),
|
CONF_NAME: config.get(CONF_NAME),
|
||||||
"image_width": int(config.get("image_width", "640")),
|
CONF_IMAGE_WIDTH: config.get(CONF_IMAGE_WIDTH),
|
||||||
"image_height": int(config.get("image_height", "480")),
|
CONF_IMAGE_HEIGHT: config.get(CONF_IMAGE_HEIGHT),
|
||||||
"image_quality": int(config.get("image_quality", "7")),
|
CONF_IMAGE_QUALITY: config.get(CONF_IMAGE_QUALITY),
|
||||||
"image_rotation": int(config.get("image_rotation", "0")),
|
CONF_IMAGE_ROTATION: config.get(CONF_IMAGE_ROTATION),
|
||||||
"timelapse": int(config.get("timelapse", "2000")),
|
CONF_TIMELAPSE: config.get(CONF_TIMELAPSE),
|
||||||
"horizontal_flip": int(config.get("horizontal_flip", "0")),
|
CONF_HORIZONTAL_FLIP: config.get(CONF_HORIZONTAL_FLIP),
|
||||||
"vertical_flip": int(config.get("vertical_flip", "0")),
|
CONF_VERTICAL_FLIP: config.get(CONF_VERTICAL_FLIP),
|
||||||
"file_path": config.get("file_path",
|
CONF_FILE_PATH: config.get(CONF_FILE_PATH,
|
||||||
os.path.join(os.path.dirname(__file__),
|
os.path.join(os.path.dirname(__file__),
|
||||||
'image.jpg'))
|
'image.jpg'))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# check filepath given is writable
|
if not os.access(setup_config[CONF_FILE_PATH], os.W_OK):
|
||||||
if not os.access(setup_config["file_path"], os.W_OK):
|
_LOGGER.error("File path is not writable")
|
||||||
_LOGGER.error("Error: file path is not writable")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
add_devices([
|
add_devices([RaspberryCamera(setup_config)])
|
||||||
RaspberryCamera(setup_config)
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
class RaspberryCamera(Camera):
|
class RaspberryCamera(Camera):
|
||||||
@ -53,26 +89,26 @@ class RaspberryCamera(Camera):
|
|||||||
"""Initialize Raspberry Pi camera component."""
|
"""Initialize Raspberry Pi camera component."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self._name = device_info["name"]
|
self._name = device_info[CONF_NAME]
|
||||||
self._config = device_info
|
self._config = device_info
|
||||||
|
|
||||||
# kill if there's raspistill instance
|
# Kill if there's raspistill instance
|
||||||
subprocess.Popen(['killall', 'raspistill'],
|
subprocess.Popen(['killall', 'raspistill'],
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
cmd_args = [
|
cmd_args = [
|
||||||
'raspistill', '--nopreview', '-o', str(device_info["file_path"]),
|
'raspistill', '--nopreview', '-o', device_info[CONF_FILE_PATH],
|
||||||
'-t', '0', '-w', str(device_info["image_width"]),
|
'-t', '0', '-w', str(device_info[CONF_IMAGE_WIDTH]),
|
||||||
'-h', str(device_info["image_height"]),
|
'-h', str(device_info[CONF_IMAGE_HEIGHT]),
|
||||||
'-tl', str(device_info["timelapse"]),
|
'-tl', str(device_info[CONF_TIMELAPSE]),
|
||||||
'-q', str(device_info["image_quality"]),
|
'-q', str(device_info[CONF_IMAGE_QUALITY]),
|
||||||
'-rot', str(device_info["image_rotation"])
|
'-rot', str(device_info[CONF_IMAGE_ROTATION])
|
||||||
]
|
]
|
||||||
if device_info["horizontal_flip"]:
|
if device_info[CONF_HORIZONTAL_FLIP]:
|
||||||
cmd_args.append("-hf")
|
cmd_args.append("-hf")
|
||||||
|
|
||||||
if device_info["vertical_flip"]:
|
if device_info[CONF_VERTICAL_FLIP]:
|
||||||
cmd_args.append("-vf")
|
cmd_args.append("-vf")
|
||||||
|
|
||||||
subprocess.Popen(cmd_args,
|
subprocess.Popen(cmd_args,
|
||||||
@ -81,7 +117,7 @@ class RaspberryCamera(Camera):
|
|||||||
|
|
||||||
def camera_image(self):
|
def camera_image(self):
|
||||||
"""Return raspstill image response."""
|
"""Return raspstill image response."""
|
||||||
with open(self._config["file_path"], 'rb') as file:
|
with open(self._config[CONF_FILE_PATH], 'rb') as file:
|
||||||
return file.read()
|
return file.read()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -37,6 +37,7 @@ CONF_ELEVATION = 'elevation'
|
|||||||
CONF_ENTITY_ID = 'entity_id'
|
CONF_ENTITY_ID = 'entity_id'
|
||||||
CONF_ENTITY_NAMESPACE = 'entity_namespace'
|
CONF_ENTITY_NAMESPACE = 'entity_namespace'
|
||||||
CONF_EVENT = 'event'
|
CONF_EVENT = 'event'
|
||||||
|
CONF_FILE_PATH = 'file_path'
|
||||||
CONF_FILENAME = 'filename'
|
CONF_FILENAME = 'filename'
|
||||||
CONF_HOST = 'host'
|
CONF_HOST = 'host'
|
||||||
CONF_HOSTS = 'hosts'
|
CONF_HOSTS = 'hosts'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user