diff --git a/.coveragerc b/.coveragerc index 0f17fa04339..c1a9fa291fe 100644 --- a/.coveragerc +++ b/.coveragerc @@ -316,6 +316,7 @@ omit = homeassistant/components/camera/ring.py homeassistant/components/camera/rpi_camera.py homeassistant/components/camera/synology.py + homeassistant/components/camera/xeoma.py homeassistant/components/camera/yi.py homeassistant/components/climate/econet.py homeassistant/components/climate/ephember.py diff --git a/homeassistant/components/camera/xeoma.py b/homeassistant/components/camera/xeoma.py new file mode 100755 index 00000000000..72f40cb83a4 --- /dev/null +++ b/homeassistant/components/camera/xeoma.py @@ -0,0 +1,113 @@ +""" +Support for Xeoma Cameras. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/camera.xeoma/ +""" +import asyncio +import logging + +import voluptuous as vol + +from homeassistant.components.camera import PLATFORM_SCHEMA, Camera +from homeassistant.const import ( + CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME) +from homeassistant.helpers import config_validation as cv + +REQUIREMENTS = ['pyxeoma==1.2'] + +_LOGGER = logging.getLogger(__name__) + +CONF_CAMERAS = 'cameras' +CONF_HIDE = 'hide' +CONF_IMAGE_NAME = 'image_name' +CONF_NEW_VERSION = 'new_version' + +CAMERAS_SCHEMA = vol.Schema({ + vol.Required(CONF_IMAGE_NAME): cv.string, + vol.Optional(CONF_HIDE, default=False): cv.boolean, + vol.Optional(CONF_NAME): cv.string, +}, required=False) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_CAMERAS, default={}): + vol.Schema(vol.All(cv.ensure_list, [CAMERAS_SCHEMA])), + vol.Optional(CONF_NEW_VERSION, default=True): cv.boolean, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_USERNAME): cv.string, +}) + + +@asyncio.coroutine +# pylint: disable=unused-argument +def async_setup_platform(hass, config, async_add_devices, discovery_info=None): + """Discover and setup Xeoma Cameras.""" + from pyxeoma.xeoma import Xeoma, XeomaError + + host = config[CONF_HOST] + login = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + new_version = config[CONF_NEW_VERSION] + + xeoma = Xeoma(host, new_version, login, password) + + try: + yield from xeoma.async_test_connection() + discovered_image_names = yield from xeoma.async_get_image_names() + discovered_cameras = [ + { + CONF_IMAGE_NAME: image_name, + CONF_HIDE: False, + CONF_NAME: image_name + } + for image_name in discovered_image_names + ] + + for cam in config[CONF_CAMERAS]: + camera = next( + (dc for dc in discovered_cameras + if dc[CONF_IMAGE_NAME] == cam[CONF_IMAGE_NAME]), None) + + if camera is not None: + if CONF_NAME in cam: + camera[CONF_NAME] = cam[CONF_NAME] + if CONF_HIDE in cam: + camera[CONF_HIDE] = cam[CONF_HIDE] + + cameras = list(filter(lambda c: not c[CONF_HIDE], discovered_cameras)) + async_add_devices( + [XeomaCamera(xeoma, camera[CONF_IMAGE_NAME], camera[CONF_NAME]) + for camera in cameras]) + except XeomaError as err: + _LOGGER.error("Error: %s", err.message) + return + + +class XeomaCamera(Camera): + """Implementation of a Xeoma camera.""" + + def __init__(self, xeoma, image, name): + """Initialize a Xeoma camera.""" + super().__init__() + self._xeoma = xeoma + self._name = name + self._image = image + self._last_image = None + + @asyncio.coroutine + def async_camera_image(self): + """Return a still image response from the camera.""" + from pyxeoma.xeoma import XeomaError + try: + image = yield from self._xeoma.async_get_camera_image(self._image) + self._last_image = image + except XeomaError as err: + _LOGGER.error("Error fetching image: %s", err.message) + + return self._last_image + + @property + def name(self): + """Return the name of this device.""" + return self._name diff --git a/requirements_all.txt b/requirements_all.txt index 17d591161e4..4d42e2b5db5 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -998,6 +998,9 @@ pywebpush==1.5.0 # homeassistant.components.wemo pywemo==0.4.25 +# homeassistant.components.camera.xeoma +pyxeoma==1.2 + # homeassistant.components.zabbix pyzabbix==0.7.4