1 """The Overkiz (by Somfy) integration."""
3 from __future__
import annotations
5 from collections
import defaultdict
6 from dataclasses
import dataclass
8 from aiohttp
import ClientError
9 from pyoverkiz.client
import OverkizClient
10 from pyoverkiz.const
import SUPPORTED_SERVERS
11 from pyoverkiz.enums
import APIType, OverkizState, UIClass, UIWidget
12 from pyoverkiz.exceptions
import (
13 BadCredentialsException,
15 NotSuchTokenException,
16 TooManyRequestsException,
18 from pyoverkiz.models
import Device, OverkizServer, Scenario
19 from pyoverkiz.utils
import generate_local_server
40 OVERKIZ_DEVICE_TO_PLATFORM,
43 UPDATE_INTERVAL_ALL_ASSUMED_STATE,
45 from .coordinator
import OverkizDataUpdateCoordinator
50 """Overkiz data stored in the Home Assistant data object."""
52 coordinator: OverkizDataUpdateCoordinator
53 platforms: defaultdict[Platform, list[Device]]
54 scenarios: list[Scenario]
58 """Set up Overkiz from a config entry."""
59 client: OverkizClient |
None =
None
60 api_type = entry.data.get(CONF_API_TYPE, APIType.CLOUD)
63 if api_type == APIType.LOCAL:
66 host=entry.data[CONF_HOST],
67 token=entry.data[CONF_TOKEN],
68 verify_ssl=entry.data[CONF_VERIFY_SSL],
75 username=entry.data[CONF_USERNAME],
76 password=entry.data[CONF_PASSWORD],
77 server=SUPPORTED_SERVERS[entry.data[CONF_HUB]],
84 setup = await client.get_setup()
88 if api_type == APIType.CLOUD:
89 scenarios = await client.get_scenarios()
92 except (BadCredentialsException, NotSuchTokenException)
as exception:
94 except TooManyRequestsException
as exception:
96 except (TimeoutError, ClientError)
as exception:
98 except MaintenanceException
as exception:
104 name=
"device events",
106 devices=setup.devices,
107 places=setup.root_place,
108 update_interval=UPDATE_INTERVAL,
109 config_entry_id=entry.entry_id,
112 await coordinator.async_config_entry_first_refresh()
114 if coordinator.is_stateless:
117 "All devices have an assumed state. Update interval has been reduced"
120 UPDATE_INTERVAL_ALL_ASSUMED_STATE,
122 coordinator.update_interval = UPDATE_INTERVAL_ALL_ASSUMED_STATE
124 platforms: defaultdict[Platform, list[Device]] = defaultdict(list)
127 coordinator=coordinator, platforms=platforms, scenarios=scenarios
131 for device
in coordinator.data.values():
134 "The following device has been retrieved. Report an issue if not"
135 " supported correctly (%s)"
140 if platform := OVERKIZ_DEVICE_TO_PLATFORM.get(
142 )
or OVERKIZ_DEVICE_TO_PLATFORM.get(device.ui_class):
143 platforms[platform].append(device)
145 device_registry = dr.async_get(hass)
147 for gateway
in setup.gateways:
148 LOGGER.debug(
"Added gateway (%s)", gateway)
150 device_registry.async_get_or_create(
151 config_entry_id=entry.entry_id,
152 identifiers={(DOMAIN, gateway.id)},
153 model=gateway.sub_type.beautify_name
if gateway.sub_type
else None,
154 manufacturer=client.server.manufacturer,
155 name=gateway.type.beautify_name
if gateway.type
else gateway.id,
156 sw_version=gateway.connectivity.protocol_version,
157 configuration_url=client.server.configuration_url,
160 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
166 """Unload a config entry."""
168 if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
169 hass.data[DOMAIN].pop(entry.entry_id)
175 hass: HomeAssistant, config_entry: ConfigEntry
177 """Migrate old entries to new unique IDs."""
178 entity_registry = er.async_get(hass)
188 if (key := entry.unique_id.split(
"-")[-1]).startswith(
189 (
"OverkizState",
"UIWidget",
"UIClass")
191 state = key.split(
".")[1]
194 if key.startswith(
"UIClass"):
195 new_key = UIClass[state]
196 elif key.startswith(
"UIWidget"):
197 new_key = UIWidget[state]
199 new_key = OverkizState[state]
201 new_unique_id = entry.unique_id.replace(key, new_key)
204 "Migrating entity '%s' unique_id from '%s' to '%s'",
210 if existing_entity_id := entity_registry.async_get_entity_id(
211 entry.domain, entry.platform, new_unique_id
214 "Cannot migrate to unique_id '%s', already exists for '%s'. Entity will be removed",
218 entity_registry.async_remove(entry.entity_id)
223 "new_unique_id": new_unique_id,
228 await er.async_migrate_entries(hass, config_entry.entry_id, update_unique_id)
234 hass: HomeAssistant, host: str, token: str, verify_ssl: bool
236 """Create Overkiz local client."""
239 return OverkizClient(
244 server=generate_local_server(host=host),
245 verify_ssl=verify_ssl,
250 hass: HomeAssistant, username: str, password: str, server: OverkizServer
252 """Create Overkiz cloud client."""
256 return OverkizClient(
257 username=username, password=password, session=session, server=server
dict[str, str]|None update_unique_id(er.RegistryEntry entity_entry, str unique_id)
bool _async_migrate_entries(HomeAssistant hass, ConfigEntry config_entry)
OverkizClient create_cloud_client(HomeAssistant hass, str username, str password, OverkizServer server)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
OverkizClient create_local_client(HomeAssistant hass, str host, str token, bool verify_ssl)
aiohttp.ClientSession async_create_clientsession()