mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Adds update file_path service to local_file camera (#13976)
* WIP: Add update_file service to local_file camera * Add event on update * Update local_file.py * Update services.yaml * Fix indent * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update local_file.py * Update test_local_file.py * Update local_file.py * Adds file_path to device_state_attributes * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update test_local_file.py * Update local_file.py * Update test_local_file.py * fixed test_update_file_path * Update local_file.py * Update test_local_file.py * Update test_local_file.py * Update services.yaml * Update local_file.py * Update local_file.py * Update test_local_file.py * Update local_file.py
This commit is contained in:
parent
ff7b51259e
commit
3e18078700
@ -11,31 +11,44 @@ import os
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.components.camera import Camera, PLATFORM_SCHEMA
|
||||
from homeassistant.components.camera import (
|
||||
Camera, CAMERA_SERVICE_SCHEMA, DOMAIN, PLATFORM_SCHEMA)
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_FILE_PATH = 'file_path'
|
||||
|
||||
DEFAULT_NAME = 'Local File'
|
||||
SERVICE_UPDATE_FILE_PATH = 'local_file_update_file_path'
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_FILE_PATH): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string
|
||||
})
|
||||
|
||||
CAMERA_SERVICE_UPDATE_FILE_PATH = CAMERA_SERVICE_SCHEMA.extend({
|
||||
vol.Required(CONF_FILE_PATH): cv.string
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up the Camera that works with local files."""
|
||||
file_path = config[CONF_FILE_PATH]
|
||||
camera = LocalFile(config[CONF_NAME], file_path)
|
||||
|
||||
# check filepath given is readable
|
||||
if not os.access(file_path, os.R_OK):
|
||||
_LOGGER.warning("Could not read camera %s image from file: %s",
|
||||
config[CONF_NAME], file_path)
|
||||
def update_file_path_service(call):
|
||||
"""Update the file path."""
|
||||
file_path = call.data.get(CONF_FILE_PATH)
|
||||
camera.update_file_path(file_path)
|
||||
return True
|
||||
|
||||
add_devices([LocalFile(config[CONF_NAME], file_path)])
|
||||
hass.services.register(
|
||||
DOMAIN,
|
||||
SERVICE_UPDATE_FILE_PATH,
|
||||
update_file_path_service,
|
||||
schema=CAMERA_SERVICE_UPDATE_FILE_PATH)
|
||||
|
||||
add_devices([camera])
|
||||
|
||||
|
||||
class LocalFile(Camera):
|
||||
@ -46,6 +59,7 @@ class LocalFile(Camera):
|
||||
super().__init__()
|
||||
|
||||
self._name = name
|
||||
self.check_file_path_access(file_path)
|
||||
self._file_path = file_path
|
||||
# Set content type of local file
|
||||
content, _ = mimetypes.guess_type(file_path)
|
||||
@ -61,7 +75,26 @@ class LocalFile(Camera):
|
||||
_LOGGER.warning("Could not read camera %s image from file: %s",
|
||||
self._name, self._file_path)
|
||||
|
||||
def check_file_path_access(self, file_path):
|
||||
"""Check that filepath given is readable."""
|
||||
if not os.access(file_path, os.R_OK):
|
||||
_LOGGER.warning("Could not read camera %s image from file: %s",
|
||||
self._name, file_path)
|
||||
|
||||
def update_file_path(self, file_path):
|
||||
"""Update the file_path."""
|
||||
self.check_file_path_access(file_path)
|
||||
self._file_path = file_path
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of this camera."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the camera state attributes."""
|
||||
return {
|
||||
'file_path': self._file_path,
|
||||
}
|
||||
|
@ -24,6 +24,16 @@ snapshot:
|
||||
description: Template of a Filename. Variable is entity_id.
|
||||
example: '/tmp/snapshot_{{ entity_id }}'
|
||||
|
||||
local_file_update_file_path:
|
||||
description: Update the file_path for a local_file camera.
|
||||
fields:
|
||||
entity_id:
|
||||
description: Name(s) of entities to update.
|
||||
example: 'camera.local_file'
|
||||
file_path:
|
||||
description: Path to the new image file.
|
||||
example: '/images/newimage.jpg'
|
||||
|
||||
onvif_ptz:
|
||||
description: Pan/Tilt/Zoom service for ONVIF camera.
|
||||
fields:
|
||||
@ -39,4 +49,3 @@ onvif_ptz:
|
||||
zoom:
|
||||
description: "Zoom. Allowed values: ZOOM_IN, ZOOM_OUT"
|
||||
example: "ZOOM_IN"
|
||||
|
||||
|
@ -6,6 +6,9 @@ from unittest import mock
|
||||
# https://bugs.python.org/issue23004
|
||||
from mock_open import MockOpen
|
||||
|
||||
from homeassistant.components.camera import DOMAIN
|
||||
from homeassistant.components.camera.local_file import (
|
||||
SERVICE_UPDATE_FILE_PATH)
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import mock_registry
|
||||
@ -115,3 +118,37 @@ def test_camera_content_type(hass, aiohttp_client):
|
||||
assert resp_4.content_type == 'image/jpeg'
|
||||
body = yield from resp_4.text()
|
||||
assert body == image
|
||||
|
||||
|
||||
async def test_update_file_path(hass):
|
||||
"""Test update_file_path service."""
|
||||
# Setup platform
|
||||
|
||||
mock_registry(hass)
|
||||
|
||||
with mock.patch('os.path.isfile', mock.Mock(return_value=True)), \
|
||||
mock.patch('os.access', mock.Mock(return_value=True)):
|
||||
await async_setup_component(hass, 'camera', {
|
||||
'camera': {
|
||||
'platform': 'local_file',
|
||||
'file_path': 'mock/path.jpg'
|
||||
}
|
||||
})
|
||||
|
||||
# Fetch state and check motion detection attribute
|
||||
state = hass.states.get('camera.local_file')
|
||||
assert state.attributes.get('friendly_name') == 'Local File'
|
||||
assert state.attributes.get('file_path') == 'mock/path.jpg'
|
||||
|
||||
service_data = {
|
||||
"entity_id": 'camera.local_file',
|
||||
"file_path": 'new/path.jpg'
|
||||
}
|
||||
|
||||
await hass.services.async_call(DOMAIN,
|
||||
SERVICE_UPDATE_FILE_PATH,
|
||||
service_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get('camera.local_file')
|
||||
assert state.attributes.get('file_path') == 'new/path.jpg'
|
||||
|
Loading…
x
Reference in New Issue
Block a user