1 """Support for Ring Doorbell/Chimes."""
3 from __future__
import annotations
5 from dataclasses
import dataclass
7 from typing
import Any, cast
10 from ring_doorbell
import Auth, Ring, RingDevices
19 from .const
import CONF_LISTEN_CREDENTIALS, DOMAIN, PLATFORMS
20 from .coordinator
import RingDataCoordinator, RingListenCoordinator
22 _LOGGER = logging.getLogger(__name__)
27 """Class to support type hinting of ring data collection."""
31 devices_coordinator: RingDataCoordinator
32 listen_coordinator: RingListenCoordinator
35 type RingConfigEntry = ConfigEntry[RingData]
39 """Return user-agent for Auth instantiation.
41 user_agent will be the display name in the ring.com authorised devices.
43 return f
"{APPLICATION_NAME}/{DOMAIN}-integration"
47 """Set up a config entry."""
49 def token_updater(token: dict[str, Any]) ->
None:
50 """Handle from async context when token is updated."""
51 hass.config_entries.async_update_entry(
53 data={**entry.data, CONF_TOKEN: token},
56 def listen_credentials_updater(token: dict[str, Any]) ->
None:
57 """Handle from async context when token is updated."""
58 hass.config_entries.async_update_entry(
60 data={**entry.data, CONF_LISTEN_CREDENTIALS: token},
67 entry.data[CONF_TOKEN],
69 hardware_id=entry.data[CONF_DEVICE_ID],
70 http_client_session=client_session,
75 listen_credentials = entry.data.get(CONF_LISTEN_CREDENTIALS)
77 hass, ring, listen_credentials, listen_credentials_updater
80 await devices_coordinator.async_config_entry_first_refresh()
84 devices=ring.devices(),
85 devices_coordinator=devices_coordinator,
86 listen_coordinator=listen_coordinator,
89 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
95 """Unload Ring entry."""
96 return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
100 hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
102 """Remove a config entry from a device."""
107 """Migrate old config entry."""
108 entry_version = entry.version
109 entry_minor_version = entry.minor_version
110 entry_id = entry.entry_id
112 new_minor_version = 2
113 if entry_version == 1
and entry_minor_version == 1:
115 "Migrating from version %s.%s", entry_version, entry_minor_version
119 entity_registry = er.async_get(hass)
122 def _async_str_unique_id_migrator(
123 entity_entry: er.RegistryEntry,
124 ) -> dict[str, str] |
None:
126 unique_id = cast(str | int, entity_entry.unique_id)
127 if isinstance(unique_id, int):
128 new_unique_id =
str(unique_id)
129 if existing_entity_id := entity_registry.async_get_entity_id(
130 entity_entry.domain, entity_entry.platform, new_unique_id
133 "Cannot migrate to unique_id '%s', already exists for '%s', "
134 "You may have to delete unavailable ring entities",
139 _LOGGER.debug(
"Fixing non string unique id %s", entity_entry.unique_id)
140 return {
"new_unique_id": new_unique_id}
143 await er.async_migrate_entries(hass, entry_id, _async_str_unique_id_migrator)
146 hardware_id =
str(uuid.uuid4())
147 hass.config_entries.async_update_entry(
149 data={**entry.data, CONF_DEVICE_ID: hardware_id},
150 minor_version=new_minor_version,
153 "Migration to version %s.%s complete", entry_version, new_minor_version
156 entry_minor_version = entry.minor_version
157 new_minor_version = 3
158 if entry_version == 1
and entry_minor_version == 2:
160 "Migrating from version %s.%s", entry_version, entry_minor_version
164 def _async_camera_unique_id_migrator(
165 entity_entry: er.RegistryEntry,
166 ) -> dict[str, str] |
None:
168 if entity_entry.domain == CAMERA_DOMAIN
and not isinstance(
169 cast(str | int, entity_entry.unique_id), int
171 new_unique_id = f
"{entity_entry.unique_id}-last_recording"
172 return {
"new_unique_id": new_unique_id}
175 await er.async_migrate_entries(hass, entry_id, _async_camera_unique_id_migrator)
177 hass.config_entries.async_update_entry(
179 minor_version=new_minor_version,
182 "Migration to version %s.%s complete", entry_version, new_minor_version
str get_auth_user_agent()
bool async_migrate_entry(HomeAssistant hass, ConfigEntry entry)
bool async_remove_config_entry_device(HomeAssistant hass, ConfigEntry config_entry, dr.DeviceEntry device_entry)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, RingConfigEntry entry)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)