|
2 | 2 | import logging
|
3 | 3 |
|
4 | 4 | import voluptuous as vol
|
| 5 | +from zoneminder.zm import ZoneMinder |
5 | 6 |
|
6 |
| -from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN |
7 |
| -from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN |
8 |
| -from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN |
9 |
| -from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN |
10 |
| -import homeassistant.config_entries as config_entries |
11 |
| -from homeassistant.config_entries import ConfigEntry |
12 | 7 | from homeassistant.const import (
|
13 | 8 | ATTR_ID,
|
14 | 9 | ATTR_NAME,
|
15 | 10 | CONF_HOST,
|
16 | 11 | CONF_PASSWORD,
|
17 | 12 | CONF_PATH,
|
18 |
| - CONF_PLATFORM, |
19 |
| - CONF_SOURCE, |
20 | 13 | CONF_SSL,
|
21 | 14 | CONF_USERNAME,
|
22 | 15 | CONF_VERIFY_SSL,
|
23 | 16 | )
|
24 |
| -from homeassistant.core import HomeAssistant, callback |
25 |
| -from homeassistant.exceptions import ConfigEntryNotReady |
26 |
| -from homeassistant.helpers import config_validation as cv |
27 |
| - |
28 |
| -from . import const |
29 |
| -from .common import ( |
30 |
| - ClientAvailabilityResult, |
31 |
| - async_test_client_availability, |
32 |
| - create_client_from_config, |
33 |
| - del_client_from_data, |
34 |
| - get_client_from_data, |
35 |
| - is_client_in_data, |
36 |
| - set_client_to_data, |
37 |
| - set_platform_configs, |
38 |
| -) |
| 17 | +import homeassistant.helpers.config_validation as cv |
| 18 | +from homeassistant.helpers.discovery import async_load_platform |
39 | 19 |
|
40 | 20 | _LOGGER = logging.getLogger(__name__)
|
41 |
| -PLATFORM_DOMAINS = tuple( |
42 |
| - [BINARY_SENSOR_DOMAIN, CAMERA_DOMAIN, SENSOR_DOMAIN, SWITCH_DOMAIN] |
43 |
| -) |
| 21 | + |
| 22 | +CONF_PATH_ZMS = "path_zms" |
| 23 | + |
| 24 | +DEFAULT_PATH = "/zm/" |
| 25 | +DEFAULT_PATH_ZMS = "/zm/cgi-bin/nph-zms" |
| 26 | +DEFAULT_SSL = False |
| 27 | +DEFAULT_TIMEOUT = 10 |
| 28 | +DEFAULT_VERIFY_SSL = True |
| 29 | +DOMAIN = "zoneminder" |
44 | 30 |
|
45 | 31 | HOST_CONFIG_SCHEMA = vol.Schema(
|
46 | 32 | {
|
47 | 33 | vol.Required(CONF_HOST): cv.string,
|
48 | 34 | vol.Optional(CONF_PASSWORD): cv.string,
|
49 |
| - vol.Optional(CONF_PATH, default=const.DEFAULT_PATH): cv.string, |
50 |
| - vol.Optional(const.CONF_PATH_ZMS, default=const.DEFAULT_PATH_ZMS): cv.string, |
51 |
| - vol.Optional(CONF_SSL, default=const.DEFAULT_SSL): cv.boolean, |
| 35 | + vol.Optional(CONF_PATH, default=DEFAULT_PATH): cv.string, |
| 36 | + vol.Optional(CONF_PATH_ZMS, default=DEFAULT_PATH_ZMS): cv.string, |
| 37 | + vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean, |
52 | 38 | vol.Optional(CONF_USERNAME): cv.string,
|
53 |
| - vol.Optional(CONF_VERIFY_SSL, default=const.DEFAULT_VERIFY_SSL): cv.boolean, |
| 39 | + vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, |
54 | 40 | }
|
55 | 41 | )
|
56 | 42 |
|
57 |
| -CONFIG_SCHEMA = vol.All( |
58 |
| - cv.deprecated(const.DOMAIN, invalidation_version="0.118"), |
59 |
| - vol.Schema( |
60 |
| - {const.DOMAIN: vol.All(cv.ensure_list, [HOST_CONFIG_SCHEMA])}, |
61 |
| - extra=vol.ALLOW_EXTRA, |
62 |
| - ), |
| 43 | +CONFIG_SCHEMA = vol.Schema( |
| 44 | + {DOMAIN: vol.All(cv.ensure_list, [HOST_CONFIG_SCHEMA])}, extra=vol.ALLOW_EXTRA |
63 | 45 | )
|
64 | 46 |
|
| 47 | +SERVICE_SET_RUN_STATE = "set_run_state" |
65 | 48 | SET_RUN_STATE_SCHEMA = vol.Schema(
|
66 | 49 | {vol.Required(ATTR_ID): cv.string, vol.Required(ATTR_NAME): cv.string}
|
67 | 50 | )
|
68 | 51 |
|
69 | 52 |
|
70 |
| -async def async_setup(hass: HomeAssistant, base_config: dict): |
| 53 | +def setup(hass, config): |
71 | 54 | """Set up the ZoneMinder component."""
|
72 | 55 |
|
73 |
| - # Collect the platform specific configs. It's necessary to collect these configs |
74 |
| - # here instead of the platform's setup_platform function because the invocation order |
75 |
| - # of setup_platform and async_setup_entry is not consistent. |
76 |
| - set_platform_configs( |
77 |
| - hass, |
78 |
| - SENSOR_DOMAIN, |
79 |
| - [ |
80 |
| - platform_config |
81 |
| - for platform_config in base_config.get(SENSOR_DOMAIN, []) |
82 |
| - if platform_config[CONF_PLATFORM] == const.DOMAIN |
83 |
| - ], |
84 |
| - ) |
85 |
| - set_platform_configs( |
86 |
| - hass, |
87 |
| - SWITCH_DOMAIN, |
88 |
| - [ |
89 |
| - platform_config |
90 |
| - for platform_config in base_config.get(SWITCH_DOMAIN, []) |
91 |
| - if platform_config[CONF_PLATFORM] == const.DOMAIN |
92 |
| - ], |
93 |
| - ) |
94 |
| - |
95 |
| - config = base_config.get(const.DOMAIN) |
96 |
| - |
97 |
| - if not config: |
98 |
| - return True |
99 |
| - |
100 |
| - for config_item in config: |
101 |
| - hass.async_create_task( |
102 |
| - hass.config_entries.flow.async_init( |
103 |
| - const.DOMAIN, |
104 |
| - context={CONF_SOURCE: config_entries.SOURCE_IMPORT}, |
105 |
| - data=config_item, |
106 |
| - ) |
107 |
| - ) |
108 |
| - |
109 |
| - return True |
110 |
| - |
111 |
| - |
112 |
| -async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: |
113 |
| - """Set up Zoneminder config entry.""" |
114 |
| - zm_client = create_client_from_config(config_entry.data) |
| 56 | + hass.data[DOMAIN] = {} |
115 | 57 |
|
116 |
| - result = await async_test_client_availability(hass, zm_client) |
117 |
| - if result != ClientAvailabilityResult.AVAILABLE: |
118 |
| - raise ConfigEntryNotReady |
| 58 | + success = True |
119 | 59 |
|
120 |
| - set_client_to_data(hass, config_entry.unique_id, zm_client) |
| 60 | + for conf in config[DOMAIN]: |
| 61 | + protocol = "https" if conf[CONF_SSL] else "http" |
121 | 62 |
|
122 |
| - for platform_domain in PLATFORM_DOMAINS: |
123 |
| - hass.async_create_task( |
124 |
| - hass.config_entries.async_forward_entry_setup(config_entry, platform_domain) |
| 63 | + host_name = conf[CONF_HOST] |
| 64 | + server_origin = f"{protocol}://{host_name}" |
| 65 | + zm_client = ZoneMinder( |
| 66 | + server_origin, |
| 67 | + conf.get(CONF_USERNAME), |
| 68 | + conf.get(CONF_PASSWORD), |
| 69 | + conf.get(CONF_PATH), |
| 70 | + conf.get(CONF_PATH_ZMS), |
| 71 | + conf.get(CONF_VERIFY_SSL), |
125 | 72 | )
|
126 |
| - |
127 |
| - if not hass.services.has_service(const.DOMAIN, const.SERVICE_SET_RUN_STATE): |
128 |
| - |
129 |
| - @callback |
130 |
| - def set_active_state(call): |
131 |
| - """Set the ZoneMinder run state to the given state name.""" |
132 |
| - zm_id = call.data[ATTR_ID] |
133 |
| - state_name = call.data[ATTR_NAME] |
134 |
| - if not is_client_in_data(hass, zm_id): |
135 |
| - _LOGGER.error("Invalid ZoneMinder host provided: %s", zm_id) |
136 |
| - return |
137 |
| - |
138 |
| - if not get_client_from_data(hass, zm_id).set_active_state(state_name): |
139 |
| - _LOGGER.error( |
140 |
| - "Unable to change ZoneMinder state. Host: %s, state: %s", |
141 |
| - zm_id, |
142 |
| - state_name, |
143 |
| - ) |
144 |
| - |
145 |
| - hass.services.async_register( |
146 |
| - const.DOMAIN, |
147 |
| - const.SERVICE_SET_RUN_STATE, |
148 |
| - set_active_state, |
149 |
| - schema=SET_RUN_STATE_SCHEMA, |
150 |
| - ) |
151 |
| - |
152 |
| - return True |
153 |
| - |
154 |
| - |
155 |
| -async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: |
156 |
| - """Unload Zoneminder config entry.""" |
157 |
| - for platform_domain in PLATFORM_DOMAINS: |
158 |
| - hass.async_create_task( |
159 |
| - hass.config_entries.async_forward_entry_unload( |
160 |
| - config_entry, platform_domain |
| 73 | + hass.data[DOMAIN][host_name] = zm_client |
| 74 | + |
| 75 | + success = zm_client.login() and success |
| 76 | + |
| 77 | + def set_active_state(call): |
| 78 | + """Set the ZoneMinder run state to the given state name.""" |
| 79 | + zm_id = call.data[ATTR_ID] |
| 80 | + state_name = call.data[ATTR_NAME] |
| 81 | + if zm_id not in hass.data[DOMAIN]: |
| 82 | + _LOGGER.error("Invalid ZoneMinder host provided: %s", zm_id) |
| 83 | + if not hass.data[DOMAIN][zm_id].set_active_state(state_name): |
| 84 | + _LOGGER.error( |
| 85 | + "Unable to change ZoneMinder state. Host: %s, state: %s", |
| 86 | + zm_id, |
| 87 | + state_name, |
161 | 88 | )
|
162 |
| - ) |
163 | 89 |
|
164 |
| - # If this is the last config to exist, remove the service too. |
165 |
| - if len(hass.config_entries.async_entries(const.DOMAIN)) <= 1: |
166 |
| - hass.services.async_remove(const.DOMAIN, const.SERVICE_SET_RUN_STATE) |
| 90 | + hass.services.register( |
| 91 | + DOMAIN, SERVICE_SET_RUN_STATE, set_active_state, schema=SET_RUN_STATE_SCHEMA |
| 92 | + ) |
167 | 93 |
|
168 |
| - del_client_from_data(hass, config_entry.unique_id) |
| 94 | + hass.async_create_task( |
| 95 | + async_load_platform(hass, "binary_sensor", DOMAIN, {}, config) |
| 96 | + ) |
169 | 97 |
|
170 |
| - return True |
| 98 | + return success |
0 commit comments