mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Add services to ezviz integration (#48984)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
parent
515bd18ddd
commit
22b8dc16c2
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
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
|
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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user