core/homeassistant/components/zoneminder/__init__.py

171 lines
5.3 KiB
Python

"""Support for ZoneMinder."""
import logging
import voluptuous as vol
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
import homeassistant.config_entries as config_entries
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_ID,
ATTR_NAME,
CONF_HOST,
CONF_PASSWORD,
CONF_PATH,
CONF_PLATFORM,
CONF_SOURCE,
CONF_SSL,
CONF_USERNAME,
CONF_VERIFY_SSL,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from . import const
from .common import (
ClientAvailabilityResult,
async_test_client_availability,
create_client_from_config,
del_client_from_data,
get_client_from_data,
is_client_in_data,
set_client_to_data,
set_platform_configs,
)
_LOGGER = logging.getLogger(__name__)
PLATFORM_DOMAINS = tuple(
[BINARY_SENSOR_DOMAIN, CAMERA_DOMAIN, SENSOR_DOMAIN, SWITCH_DOMAIN]
)
HOST_CONFIG_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_PATH, default=const.DEFAULT_PATH): cv.string,
vol.Optional(const.CONF_PATH_ZMS, default=const.DEFAULT_PATH_ZMS): cv.string,
vol.Optional(CONF_SSL, default=const.DEFAULT_SSL): cv.boolean,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_VERIFY_SSL, default=const.DEFAULT_VERIFY_SSL): cv.boolean,
}
)
CONFIG_SCHEMA = vol.All(
cv.deprecated(const.DOMAIN, invalidation_version="0.118"),
vol.Schema(
{const.DOMAIN: vol.All(cv.ensure_list, [HOST_CONFIG_SCHEMA])},
extra=vol.ALLOW_EXTRA,
),
)
SET_RUN_STATE_SCHEMA = vol.Schema(
{vol.Required(ATTR_ID): cv.string, vol.Required(ATTR_NAME): cv.string}
)
async def async_setup(hass: HomeAssistant, base_config: dict):
"""Set up the ZoneMinder component."""
# Collect the platform specific configs. It's necessary to collect these configs
# here instead of the platform's setup_platform function because the invocation order
# of setup_platform and async_setup_entry is not consistent.
set_platform_configs(
hass,
SENSOR_DOMAIN,
[
platform_config
for platform_config in base_config.get(SENSOR_DOMAIN, [])
if platform_config[CONF_PLATFORM] == const.DOMAIN
],
)
set_platform_configs(
hass,
SWITCH_DOMAIN,
[
platform_config
for platform_config in base_config.get(SWITCH_DOMAIN, [])
if platform_config[CONF_PLATFORM] == const.DOMAIN
],
)
config = base_config.get(const.DOMAIN)
if not config:
return True
for config_item in config:
hass.async_create_task(
hass.config_entries.flow.async_init(
const.DOMAIN,
context={CONF_SOURCE: config_entries.SOURCE_IMPORT},
data=config_item,
)
)
return True
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Set up Zoneminder config entry."""
zm_client = create_client_from_config(config_entry.data)
result = await async_test_client_availability(hass, zm_client)
if result != ClientAvailabilityResult.AVAILABLE:
raise ConfigEntryNotReady
set_client_to_data(hass, config_entry.unique_id, zm_client)
for platform_domain in PLATFORM_DOMAINS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, platform_domain)
)
if not hass.services.has_service(const.DOMAIN, const.SERVICE_SET_RUN_STATE):
@callback
def set_active_state(call):
"""Set the ZoneMinder run state to the given state name."""
zm_id = call.data[ATTR_ID]
state_name = call.data[ATTR_NAME]
if not is_client_in_data(hass, zm_id):
_LOGGER.error("Invalid ZoneMinder host provided: %s", zm_id)
return
if not get_client_from_data(hass, zm_id).set_active_state(state_name):
_LOGGER.error(
"Unable to change ZoneMinder state. Host: %s, state: %s",
zm_id,
state_name,
)
hass.services.async_register(
const.DOMAIN,
const.SERVICE_SET_RUN_STATE,
set_active_state,
schema=SET_RUN_STATE_SCHEMA,
)
return True
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload Zoneminder config entry."""
for platform_domain in PLATFORM_DOMAINS:
hass.async_create_task(
hass.config_entries.async_forward_entry_unload(
config_entry, platform_domain
)
)
# If this is the last config to exist, remove the service too.
if len(hass.config_entries.async_entries(const.DOMAIN)) <= 1:
hass.services.async_remove(const.DOMAIN, const.SERVICE_SET_RUN_STATE)
del_client_from_data(hass, config_entry.unique_id)
return True