diff --git a/.coveragerc b/.coveragerc index 03ee2e4038c..e96340dde1c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -694,6 +694,7 @@ omit = homeassistant/components/vesync/switch.py homeassistant/components/viaggiatreno/sensor.py homeassistant/components/vicare/* + homeassistant/components/vivotek/camera.py homeassistant/components/vizio/media_player.py homeassistant/components/vlc/media_player.py homeassistant/components/vlc_telnet/media_player.py diff --git a/homeassistant/components/vivotek/__init__.py b/homeassistant/components/vivotek/__init__.py new file mode 100644 index 00000000000..b5220b12a9b --- /dev/null +++ b/homeassistant/components/vivotek/__init__.py @@ -0,0 +1 @@ +"""The Vivotek camera component.""" diff --git a/homeassistant/components/vivotek/camera.py b/homeassistant/components/vivotek/camera.py new file mode 100644 index 00000000000..bf136731cb6 --- /dev/null +++ b/homeassistant/components/vivotek/camera.py @@ -0,0 +1,120 @@ +"""Support for Vivotek IP Cameras.""" + +import logging + +import voluptuous as vol +from libpyvivotek import VivotekCamera + +from homeassistant.const import ( + CONF_IP_ADDRESS, + CONF_NAME, + CONF_PASSWORD, + CONF_SSL, + CONF_USERNAME, + CONF_VERIFY_SSL, +) +from homeassistant.components.camera import PLATFORM_SCHEMA, SUPPORT_STREAM, Camera +from homeassistant.helpers import config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +CONF_FRAMERATE = "framerate" + +DEFAULT_CAMERA_BRAND = "Vivotek" +DEFAULT_NAME = "Vivotek Camera" +DEFAULT_EVENT_0_KEY = "event_i0_enable" + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( + { + vol.Required(CONF_IP_ADDRESS): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Required(CONF_USERNAME): cv.string, + vol.Optional(CONF_SSL, default=False): cv.boolean, + vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + vol.Optional(CONF_FRAMERATE, default=2): cv.positive_int, + } +) + + +def setup_platform(hass, config, add_entities, discovery_info=None): + """Set up a Vivotek IP Camera.""" + args = dict( + config=config, + cam=VivotekCamera( + host=config[CONF_IP_ADDRESS], + port=(443 if config[CONF_SSL] else 80), + verify_ssl=config[CONF_VERIFY_SSL], + usr=config[CONF_USERNAME], + pwd=config[CONF_PASSWORD], + ), + stream_source=( + "rtsp://%s:%s@%s:554/live.sdp", + config[CONF_USERNAME], + config[CONF_PASSWORD], + config[CONF_IP_ADDRESS], + ), + ) + add_entities([VivotekCam(**args)]) + + +class VivotekCam(Camera): + """A Vivotek IP camera.""" + + def __init__(self, config, cam, stream_source): + """Initialize a Vivotek camera.""" + super().__init__() + + self._cam = cam + self._frame_interval = 1 / config[CONF_FRAMERATE] + self._motion_detection_enabled = False + self._name = config[CONF_NAME] + self._stream_source = stream_source + + @property + def supported_features(self): + """Return supported features for this camera.""" + return SUPPORT_STREAM + + @property + def frame_interval(self): + """Return the interval between frames of the mjpeg stream.""" + return self._frame_interval + + def camera_image(self): + """Return bytes of camera image.""" + return self._cam.snapshot() + + @property + def name(self): + """Return the name of this device.""" + return self._name + + async def stream_source(self): + """Return the source of the stream.""" + return self._stream_source + + @property + def motion_detection_enabled(self): + """Return the camera motion detection status.""" + return self._motion_detection_enabled + + def disable_motion_detection(self): + """Disable motion detection in camera.""" + response = self._cam.set_param(DEFAULT_EVENT_0_KEY, 0) + self._motion_detection_enabled = int(response) == 1 + + def enable_motion_detection(self): + """Enable motion detection in camera.""" + response = self._cam.set_param(DEFAULT_EVENT_0_KEY, 1) + self._motion_detection_enabled = int(response) == 1 + + @property + def brand(self): + """Return the camera brand.""" + return DEFAULT_CAMERA_BRAND + + @property + def model(self): + """Return the camera model.""" + return self._cam.model_name diff --git a/homeassistant/components/vivotek/manifest.json b/homeassistant/components/vivotek/manifest.json new file mode 100644 index 00000000000..8a6a37762d4 --- /dev/null +++ b/homeassistant/components/vivotek/manifest.json @@ -0,0 +1,10 @@ +{ + "domain": "vivotek", + "name": "Vivotek", + "documentation": "https://www.home-assistant.io/components/vivotek", + "requirements": [ + "libpyvivotek==0.2.1" + ], + "dependencies": [], + "codeowners": [] +} diff --git a/requirements_all.txt b/requirements_all.txt index 225227cc5b5..e467f5ab2ba 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -726,6 +726,9 @@ libpurecool==0.5.0 # homeassistant.components.foscam libpyfoscam==1.0 +# homeassistant.components.vivotek +libpyvivotek==0.2.1 + # homeassistant.components.mikrotik librouteros==2.3.0