Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The Screenlogic integration."""
2 
3 import logging
4 from typing import Any
5 
6 from screenlogicpy import ScreenLogicError, ScreenLogicGateway
7 from screenlogicpy.const.data import SHARED_VALUES
8 
9 from homeassistant.config_entries import ConfigEntry
10 from homeassistant.const import Platform
11 from homeassistant.core import HomeAssistant
12 from homeassistant.exceptions import ConfigEntryNotReady
13 from homeassistant.helpers import config_validation as cv, entity_registry as er
14 from homeassistant.helpers.typing import ConfigType
15 from homeassistant.util import slugify
16 
17 from .const import DOMAIN
18 from .coordinator import ScreenlogicDataUpdateCoordinator, async_get_connect_info
19 from .data import ENTITY_MIGRATIONS
20 from .services import async_load_screenlogic_services
21 from .util import generate_unique_id
22 
23 type ScreenLogicConfigEntry = ConfigEntry[ScreenlogicDataUpdateCoordinator]
24 
25 
26 _LOGGER = logging.getLogger(__name__)
27 
28 
29 REQUEST_REFRESH_DELAY = 2
30 HEATER_COOLDOWN_DELAY = 6
31 
32 # These seem to be constant across all controller models
33 PRIMARY_CIRCUIT_IDS = [500, 505] # [Spa, Pool]
34 
35 PLATFORMS = [
36  Platform.BINARY_SENSOR,
37  Platform.CLIMATE,
38  Platform.LIGHT,
39  Platform.NUMBER,
40  Platform.SENSOR,
41  Platform.SWITCH,
42 ]
43 
44 CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
45 
46 
47 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
48  """Set up Screenlogic."""
49 
51 
52  return True
53 
54 
55 async def async_setup_entry(hass: HomeAssistant, entry: ScreenLogicConfigEntry) -> bool:
56  """Set up Screenlogic from a config entry."""
57 
58  await _async_migrate_entries(hass, entry)
59 
60  gateway = ScreenLogicGateway()
61 
62  connect_info = await async_get_connect_info(hass, entry)
63 
64  try:
65  await gateway.async_connect(**connect_info)
66  await gateway.async_update()
67  except ScreenLogicError as ex:
68  raise ConfigEntryNotReady(ex.msg) from ex
69 
71  hass, config_entry=entry, gateway=gateway
72  )
73 
74  await coordinator.async_config_entry_first_refresh()
75 
76  entry.async_on_unload(entry.add_update_listener(async_update_listener))
77 
78  entry.runtime_data = coordinator
79 
80  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
81 
82  return True
83 
84 
86  hass: HomeAssistant, entry: ScreenLogicConfigEntry
87 ) -> bool:
88  """Unload a config entry."""
89  unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
90  if unload_ok:
91  coordinator = entry.runtime_data
92  await coordinator.gateway.async_disconnect()
93  return unload_ok
94 
95 
97  hass: HomeAssistant, entry: ScreenLogicConfigEntry
98 ) -> None:
99  """Handle options update."""
100  await hass.config_entries.async_reload(entry.entry_id)
101 
102 
104  hass: HomeAssistant, config_entry: ScreenLogicConfigEntry
105 ) -> None:
106  """Migrate to new entity names."""
107  entity_registry = er.async_get(hass)
108 
109  for entry in er.async_entries_for_config_entry(
110  entity_registry, config_entry.entry_id
111  ):
112  source_mac, source_key = entry.unique_id.split("_", 1)
113 
114  source_index = None
115  if (
116  len(key_parts := source_key.rsplit("_", 1)) == 2
117  and key_parts[1].isdecimal()
118  ):
119  source_key, source_index = key_parts
120 
121  _LOGGER.debug(
122  "Checking migration status for '%s' against key '%s'",
123  entry.unique_id,
124  source_key,
125  )
126 
127  if source_key not in ENTITY_MIGRATIONS:
128  continue
129 
130  _LOGGER.debug(
131  "Evaluating migration of '%s' from migration key '%s'",
132  entry.entity_id,
133  source_key,
134  )
135  migrations = ENTITY_MIGRATIONS[source_key]
136  updates: dict[str, Any] = {}
137  new_key = migrations["new_key"]
138  if new_key in SHARED_VALUES:
139  if (device := migrations.get("device")) is None:
140  _LOGGER.debug(
141  "Shared key '%s' is missing required migration data 'device'",
142  new_key,
143  )
144  continue
145  if device == "pump" and source_index is None:
146  _LOGGER.debug(
147  "Unable to parse 'source_index' from existing unique_id for pump entity '%s'",
148  source_key,
149  )
150  continue
151  new_unique_id = (
152  f"{source_mac}_{generate_unique_id(device, source_index, new_key)}"
153  )
154  else:
155  new_unique_id = entry.unique_id.replace(source_key, new_key)
156 
157  if new_unique_id and new_unique_id != entry.unique_id:
158  if existing_entity_id := entity_registry.async_get_entity_id(
159  entry.domain, entry.platform, new_unique_id
160  ):
161  _LOGGER.debug(
162  "Cannot migrate '%s' to unique_id '%s', already exists for entity '%s'. Aborting",
163  entry.unique_id,
164  new_unique_id,
165  existing_entity_id,
166  )
167  continue
168  updates["new_unique_id"] = new_unique_id
169 
170  if (old_name := migrations.get("old_name")) is not None:
171  new_name = migrations["new_name"]
172  if (s_old_name := slugify(old_name)) in entry.entity_id:
173  new_entity_id = entry.entity_id.replace(s_old_name, slugify(new_name))
174  if new_entity_id and new_entity_id != entry.entity_id:
175  updates["new_entity_id"] = new_entity_id
176 
177  if entry.original_name and old_name in entry.original_name:
178  new_original_name = entry.original_name.replace(old_name, new_name)
179  if new_original_name and new_original_name != entry.original_name:
180  updates["original_name"] = new_original_name
181 
182  if updates:
183  _LOGGER.debug(
184  "Migrating entity '%s' unique_id from '%s' to '%s'",
185  entry.entity_id,
186  entry.unique_id,
187  new_unique_id,
188  )
189  entity_registry.async_update_entity(entry.entity_id, **updates)
dict[str, str|int] async_get_connect_info(HomeAssistant hass, ConfigEntry entry)
Definition: coordinator.py:33
def async_load_screenlogic_services(HomeAssistant hass)
Definition: services.py:58
None _async_migrate_entries(HomeAssistant hass, ScreenLogicConfigEntry config_entry)
Definition: __init__.py:105
bool async_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:47
bool async_setup_entry(HomeAssistant hass, ScreenLogicConfigEntry entry)
Definition: __init__.py:55
bool async_unload_entry(HomeAssistant hass, ScreenLogicConfigEntry entry)
Definition: __init__.py:87
None async_update_listener(HomeAssistant hass, ScreenLogicConfigEntry entry)
Definition: __init__.py:98
str slugify(str|None text, *str separator="_")
Definition: __init__.py:41