Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The myUplink integration."""
2 
3 from __future__ import annotations
4 
5 from http import HTTPStatus
6 
7 from aiohttp import ClientError, ClientResponseError
8 from myuplink import MyUplinkAPI, get_manufacturer, get_model, get_system_name
9 
10 from homeassistant.config_entries import ConfigEntry
11 from homeassistant.const import Platform
12 from homeassistant.core import HomeAssistant, callback
13 from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
14 from homeassistant.helpers import (
15  aiohttp_client,
16  config_entry_oauth2_flow,
17  device_registry as dr,
18 )
19 from homeassistant.helpers.device_registry import DeviceEntry
20 
21 from .api import AsyncConfigEntryAuth
22 from .const import DOMAIN, OAUTH2_SCOPES
23 from .coordinator import MyUplinkDataCoordinator
24 
25 PLATFORMS: list[Platform] = [
26  Platform.BINARY_SENSOR,
27  Platform.NUMBER,
28  Platform.SELECT,
29  Platform.SENSOR,
30  Platform.SWITCH,
31  Platform.UPDATE,
32 ]
33 
34 type MyUplinkConfigEntry = ConfigEntry[MyUplinkDataCoordinator]
35 
36 
38  hass: HomeAssistant, config_entry: MyUplinkConfigEntry
39 ) -> bool:
40  """Set up myUplink from a config entry."""
41 
42  implementation = (
43  await config_entry_oauth2_flow.async_get_config_entry_implementation(
44  hass, config_entry
45  )
46  )
47  session = config_entry_oauth2_flow.OAuth2Session(hass, config_entry, implementation)
48  auth = AsyncConfigEntryAuth(aiohttp_client.async_get_clientsession(hass), session)
49 
50  try:
51  await auth.async_get_access_token()
52  except ClientResponseError as err:
53  if err.status in {HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN}:
54  raise ConfigEntryAuthFailed from err
55  raise ConfigEntryNotReady from err
56  except ClientError as err:
57  raise ConfigEntryNotReady from err
58 
59  if set(config_entry.data["token"]["scope"].split(" ")) != set(OAUTH2_SCOPES):
60  raise ConfigEntryAuthFailed("Incorrect OAuth2 scope")
61 
62  # Setup MyUplinkAPI and coordinator for data fetch
63  api = MyUplinkAPI(auth)
64  coordinator = MyUplinkDataCoordinator(hass, api)
65  await coordinator.async_config_entry_first_refresh()
66  config_entry.runtime_data = coordinator
67 
68  # Update device registry
69  create_devices(hass, config_entry, coordinator)
70 
71  await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
72 
73  return True
74 
75 
76 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
77  """Unload a config entry."""
78  return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
79 
80 
81 @callback
83  hass: HomeAssistant, config_entry: ConfigEntry, coordinator: MyUplinkDataCoordinator
84 ) -> None:
85  """Update all devices."""
86  device_registry = dr.async_get(hass)
87 
88  for system in coordinator.data.systems:
89  devices_in_system = [x.id for x in system.devices]
90  for device_id, device in coordinator.data.devices.items():
91  if device_id in devices_in_system:
92  device_registry.async_get_or_create(
93  config_entry_id=config_entry.entry_id,
94  identifiers={(DOMAIN, device_id)},
95  name=get_system_name(system),
96  manufacturer=get_manufacturer(device),
97  model=get_model(device),
98  sw_version=device.firmwareCurrent,
99  serial_number=device.product_serial_number,
100  )
101 
102 
104  hass: HomeAssistant, config_entry: MyUplinkConfigEntry, device_entry: DeviceEntry
105 ) -> bool:
106  """Remove myuplink config entry from a device."""
107 
108  myuplink_data = config_entry.runtime_data
109  return not device_entry.identifiers.intersection(
110  (DOMAIN, device_id) for device_id in myuplink_data.data.devices
111  )