Add services to ezviz integration (#48984)

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
RenierM26 2021-06-15 13:23:32 +02:00 committed by GitHub
parent 515bd18ddd
commit 22b8dc16c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 274 additions and 30 deletions

View File

@ -2,7 +2,8 @@
from datetime import timedelta from datetime import timedelta
import logging import logging
from pyezviz.client import EzvizClient, HTTPError, InvalidURL, PyEzvizError from pyezviz.client import EzvizClient
from pyezviz.exceptions import HTTPError, InvalidURL, PyEzvizError
from homeassistant.const import ( from homeassistant.const import (
CONF_PASSWORD, CONF_PASSWORD,

View File

@ -1,29 +1,43 @@
"""Support ezviz camera devices.""" """Support ezviz camera devices."""
import asyncio import asyncio
from datetime import timedelta
import logging import logging
from haffmpeg.tools import IMAGE_JPEG, ImageFrame from haffmpeg.tools import IMAGE_JPEG, ImageFrame
from pyezviz.exceptions import HTTPError, InvalidHost, PyEzvizError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.camera import PLATFORM_SCHEMA, SUPPORT_STREAM, Camera from homeassistant.components.camera import PLATFORM_SCHEMA, SUPPORT_STREAM, Camera
from homeassistant.components.ffmpeg import DATA_FFMPEG from homeassistant.components.ffmpeg import DATA_FFMPEG
from homeassistant.config_entries import SOURCE_DISCOVERY, SOURCE_IGNORE, SOURCE_IMPORT from homeassistant.config_entries import SOURCE_DISCOVERY, SOURCE_IGNORE, SOURCE_IMPORT
from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import (
ATTR_DIRECTION,
ATTR_ENABLE,
ATTR_LEVEL,
ATTR_SERIAL, ATTR_SERIAL,
ATTR_SPEED,
ATTR_TYPE,
CONF_CAMERAS, CONF_CAMERAS,
CONF_FFMPEG_ARGUMENTS, CONF_FFMPEG_ARGUMENTS,
DATA_COORDINATOR, DATA_COORDINATOR,
DEFAULT_CAMERA_USERNAME, DEFAULT_CAMERA_USERNAME,
DEFAULT_FFMPEG_ARGUMENTS, DEFAULT_FFMPEG_ARGUMENTS,
DEFAULT_RTSP_PORT, DEFAULT_RTSP_PORT,
DIR_DOWN,
DIR_LEFT,
DIR_RIGHT,
DIR_UP,
DOMAIN, DOMAIN,
MANUFACTURER, MANUFACTURER,
SERVICE_ALARM_SOUND,
SERVICE_ALARM_TRIGER,
SERVICE_DETECTION_SENSITIVITY,
SERVICE_PTZ,
SERVICE_WAKE_DEVICE,
) )
CAMERA_SCHEMA = vol.Schema( CAMERA_SCHEMA = vol.Schema(
@ -40,8 +54,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
MIN_TIME_BETWEEN_SESSION_RENEW = timedelta(seconds=90)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up a Ezviz IP Camera from platform config.""" """Set up a Ezviz IP Camera from platform config."""
@ -157,6 +169,46 @@ async def async_setup_entry(hass, entry, async_add_entities):
async_add_entities(camera_entities) async_add_entities(camera_entities)
platform = entity_platform.current_platform.get()
platform.async_register_entity_service(
SERVICE_PTZ,
{
vol.Required(ATTR_DIRECTION): vol.In(
[DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT]
),
vol.Required(ATTR_SPEED): cv.positive_int,
},
"perform_ptz",
)
platform.async_register_entity_service(
SERVICE_ALARM_TRIGER,
{
vol.Required(ATTR_ENABLE): cv.positive_int,
},
"perform_sound_alarm",
)
platform.async_register_entity_service(
SERVICE_WAKE_DEVICE, {}, "perform_wake_device"
)
platform.async_register_entity_service(
SERVICE_ALARM_SOUND,
{vol.Required(ATTR_LEVEL): cv.positive_int},
"perform_alarm_sound",
)
platform.async_register_entity_service(
SERVICE_DETECTION_SENSITIVITY,
{
vol.Required(ATTR_LEVEL): cv.positive_int,
vol.Required(ATTR_TYPE): cv.positive_int,
},
"perform_set_alarm_detection_sensibility",
)
class EzvizCamera(CoordinatorEntity, Camera, RestoreEntity): class EzvizCamera(CoordinatorEntity, Camera, RestoreEntity):
"""An implementation of a Ezviz security camera.""" """An implementation of a Ezviz security camera."""
@ -232,6 +284,24 @@ class EzvizCamera(CoordinatorEntity, Camera, RestoreEntity):
"""Camera Motion Detection Status.""" """Camera Motion Detection Status."""
return self.coordinator.data[self._idx]["alarm_notify"] return self.coordinator.data[self._idx]["alarm_notify"]
def enable_motion_detection(self):
"""Enable motion detection in camera."""
try:
self.coordinator.ezviz_client.set_camera_defence(self._serial, 1)
except InvalidHost as err:
_LOGGER.error("Error enabling motion detection")
raise InvalidHost from err
def disable_motion_detection(self):
"""Disable motion detection."""
try:
self.coordinator.ezviz_client.set_camera_defence(self._serial, 0)
except InvalidHost as err:
_LOGGER.error("Error disabling motion detection")
raise InvalidHost from err
@property @property
def unique_id(self): def unique_id(self):
"""Return the name of this camera.""" """Return the name of this camera."""
@ -271,3 +341,52 @@ class EzvizCamera(CoordinatorEntity, Camera, RestoreEntity):
self._rtsp_stream = rtsp_stream_source self._rtsp_stream = rtsp_stream_source
return rtsp_stream_source return rtsp_stream_source
return None return None
def perform_ptz(self, direction, speed):
"""Perform a PTZ action on the camera."""
_LOGGER.debug("PTZ action '%s' on %s", direction, self._name)
try:
self.coordinator.ezviz_client.ptz_control(
str(direction).upper(), self._serial, "START", speed
)
self.coordinator.ezviz_client.ptz_control(
str(direction).upper(), self._serial, "STOP", speed
)
except HTTPError as err:
_LOGGER.error("Cannot perform PTZ")
raise HTTPError from err
def perform_sound_alarm(self, enable):
"""Sound the alarm on a camera."""
try:
self.coordinator.ezviz_client.sound_alarm(self._serial, enable)
except HTTPError as err:
_LOGGER.debug("Cannot sound alarm")
raise HTTPError from err
def perform_wake_device(self):
"""Basically wakes the camera by querying the device."""
try:
self.coordinator.ezviz_client.get_detection_sensibility(self._serial)
except (HTTPError, PyEzvizError) as err:
_LOGGER.error("Cannot wake device")
raise PyEzvizError from err
def perform_alarm_sound(self, level):
"""Enable/Disable movement sound alarm."""
try:
self.coordinator.ezviz_client.alarm_sound(self._serial, level, 1)
except HTTPError as err:
_LOGGER.error("Cannot set alarm sound level for on movement detected")
raise HTTPError from err
def perform_set_alarm_detection_sensibility(self, level, type_value):
"""Set camera detection sensibility level service."""
try:
self.coordinator.ezviz_client.detection_sensibility(
self._serial, level, type_value
)
except (HTTPError, PyEzvizError) as err:
_LOGGER.error("Cannot set detection sensitivity level")
raise PyEzvizError from err

View File

@ -1,8 +1,15 @@
"""Config flow for ezviz.""" """Config flow for ezviz."""
import logging import logging
from pyezviz.client import EzvizClient, HTTPError, InvalidURL, PyEzvizError from pyezviz.client import EzvizClient
from pyezviz.test_cam_rtsp import AuthTestResultFailed, InvalidHost, TestRTSPAuth from pyezviz.exceptions import (
AuthTestResultFailed,
HTTPError,
InvalidHost,
InvalidURL,
PyEzvizError,
)
from pyezviz.test_cam_rtsp import TestRTSPAuth
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, OptionsFlow from homeassistant.config_entries import ConfigFlow, OptionsFlow

View File

@ -6,29 +6,30 @@ MANUFACTURER = "Ezviz"
# Configuration # Configuration
ATTR_SERIAL = "serial" ATTR_SERIAL = "serial"
CONF_CAMERAS = "cameras" CONF_CAMERAS = "cameras"
ATTR_SWITCH = "switch"
ATTR_ENABLE = "enable"
ATTR_DIRECTION = "direction"
ATTR_SPEED = "speed"
ATTR_LEVEL = "level"
ATTR_TYPE = "type_value"
DIR_UP = "up"
DIR_DOWN = "down"
DIR_LEFT = "left"
DIR_RIGHT = "right"
ATTR_LIGHT = "LIGHT"
ATTR_SOUND = "SOUND"
ATTR_INFRARED_LIGHT = "INFRARED_LIGHT"
ATTR_PRIVACY = "PRIVACY"
ATTR_SLEEP = "SLEEP"
ATTR_MOBILE_TRACKING = "MOBILE_TRACKING"
ATTR_TRACKING = "TRACKING"
CONF_FFMPEG_ARGUMENTS = "ffmpeg_arguments" CONF_FFMPEG_ARGUMENTS = "ffmpeg_arguments"
ATTR_HOME = "HOME_MODE" ATTR_HOME = "HOME_MODE"
ATTR_AWAY = "AWAY_MODE" ATTR_AWAY = "AWAY_MODE"
ATTR_TYPE_CLOUD = "EZVIZ_CLOUD_ACCOUNT" ATTR_TYPE_CLOUD = "EZVIZ_CLOUD_ACCOUNT"
ATTR_TYPE_CAMERA = "CAMERA_ACCOUNT" ATTR_TYPE_CAMERA = "CAMERA_ACCOUNT"
# Services data
DIR_UP = "up"
DIR_DOWN = "down"
DIR_LEFT = "left"
DIR_RIGHT = "right"
ATTR_ENABLE = "enable"
ATTR_DIRECTION = "direction"
ATTR_SPEED = "speed"
ATTR_LEVEL = "level"
ATTR_TYPE = "type_value"
# Service names
SERVICE_PTZ = "ptz"
SERVICE_ALARM_TRIGER = "sound_alarm"
SERVICE_WAKE_DEVICE = "wake_device"
SERVICE_ALARM_SOUND = "alarm_sound"
SERVICE_DETECTION_SENSITIVITY = "set_alarm_detection_sensibility"
# Defaults # Defaults
EU_URL = "apiieu.ezvizlife.com" EU_URL = "apiieu.ezvizlife.com"
RUSSIA_URL = "apirus.ezvizru.com" RUSSIA_URL = "apirus.ezvizru.com"

View File

@ -3,7 +3,7 @@ from datetime import timedelta
import logging import logging
from async_timeout import timeout from async_timeout import timeout
from pyezviz.client import HTTPError, InvalidURL, PyEzvizError from pyezviz.exceptions import HTTPError, InvalidURL, PyEzvizError
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

View File

@ -4,7 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/ezviz", "documentation": "https://www.home-assistant.io/integrations/ezviz",
"dependencies": ["ffmpeg"], "dependencies": ["ffmpeg"],
"codeowners": ["@RenierM26", "@baqs"], "codeowners": ["@RenierM26", "@baqs"],
"requirements": ["pyezviz==0.1.8.7"], "requirements": ["pyezviz==0.1.8.9"],
"config_flow": true, "config_flow": true,
"iot_class": "cloud_polling" "iot_class": "cloud_polling"
} }

View File

@ -0,0 +1,111 @@
alarm_sound:
name: Set warning sound level.
description: Set movement warning sound level.
target:
entity:
integration: ezviz
domain: camera
fields:
level:
name: Sound level
description: Sound level (2 is disabled, 1 intensive, 0 soft).
required: true
example: 0
default: 0
selector:
number:
min: 0
max: 2
step: 1
mode: box
ptz:
name: PTZ
description: Moves the camera to the direction, with defined speed
target:
entity:
integration: ezviz
domain: camera
fields:
direction:
name: Direction
description: Direction to move camera (up, down, left, right).
required: true
example: "up"
default: "up"
selector:
select:
options:
- "up"
- "down"
- "left"
- "right"
speed:
name: Speed
description: Speed of movement (from 1 to 9).
required: true
example: 5
default: 5
selector:
number:
min: 1
max: 9
step: 1
mode: box
set_alarm_detection_sensibility:
name: Detection sensitivity
description: Sets the detection sensibility level.
target:
entity:
integration: ezviz
domain: camera
fields:
level:
name: Sensitivity Level
description: 'Sensibility level (1-6) for type 0 (Normal camera)
or (1-100) for type 3 (PIR sensor camera).'
required: true
example: 3
default: 3
selector:
number:
min: 1
max: 100
step: 1
mode: box
type_value:
name: Detection type
description: 'Type of detection. Options : 0 - Camera or 3 - PIR Sensor Camera'
required: true
example: '0'
default: '0'
selector:
select:
options:
- '0'
- '3'
sound_alarm:
name: Sound Alarm
description: Sounds the alarm on your camera.
target:
entity:
integration: ezviz
domain: camera
fields:
enable:
description: Enter 1 or 2 (1=disable, 2=enable).
required: true
example: 1
default: 1
selector:
number:
min: 1
max: 2
step: 1
mode: box
wake_device:
name: Wake Camera
description: This can be used to wake the camera/device from hibernation.
target:
entity:
integration: ezviz
domain: camera

View File

@ -1411,7 +1411,7 @@ pyephember==0.3.1
pyeverlights==0.1.0 pyeverlights==0.1.0
# homeassistant.components.ezviz # homeassistant.components.ezviz
pyezviz==0.1.8.7 pyezviz==0.1.8.9
# homeassistant.components.fido # homeassistant.components.fido
pyfido==2.1.1 pyfido==2.1.1

View File

@ -776,7 +776,7 @@ pyeconet==0.1.14
pyeverlights==0.1.0 pyeverlights==0.1.0
# homeassistant.components.ezviz # homeassistant.components.ezviz
pyezviz==0.1.8.7 pyezviz==0.1.8.9
# homeassistant.components.fido # homeassistant.components.fido
pyfido==2.1.1 pyfido==2.1.1

View File

@ -2,8 +2,13 @@
from unittest.mock import patch from unittest.mock import patch
from pyezviz.client import HTTPError, InvalidURL, PyEzvizError from pyezviz.exceptions import (
from pyezviz.test_cam_rtsp import AuthTestResultFailed, InvalidHost AuthTestResultFailed,
HTTPError,
InvalidHost,
InvalidURL,
PyEzvizError,
)
from homeassistant.components.ezviz.const import ( from homeassistant.components.ezviz.const import (
ATTR_SERIAL, ATTR_SERIAL,