Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The TP-Link Omada integration."""
2 
3 from __future__ import annotations
4 
5 from tplink_omada_client import OmadaSite
6 from tplink_omada_client.devices import OmadaListDevice
7 from tplink_omada_client.exceptions import (
8  ConnectionFailed,
9  LoginFailed,
10  OmadaClientException,
11  UnsupportedControllerVersion,
12 )
13 
14 from homeassistant.config_entries import ConfigEntry, ConfigEntryState
15 from homeassistant.const import Platform
16 from homeassistant.core import HomeAssistant, ServiceCall
17 from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
18 from homeassistant.helpers import device_registry as dr
19 
20 from .config_flow import CONF_SITE, create_omada_client
21 from .const import DOMAIN
22 from .controller import OmadaSiteController
23 
24 PLATFORMS: list[Platform] = [
25  Platform.BINARY_SENSOR,
26  Platform.DEVICE_TRACKER,
27  Platform.SENSOR,
28  Platform.SWITCH,
29  Platform.UPDATE,
30 ]
31 
32 
33 type OmadaConfigEntry = ConfigEntry[OmadaSiteController]
34 
35 
36 async def async_setup_entry(hass: HomeAssistant, entry: OmadaConfigEntry) -> bool:
37  """Set up TP-Link Omada from a config entry."""
38 
39  try:
40  client = await create_omada_client(hass, entry.data)
41  await client.login()
42 
43  except (LoginFailed, UnsupportedControllerVersion) as ex:
45  f"Omada controller refused login attempt: {ex}"
46  ) from ex
47  except ConnectionFailed as ex:
48  raise ConfigEntryNotReady(
49  f"Omada controller could not be reached: {ex}"
50  ) from ex
51 
52  except OmadaClientException as ex:
53  raise ConfigEntryNotReady(
54  f"Unexpected error connecting to Omada controller: {ex}"
55  ) from ex
56 
57  site_client = await client.get_site_client(OmadaSite("", entry.data[CONF_SITE]))
58  controller = OmadaSiteController(hass, site_client)
59  await controller.initialize_first_refresh()
60 
61  entry.runtime_data = controller
62 
63  async def handle_reconnect_client(call: ServiceCall) -> None:
64  """Handle the service action call."""
65  mac: str | None = call.data.get("mac")
66  if not mac:
67  return
68 
69  await site_client.reconnect_client(mac)
70 
71  hass.services.async_register(DOMAIN, "reconnect_client", handle_reconnect_client)
72 
73  _remove_old_devices(hass, entry, controller.devices_coordinator.data)
74 
75  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
76 
77  return True
78 
79 
80 async def async_unload_entry(hass: HomeAssistant, entry: OmadaConfigEntry) -> bool:
81  """Unload a config entry."""
82  unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
83  loaded_entries = [
84  entry
85  for entry in hass.config_entries.async_entries(DOMAIN)
86  if entry.state == ConfigEntryState.LOADED
87  ]
88  if len(loaded_entries) == 1:
89  # This is the last loaded instance of Omada, deregister any services
90  hass.services.async_remove(DOMAIN, "reconnect_client")
91 
92  return unload_ok
93 
94 
96  hass: HomeAssistant,
97  entry: OmadaConfigEntry,
98  omada_devices: dict[str, OmadaListDevice],
99 ) -> None:
100  device_registry = dr.async_get(hass)
101 
102  for registered_device in device_registry.devices.get_devices_for_config_entry_id(
103  entry.entry_id
104  ):
105  mac = next(
106  (i[1] for i in registered_device.identifiers if i[0] == DOMAIN), None
107  )
108  if mac and mac not in omada_devices:
109  device_registry.async_update_device(
110  registered_device.id, remove_config_entry_id=entry.entry_id
111  )