Add services to ezviz integration (#48984)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
parent
515bd18ddd
commit
22b8dc16c2
10 changed files with 274 additions and 30 deletions
|
@ -2,7 +2,8 @@
|
|||
from datetime import timedelta
|
||||
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 (
|
||||
CONF_PASSWORD,
|
||||
|
|
|
@ -1,29 +1,43 @@
|
|||
"""Support ezviz camera devices."""
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from haffmpeg.tools import IMAGE_JPEG, ImageFrame
|
||||
from pyezviz.exceptions import HTTPError, InvalidHost, PyEzvizError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.camera import PLATFORM_SCHEMA, SUPPORT_STREAM, Camera
|
||||
from homeassistant.components.ffmpeg import DATA_FFMPEG
|
||||
from homeassistant.config_entries import SOURCE_DISCOVERY, SOURCE_IGNORE, SOURCE_IMPORT
|
||||
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.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import (
|
||||
ATTR_DIRECTION,
|
||||
ATTR_ENABLE,
|
||||
ATTR_LEVEL,
|
||||
ATTR_SERIAL,
|
||||
ATTR_SPEED,
|
||||
ATTR_TYPE,
|
||||
CONF_CAMERAS,
|
||||
CONF_FFMPEG_ARGUMENTS,
|
||||
DATA_COORDINATOR,
|
||||
DEFAULT_CAMERA_USERNAME,
|
||||
DEFAULT_FFMPEG_ARGUMENTS,
|
||||
DEFAULT_RTSP_PORT,
|
||||
DIR_DOWN,
|
||||
DIR_LEFT,
|
||||
DIR_RIGHT,
|
||||
DIR_UP,
|
||||
DOMAIN,
|
||||
MANUFACTURER,
|
||||
SERVICE_ALARM_SOUND,
|
||||
SERVICE_ALARM_TRIGER,
|
||||
SERVICE_DETECTION_SENSITIVITY,
|
||||
SERVICE_PTZ,
|
||||
SERVICE_WAKE_DEVICE,
|
||||
)
|
||||
|
||||
CAMERA_SCHEMA = vol.Schema(
|
||||
|
@ -40,8 +54,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|||
|
||||
_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):
|
||||
"""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)
|
||||
|
||||
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):
|
||||
"""An implementation of a Ezviz security camera."""
|
||||
|
@ -232,6 +284,24 @@ class EzvizCamera(CoordinatorEntity, Camera, RestoreEntity):
|
|||
"""Camera Motion Detection Status."""
|
||||
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
|
||||
def unique_id(self):
|
||||
"""Return the name of this camera."""
|
||||
|
@ -271,3 +341,52 @@ class EzvizCamera(CoordinatorEntity, Camera, RestoreEntity):
|
|||
self._rtsp_stream = rtsp_stream_source
|
||||
return rtsp_stream_source
|
||||
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
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
"""Config flow for ezviz."""
|
||||
import logging
|
||||
|
||||
from pyezviz.client import EzvizClient, HTTPError, InvalidURL, PyEzvizError
|
||||
from pyezviz.test_cam_rtsp import AuthTestResultFailed, InvalidHost, TestRTSPAuth
|
||||
from pyezviz.client import EzvizClient
|
||||
from pyezviz.exceptions import (
|
||||
AuthTestResultFailed,
|
||||
HTTPError,
|
||||
InvalidHost,
|
||||
InvalidURL,
|
||||
PyEzvizError,
|
||||
)
|
||||
from pyezviz.test_cam_rtsp import TestRTSPAuth
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, OptionsFlow
|
||||
|
|
|
@ -6,29 +6,30 @@ MANUFACTURER = "Ezviz"
|
|||
# Configuration
|
||||
ATTR_SERIAL = "serial"
|
||||
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"
|
||||
ATTR_HOME = "HOME_MODE"
|
||||
ATTR_AWAY = "AWAY_MODE"
|
||||
ATTR_TYPE_CLOUD = "EZVIZ_CLOUD_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
|
||||
EU_URL = "apiieu.ezvizlife.com"
|
||||
RUSSIA_URL = "apirus.ezvizru.com"
|
||||
|
|
|
@ -3,7 +3,7 @@ from datetime import timedelta
|
|||
import logging
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"documentation": "https://www.home-assistant.io/integrations/ezviz",
|
||||
"dependencies": ["ffmpeg"],
|
||||
"codeowners": ["@RenierM26", "@baqs"],
|
||||
"requirements": ["pyezviz==0.1.8.7"],
|
||||
"requirements": ["pyezviz==0.1.8.9"],
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
}
|
||||
|
|
111
homeassistant/components/ezviz/services.yaml
Normal file
111
homeassistant/components/ezviz/services.yaml
Normal 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
|
|
@ -1411,7 +1411,7 @@ pyephember==0.3.1
|
|||
pyeverlights==0.1.0
|
||||
|
||||
# homeassistant.components.ezviz
|
||||
pyezviz==0.1.8.7
|
||||
pyezviz==0.1.8.9
|
||||
|
||||
# homeassistant.components.fido
|
||||
pyfido==2.1.1
|
||||
|
|
|
@ -776,7 +776,7 @@ pyeconet==0.1.14
|
|||
pyeverlights==0.1.0
|
||||
|
||||
# homeassistant.components.ezviz
|
||||
pyezviz==0.1.8.7
|
||||
pyezviz==0.1.8.9
|
||||
|
||||
# homeassistant.components.fido
|
||||
pyfido==2.1.1
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
|
||||
from unittest.mock import patch
|
||||
|
||||
from pyezviz.client import HTTPError, InvalidURL, PyEzvizError
|
||||
from pyezviz.test_cam_rtsp import AuthTestResultFailed, InvalidHost
|
||||
from pyezviz.exceptions import (
|
||||
AuthTestResultFailed,
|
||||
HTTPError,
|
||||
InvalidHost,
|
||||
InvalidURL,
|
||||
PyEzvizError,
|
||||
)
|
||||
|
||||
from homeassistant.components.ezviz.const import (
|
||||
ATTR_SERIAL,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue