1 """Support the Universal Devices ISY/IoX controllers."""
3 from __future__
import annotations
6 from urllib.parse
import urlparse
8 from aiohttp
import CookieJar
9 from pyisy
import ISY, ISYConnectionError, ISYInvalidAuthError, ISYResponseParseError
10 from pyisy.constants
import CONFIG_NETWORKING, CONFIG_PORTAL
11 import voluptuous
as vol
13 from homeassistant
import config_entries
19 EVENT_HOMEASSISTANT_STOP,
34 DEFAULT_IGNORE_STRING,
35 DEFAULT_SENSOR_STRING,
45 from .helpers
import _categorize_nodes, _categorize_programs
46 from .models
import IsyData
47 from .services
import async_setup_services, async_unload_services
48 from .util
import _async_cleanup_registry_entries
50 CONFIG_SCHEMA = vol.Schema(
51 cv.deprecated(DOMAIN),
52 extra=vol.ALLOW_EXTRA,
59 """Set up the ISY 994 integration."""
60 hass.data.setdefault(DOMAIN, {})
61 isy_data = hass.data[DOMAIN][entry.entry_id] =
IsyData()
63 isy_config = entry.data
64 isy_options = entry.options
67 user = isy_config[CONF_USERNAME]
68 password = isy_config[CONF_PASSWORD]
69 host = urlparse(isy_config[CONF_HOST])
72 tls_version = isy_config.get(CONF_TLS_VER)
73 ignore_identifier = isy_options.get(CONF_IGNORE_STRING, DEFAULT_IGNORE_STRING)
74 sensor_identifier = isy_options.get(CONF_SENSOR_STRING, DEFAULT_SENSOR_STRING)
76 if host.scheme == SCHEME_HTTP:
78 port = host.port
or 80
79 session = aiohttp_client.async_create_clientsession(
80 hass, verify_ssl=
False, cookie_jar=CookieJar(unsafe=
True)
82 elif host.scheme == SCHEME_HTTPS:
84 port = host.port
or 443
85 session = aiohttp_client.async_get_clientsession(hass)
87 _LOGGER.error(
"The ISY/IoX host value in configuration is invalid")
104 async
with asyncio.timeout(60):
105 await isy.initialize()
106 except TimeoutError
as err:
108 "Timed out initializing the ISY; device may be busy, trying again later:"
111 except ISYInvalidAuthError
as err:
113 except ISYConnectionError
as err:
115 f
"Failed to connect to the ISY, please adjust settings and try again: {err}"
117 except ISYResponseParseError
as err:
119 "Invalid XML response from ISY; Ensure the ISY is running the latest"
122 except TypeError
as err:
124 f
"Invalid response ISY, device is likely still starting: {err}"
130 if isy.variables.children:
132 isy, name=CONF_VARIABLES.title(), unique_id=CONF_VARIABLES
134 numbers = isy_data.variables[Platform.NUMBER]
135 for vtype, _, vid
in isy.variables.children:
136 numbers.append(isy.variables[vtype][vid])
138 isy.conf[CONFIG_NETWORKING]
or isy.conf[CONFIG_PORTAL]
139 )
and isy.networking.nobjs:
141 isy, name=CONFIG_NETWORKING, unique_id=CONF_NETWORK
143 for resource
in isy.networking.nobjs:
144 isy_data.net_resources.append(resource)
147 _LOGGER.debug(repr(isy.clock))
153 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
159 def _async_stop_auto_update(event: Event) ->
None:
160 """Stop the isy auto update on Home Assistant Shutdown."""
161 _LOGGER.debug(
"ISY Stopping Event Stream and automatic updates")
164 _LOGGER.debug(
"ISY Starting Event Stream and automatic updates")
165 isy.websocket.start()
167 entry.async_on_unload(entry.add_update_listener(_async_update_listener))
168 entry.async_on_unload(
169 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_stop_auto_update)
181 """Handle options update."""
182 await hass.config_entries.async_reload(entry.entry_id)
189 device_registry = dr.async_get(hass)
190 device_registry.async_get_or_create(
191 config_entry_id=entry.entry_id,
192 connections={(dr.CONNECTION_NETWORK_MAC, isy.uuid)},
193 identifiers={(DOMAIN, isy.uuid)},
194 manufacturer=MANUFACTURER,
195 name=isy.conf[ISY_CONF_NAME],
196 model=isy.conf[ISY_CONF_MODEL],
197 sw_version=isy.conf[ISY_CONF_FIRMWARE],
198 configuration_url=isy.conn.url,
203 """Create device info for ISY service devices."""
208 f
"{isy.uuid}_{unique_id}",
211 manufacturer=MANUFACTURER,
212 name=f
"{isy.conf[ISY_CONF_NAME]} {name}",
213 model=isy.conf[ISY_CONF_MODEL],
214 sw_version=isy.conf[ISY_CONF_FIRMWARE],
215 configuration_url=isy.conn.url,
216 via_device=(DOMAIN, isy.uuid),
217 entry_type=DeviceEntryType.SERVICE,
224 """Unload a config entry."""
225 unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
227 isy_data = hass.data[DOMAIN][entry.entry_id]
229 isy: ISY = isy_data.root
231 _LOGGER.debug(
"ISY Stopping Event Stream and automatic updates")
235 hass.data[DOMAIN].pop(entry.entry_id)
245 device_entry: dr.DeviceEntry,
247 """Remove ISY config entry from a device."""
248 isy_data = hass.data[DOMAIN][config_entry.entry_id]
249 return not device_entry.identifiers.intersection(
250 (DOMAIN, unique_id)
for unique_id
in isy_data.devices
None async_unload_services(HomeAssistant hass)
None async_setup_services(HomeAssistant hass)
None _categorize_programs(IsyData isy_data, Programs programs)
None _categorize_nodes(IsyData isy_data, Nodes nodes, str ignore_identifier, str sensor_identifier)
None _async_cleanup_registry_entries(HomeAssistant hass, str entry_id)
bool async_remove_config_entry_device(HomeAssistant hass, config_entries.ConfigEntry config_entry, dr.DeviceEntry device_entry)
bool async_unload_entry(HomeAssistant hass, config_entries.ConfigEntry entry)
DeviceInfo _create_service_device_info(ISY isy, str name, str unique_id)
None _async_get_or_create_isy_device_in_registry(HomeAssistant hass, config_entries.ConfigEntry entry, ISY isy)
None _async_update_listener(HomeAssistant hass, config_entries.ConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, config_entries.ConfigEntry entry)