Add support for connecting to multiple zoneminder instances (#19955)

* Add support for connecting to multiple zoneminder instances

* Lint

* Lint

* Clean up and better error handling

* Fix config validation

* Lint
This commit is contained in:
Rohan Kapoor 2019-01-16 01:15:13 -08:00 committed by Martin Hjelmare
parent fe93ea9bdf
commit bc30491dc0
4 changed files with 78 additions and 54 deletions

View file

@ -19,17 +19,18 @@ DEPENDENCIES = ['zoneminder']
def setup_platform(hass, config, add_entities, discovery_info=None): def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the ZoneMinder cameras.""" """Set up the ZoneMinder cameras."""
filter_urllib3_logging() filter_urllib3_logging()
zm_client = hass.data[ZONEMINDER_DOMAIN]
monitors = zm_client.get_monitors()
if not monitors:
_LOGGER.warning("Could not fetch monitors from ZoneMinder")
return
cameras = [] cameras = []
for monitor in monitors: for zm_client in hass.data[ZONEMINDER_DOMAIN].values():
_LOGGER.info("Initializing camera %s", monitor.id) monitors = zm_client.get_monitors()
cameras.append(ZoneMinderCamera(monitor, zm_client.verify_ssl)) if not monitors:
_LOGGER.warning(
"Could not fetch monitors from ZoneMinder host: %s"
)
return
for monitor in monitors:
_LOGGER.info("Initializing camera %s", monitor.id)
cameras.append(ZoneMinderCamera(monitor, zm_client.verify_ssl))
add_entities(cameras) add_entities(cameras)

View file

@ -42,19 +42,21 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the ZoneMinder sensor platform.""" """Set up the ZoneMinder sensor platform."""
include_archived = config.get(CONF_INCLUDE_ARCHIVED) include_archived = config.get(CONF_INCLUDE_ARCHIVED)
zm_client = hass.data[ZONEMINDER_DOMAIN]
monitors = zm_client.get_monitors()
if not monitors:
_LOGGER.warning('Could not fetch any monitors from ZoneMinder')
sensors = [] sensors = []
for monitor in monitors: for zm_client in hass.data[ZONEMINDER_DOMAIN].values():
sensors.append(ZMSensorMonitors(monitor)) monitors = zm_client.get_monitors()
if not monitors:
_LOGGER.warning('Could not fetch any monitors from ZoneMinder')
for sensor in config[CONF_MONITORED_CONDITIONS]: for monitor in monitors:
sensors.append(ZMSensorEvents(monitor, include_archived, sensor)) sensors.append(ZMSensorMonitors(monitor))
sensors.append(ZMSensorRunState(zm_client)) for sensor in config[CONF_MONITORED_CONDITIONS]:
sensors.append(
ZMSensorEvents(monitor, include_archived, sensor)
)
sensors.append(ZMSensorRunState(zm_client))
add_entities(sensors) add_entities(sensors)

View file

@ -29,16 +29,15 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
on_state = MonitorState(config.get(CONF_COMMAND_ON)) on_state = MonitorState(config.get(CONF_COMMAND_ON))
off_state = MonitorState(config.get(CONF_COMMAND_OFF)) off_state = MonitorState(config.get(CONF_COMMAND_OFF))
zm_client = hass.data[ZONEMINDER_DOMAIN]
monitors = zm_client.get_monitors()
if not monitors:
_LOGGER.warning('Could not fetch monitors from ZoneMinder')
return
switches = [] switches = []
for monitor in monitors: for zm_client in hass.data[ZONEMINDER_DOMAIN].values():
switches.append(ZMSwitchMonitors(monitor, on_state, off_state)) monitors = zm_client.get_monitors()
if not monitors:
_LOGGER.warning('Could not fetch monitors from ZoneMinder')
return
for monitor in monitors:
switches.append(ZMSwitchMonitors(monitor, on_state, off_state))
add_entities(switches) add_entities(switches)

View file

@ -8,10 +8,10 @@ import logging
import voluptuous as vol import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_PASSWORD, CONF_PATH, CONF_SSL, CONF_USERNAME, CONF_HOST, CONF_PASSWORD, CONF_PATH, CONF_SSL, CONF_USERNAME,
CONF_VERIFY_SSL, ATTR_NAME) CONF_VERIFY_SSL, ATTR_NAME, ATTR_ID)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -26,20 +26,23 @@ DEFAULT_TIMEOUT = 10
DEFAULT_VERIFY_SSL = True DEFAULT_VERIFY_SSL = True
DOMAIN = 'zoneminder' DOMAIN = 'zoneminder'
HOST_CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_PATH, default=DEFAULT_PATH): cv.string,
vol.Optional(CONF_PATH_ZMS, default=DEFAULT_PATH_ZMS): cv.string,
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
})
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({ DOMAIN: vol.All(cv.ensure_list, [HOST_CONFIG_SCHEMA])
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_PATH, default=DEFAULT_PATH): cv.string,
vol.Optional(CONF_PATH_ZMS, default=DEFAULT_PATH_ZMS): cv.string,
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
})
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
SERVICE_SET_RUN_STATE = 'set_run_state' SERVICE_SET_RUN_STATE = 'set_run_state'
SET_RUN_STATE_SCHEMA = vol.Schema({ SET_RUN_STATE_SCHEMA = vol.Schema({
vol.Required(ATTR_ID): cv.string,
vol.Required(ATTR_NAME): cv.string vol.Required(ATTR_NAME): cv.string
}) })
@ -48,27 +51,46 @@ def setup(hass, config):
"""Set up the ZoneMinder component.""" """Set up the ZoneMinder component."""
from zoneminder.zm import ZoneMinder from zoneminder.zm import ZoneMinder
conf = config[DOMAIN] hass.data[DOMAIN] = {}
if conf[CONF_SSL]:
schema = 'https'
else:
schema = 'http'
server_origin = '{}://{}'.format(schema, conf[CONF_HOST]) success = True
hass.data[DOMAIN] = ZoneMinder(server_origin,
conf.get(CONF_USERNAME), for conf in config[DOMAIN]:
conf.get(CONF_PASSWORD), if conf[CONF_SSL]:
conf.get(CONF_PATH), schema = 'https'
conf.get(CONF_PATH_ZMS), else:
conf.get(CONF_VERIFY_SSL)) schema = 'http'
host_name = conf[CONF_HOST]
server_origin = '{}://{}'.format(schema, host_name)
zm_client = ZoneMinder(
server_origin,
conf.get(CONF_USERNAME),
conf.get(CONF_PASSWORD),
conf.get(CONF_PATH),
conf.get(CONF_PATH_ZMS),
conf.get(CONF_VERIFY_SSL)
)
hass.data[DOMAIN][host_name] = zm_client
success = zm_client.login() and success
def set_active_state(call): def set_active_state(call):
"""Set the ZoneMinder run state to the given state name.""" """Set the ZoneMinder run state to the given state name."""
return hass.data[DOMAIN].set_active_state(call.data[ATTR_NAME]) zm_id = call.data[ATTR_ID]
state_name = call.data[ATTR_NAME]
if zm_id not in hass.data[DOMAIN]:
_LOGGER.error('Invalid ZoneMinder host provided: %s', zm_id)
if not hass.data[DOMAIN][zm_id].set_active_state(state_name):
_LOGGER.error(
'Unable to change ZoneMinder state. Host: %s, state: %s',
zm_id,
state_name
)
hass.services.register( hass.services.register(
DOMAIN, SERVICE_SET_RUN_STATE, set_active_state, DOMAIN, SERVICE_SET_RUN_STATE, set_active_state,
schema=SET_RUN_STATE_SCHEMA schema=SET_RUN_STATE_SCHEMA
) )
return hass.data[DOMAIN].login() return success