diff --git a/homeassistant/components/unifi/hub/__init__.py b/homeassistant/components/unifi/hub/__init__.py index e1f2668b956..b8ed15d46f4 100644 --- a/homeassistant/components/unifi/hub/__init__.py +++ b/homeassistant/components/unifi/hub/__init__.py @@ -1,3 +1,4 @@ """Internal functionality not part of HA infrastructure.""" -from .hub import UnifiHub, get_unifi_api # noqa: F401 +from .api import get_unifi_api # noqa: F401 +from .hub import UnifiHub # noqa: F401 diff --git a/homeassistant/components/unifi/hub/api.py b/homeassistant/components/unifi/hub/api.py new file mode 100644 index 00000000000..8a1be0427b2 --- /dev/null +++ b/homeassistant/components/unifi/hub/api.py @@ -0,0 +1,92 @@ +"""Provide an object to communicate with UniFi Network application.""" + +from __future__ import annotations + +import asyncio +import ssl +from types import MappingProxyType +from typing import Any, Literal + +from aiohttp import CookieJar +import aiounifi +from aiounifi.models.configuration import Configuration + +from homeassistant.const import ( + CONF_HOST, + CONF_PASSWORD, + CONF_PORT, + CONF_USERNAME, + CONF_VERIFY_SSL, +) +from homeassistant.core import HomeAssistant +from homeassistant.helpers import aiohttp_client + +from ..const import CONF_SITE_ID, LOGGER +from ..errors import AuthenticationRequired, CannotConnect + + +async def get_unifi_api( + hass: HomeAssistant, + config: MappingProxyType[str, Any], +) -> aiounifi.Controller: + """Create a aiounifi object and verify authentication.""" + ssl_context: ssl.SSLContext | Literal[False] = False + + if verify_ssl := config.get(CONF_VERIFY_SSL): + session = aiohttp_client.async_get_clientsession(hass) + if isinstance(verify_ssl, str): + ssl_context = ssl.create_default_context(cafile=verify_ssl) + else: + session = aiohttp_client.async_create_clientsession( + hass, verify_ssl=False, cookie_jar=CookieJar(unsafe=True) + ) + + api = aiounifi.Controller( + Configuration( + session, + host=config[CONF_HOST], + username=config[CONF_USERNAME], + password=config[CONF_PASSWORD], + port=config[CONF_PORT], + site=config[CONF_SITE_ID], + ssl_context=ssl_context, + ) + ) + + try: + async with asyncio.timeout(10): + await api.login() + return api + + except aiounifi.Unauthorized as err: + LOGGER.warning( + "Connected to UniFi Network at %s but not registered: %s", + config[CONF_HOST], + err, + ) + raise AuthenticationRequired from err + + except ( + TimeoutError, + aiounifi.BadGateway, + aiounifi.Forbidden, + aiounifi.ServiceUnavailable, + aiounifi.RequestError, + aiounifi.ResponseError, + ) as err: + LOGGER.error( + "Error connecting to the UniFi Network at %s: %s", config[CONF_HOST], err + ) + raise CannotConnect from err + + except aiounifi.LoginRequired as err: + LOGGER.warning( + "Connected to UniFi Network at %s but login required: %s", + config[CONF_HOST], + err, + ) + raise AuthenticationRequired from err + + except aiounifi.AiounifiException as err: + LOGGER.exception("Unknown UniFi Network communication error occurred: %s", err) + raise AuthenticationRequired from err diff --git a/homeassistant/components/unifi/hub/hub.py b/homeassistant/components/unifi/hub/hub.py index 6d52c9127b4..c9054152abb 100644 --- a/homeassistant/components/unifi/hub/hub.py +++ b/homeassistant/components/unifi/hub/hub.py @@ -1,35 +1,18 @@ """UniFi Network abstraction.""" from __future__ import annotations -import asyncio from collections.abc import Iterable from datetime import datetime, timedelta from functools import partial -import ssl -from types import MappingProxyType -from typing import Any, Literal -from aiohttp import CookieJar import aiounifi from aiounifi.interfaces.api_handlers import ItemEvent -from aiounifi.models.configuration import Configuration from aiounifi.models.device import DeviceSetPoePortModeRequest from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - CONF_HOST, - CONF_PASSWORD, - CONF_PORT, - CONF_USERNAME, - CONF_VERIFY_SSL, - Platform, -) +from homeassistant.const import CONF_HOST, Platform from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, callback -from homeassistant.helpers import ( - aiohttp_client, - device_registry as dr, - entity_registry as er, -) +from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.device_registry import ( DeviceEntry, DeviceEntryType, @@ -67,12 +50,10 @@ from ..const import ( DEFAULT_TRACK_DEVICES, DEFAULT_TRACK_WIRED_CLIENTS, DOMAIN as UNIFI_DOMAIN, - LOGGER, PLATFORMS, UNIFI_WIRELESS_CLIENTS, ) from ..entity import UnifiEntity, UnifiEntityDescription -from ..errors import AuthenticationRequired, CannotConnect from .websocket import UnifiWebsocket CHECK_HEARTBEAT_INTERVAL = timedelta(seconds=1) @@ -418,70 +399,3 @@ class UnifiHub: self._cancel_poe_command = None return True - - -async def get_unifi_api( - hass: HomeAssistant, - config: MappingProxyType[str, Any], -) -> aiounifi.Controller: - """Create a aiounifi object and verify authentication.""" - ssl_context: ssl.SSLContext | Literal[False] = False - - if verify_ssl := config.get(CONF_VERIFY_SSL): - session = aiohttp_client.async_get_clientsession(hass) - if isinstance(verify_ssl, str): - ssl_context = ssl.create_default_context(cafile=verify_ssl) - else: - session = aiohttp_client.async_create_clientsession( - hass, verify_ssl=False, cookie_jar=CookieJar(unsafe=True) - ) - - api = aiounifi.Controller( - Configuration( - session, - host=config[CONF_HOST], - username=config[CONF_USERNAME], - password=config[CONF_PASSWORD], - port=config[CONF_PORT], - site=config[CONF_SITE_ID], - ssl_context=ssl_context, - ) - ) - - try: - async with asyncio.timeout(10): - await api.login() - return api - - except aiounifi.Unauthorized as err: - LOGGER.warning( - "Connected to UniFi Network at %s but not registered: %s", - config[CONF_HOST], - err, - ) - raise AuthenticationRequired from err - - except ( - TimeoutError, - aiounifi.BadGateway, - aiounifi.Forbidden, - aiounifi.ServiceUnavailable, - aiounifi.RequestError, - aiounifi.ResponseError, - ) as err: - LOGGER.error( - "Error connecting to the UniFi Network at %s: %s", config[CONF_HOST], err - ) - raise CannotConnect from err - - except aiounifi.LoginRequired as err: - LOGGER.warning( - "Connected to UniFi Network at %s but login required: %s", - config[CONF_HOST], - err, - ) - raise AuthenticationRequired from err - - except aiounifi.AiounifiException as err: - LOGGER.exception("Unknown UniFi Network communication error occurred: %s", err) - raise AuthenticationRequired from err