core/homeassistant/components/ezviz/__init__.py

130 lines
3.6 KiB
Python
Raw Normal View History

Update Ezviz Component (#45722) * Update Ezviz Component * Update Ezviz for pylint test * Update Ezviz component pylint tests * Update Ezviz component tests * Update Ezviz Component tests * Update Ezviz component pylint error * Fix ezviz component config flow tests * Update ezviz component * Update Ezviz component * Add sensor platforms * issue with requirements file * Update binary_sensor to include switches * Updates to Ezviz sensors * Removed enum private method. * Fix switch args * Update homeassistant/components/ezviz/switch.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * config flow checks login info * Config_flow now imports ezviz from camera platform * Update test * Updated config_flow with unique_id and remove period from logging * Added two camera services and clarified service descryptions in services.yaml * Fixed variable name mistake with new service * Added french integration translation * Config_flow add camera rtsp credentials as seperate entities, with user step and import step * rerun hassfest after rebase * Removed region from legacy config schema, removed logging in camera platform setup that could contain credentials, removed unused constant. * Regenerate requirements * Fix tests and add config_flow import config test * Added addition test to config_flow to test successfull camera entity create. * Add to tests method to end in create entry, config_flow cleanup, use entry instead of entry.data * Removed all services, sorted platforms in init file. * Changed RTSP logging to debug from warning. (Forgot to change this before commit) * Cleanup typing, change platform order, bump pyezviz version * Added types to entries, allow creation of main entry if deleted by validating existance of type * Config_flow doesn't store serial under entry data, camera rtsp read from entry and not stored in hass, removed duplicate abort if unique id from config flow * Fix test of config_flow * Update tests/components/ezviz/test_config_flow.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update tests/components/ezviz/test_config_flow.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update tests/components/ezviz/test_config_flow.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Bumped pyezviz api version, added api pyezvizerror exception raised in api (on HTTPError), cleanup unused imports. * rebase * cleanup coordinator, bump pyezviz api version, move async_setup_entry to add entry options to camera entries. (order change) * Added discovery step in config_flow if cameras detected without rtsp config entry * Reload main integration after addition or completion of camera rtsp config entry * Add tests for discovery config_flow, added a few other output asserts * Camera platform call discover flow with hass.async_create_task. Fixes to config_flow for discovery step * Fix config_flow discovery, add check to legacy yaml camera platform import, move camera private method to camera import step * Remove not needed check from config_flow import step. * Cleanup config_flow * Added config_flow description for discovered camera * Reordered description in config_flow confim step. * Added serial to flow_step description for discovered camera, readded camera attributes for rtsp stream url (allows user to check RTSP cred), added local ip and firmware upgade available. * Bumped pyezviz version and changed region code to region url. (Russia uses a completly different url). PyEzviz adds a Local IP sensor, removed camera entity attributes. * Add RSTP describe auth check from API to config_flow * url as vol.in options in Config_flow * Config_flow changes to discovery step, added exceptions, fixed tests, added rtsp config validate module mock to test disovery confirm step * Add test for config_flow step user_camera * Added tests for abort flow * Extend tests on custom url flow step * Fix exceptions in config_flow, fix test for discovery import exception test * Bump pyezviz api version * Bump api version, added config_flow function to wake hybernating camera before testing credentials, removed "user camera" step from config flow not needed as cameras are discovered. * Create pyezviz Api instance for config_flow wake hybernating camera, fixed tests and added fixture to mock method * Added alarm_control_panel with support to arm/disarm all cameras, fixed camera is available attribute (returns 2 if unavailable, 1 if available) * Skip ignored entities when setup up camera RTSP stream * Remove alarm_control_panel, add additional config_flow tests * Cleanup tests, add tests for discovery_step. * Add test for config_flow rtsp test step1 exceptions * Removed redundant except from second step in test RTSP method * All tests to CREATE or ABORT, added step exception for general HTTP error so user can retry in case of trasient network condition * Ammended tests with output checks for step_id, error, data, create entry method calls. * bumped ezviz api now rases library exceptions. Config_flow, coordiantor and init raises library exceptions. Updated test sideeffect for library exceptions * Bump api version, Create mock ezviz cloud account on discovery tests first to allow more complete testing of step. * Add abort to rtsp verification method if cloud account was deleted and add tests * Update tests/components/ezviz/__init__.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/const.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update tests/components/ezviz/__init__.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Undo config import change to password key for yaml, move hass.data.setdefault to async_setup_entry and remove async_setup * Fixed tests by removing _patch_async_setup as this was removed from init. * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/ezviz/camera.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Changed L67 on camera config to complete suggestion for cleanup Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2021-04-09 10:39:19 +00:00
"""Support for Ezviz camera."""
import asyncio
from datetime import timedelta
import logging
from pyezviz.client import EzvizClient, HTTPError, InvalidURL, PyEzvizError
from homeassistant.const import (
CONF_PASSWORD,
CONF_TIMEOUT,
CONF_TYPE,
CONF_URL,
CONF_USERNAME,
)
from homeassistant.exceptions import ConfigEntryNotReady
from .const import (
ATTR_TYPE_CAMERA,
ATTR_TYPE_CLOUD,
CONF_FFMPEG_ARGUMENTS,
DATA_COORDINATOR,
DATA_UNDO_UPDATE_LISTENER,
DEFAULT_FFMPEG_ARGUMENTS,
DEFAULT_TIMEOUT,
DOMAIN,
)
from .coordinator import EzvizDataUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
PLATFORMS = [
"binary_sensor",
"camera",
"sensor",
"switch",
]
async def async_setup_entry(hass, entry):
"""Set up Ezviz from a config entry."""
hass.data.setdefault(DOMAIN, {})
if not entry.options:
options = {
CONF_FFMPEG_ARGUMENTS: entry.data.get(
CONF_FFMPEG_ARGUMENTS, DEFAULT_FFMPEG_ARGUMENTS
),
CONF_TIMEOUT: entry.data.get(CONF_TIMEOUT, DEFAULT_TIMEOUT),
}
hass.config_entries.async_update_entry(entry, options=options)
if entry.data.get(CONF_TYPE) == ATTR_TYPE_CAMERA:
if hass.data.get(DOMAIN):
# Should only execute on addition of new camera entry.
# Fetch Entry id of main account and reload it.
for item in hass.config_entries.async_entries():
if item.data.get(CONF_TYPE) == ATTR_TYPE_CLOUD:
_LOGGER.info("Reload Ezviz integration with new camera rtsp entry")
await hass.config_entries.async_reload(item.entry_id)
return True
try:
ezviz_client = await hass.async_add_executor_job(
_get_ezviz_client_instance, entry
)
except (InvalidURL, HTTPError, PyEzvizError) as error:
_LOGGER.error("Unable to connect to Ezviz service: %s", str(error))
raise ConfigEntryNotReady from error
coordinator = EzvizDataUpdateCoordinator(hass, api=ezviz_client)
await coordinator.async_refresh()
if not coordinator.last_update_success:
raise ConfigEntryNotReady
undo_listener = entry.add_update_listener(_async_update_listener)
hass.data[DOMAIN][entry.entry_id] = {
DATA_COORDINATOR: coordinator,
DATA_UNDO_UPDATE_LISTENER: undo_listener,
}
for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)
return True
async def async_unload_entry(hass, entry):
"""Unload a config entry."""
if entry.data.get(CONF_TYPE) == ATTR_TYPE_CAMERA:
return True
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(entry, component)
for component in PLATFORMS
]
)
)
if unload_ok:
hass.data[DOMAIN][entry.entry_id][DATA_UNDO_UPDATE_LISTENER]()
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
async def _async_update_listener(hass, entry):
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)
def _get_ezviz_client_instance(entry):
"""Initialize a new instance of EzvizClientApi."""
ezviz_client = EzvizClient(
entry.data[CONF_USERNAME],
entry.data[CONF_PASSWORD],
entry.data[CONF_URL],
entry.options.get(CONF_TIMEOUT, DEFAULT_TIMEOUT),
)
ezviz_client.login()
return ezviz_client