core/homeassistant/components/lyric/__init__.py

201 lines
5.6 KiB
Python
Raw Normal View History

"""The Honeywell Lyric integration."""
import asyncio
from datetime import timedelta
import logging
from typing import Any, Dict, Optional
from aiolyric import Lyric
from aiolyric.objects.device import LyricDevice
from aiolyric.objects.location import LyricLocation
import async_timeout
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import (
aiohttp_client,
config_entry_oauth2_flow,
config_validation as cv,
device_registry as dr,
)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
UpdateFailed,
)
from .api import ConfigEntryLyricClient, LyricLocalOAuth2Implementation
from .config_flow import OAuth2FlowHandler
from .const import DOMAIN, LYRIC_EXCEPTIONS, OAUTH2_AUTHORIZE, OAUTH2_TOKEN
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Required(CONF_CLIENT_ID): cv.string,
vol.Required(CONF_CLIENT_SECRET): cv.string,
}
)
},
extra=vol.ALLOW_EXTRA,
)
_LOGGER = logging.getLogger(__name__)
PLATFORMS = ["climate"]
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the Honeywell Lyric component."""
hass.data[DOMAIN] = {}
if DOMAIN not in config:
return True
hass.data[DOMAIN][CONF_CLIENT_ID] = config[DOMAIN][CONF_CLIENT_ID]
OAuth2FlowHandler.async_register_implementation(
hass,
LyricLocalOAuth2Implementation(
hass,
DOMAIN,
config[DOMAIN][CONF_CLIENT_ID],
config[DOMAIN][CONF_CLIENT_SECRET],
OAUTH2_AUTHORIZE,
OAUTH2_TOKEN,
),
)
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Honeywell Lyric from a config entry."""
implementation = (
await config_entry_oauth2_flow.async_get_config_entry_implementation(
hass, entry
)
)
session = aiohttp_client.async_get_clientsession(hass)
oauth_session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation)
client = ConfigEntryLyricClient(session, oauth_session)
client_id = hass.data[DOMAIN][CONF_CLIENT_ID]
lyric = Lyric(client, client_id)
async def async_update_data() -> Lyric:
"""Fetch data from Lyric."""
try:
async with async_timeout.timeout(60):
await lyric.get_locations()
return lyric
except LYRIC_EXCEPTIONS as exception:
raise UpdateFailed(exception) from exception
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
# Name of the data. For logging purposes.
name="lyric_coordinator",
update_method=async_update_data,
# Polling interval. Will only be polled if there are subscribers.
update_interval=timedelta(seconds=120),
)
hass.data[DOMAIN][entry.entry_id] = coordinator
# Fetch initial data so we have data when entities subscribe
await coordinator.async_refresh()
if not coordinator.last_update_success:
raise ConfigEntryNotReady
for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(entry, component)
for component in PLATFORMS
]
)
)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
class LyricEntity(CoordinatorEntity):
"""Defines a base Honeywell Lyric entity."""
def __init__(
self,
coordinator: DataUpdateCoordinator,
location: LyricLocation,
device: LyricDevice,
key: str,
name: str,
icon: Optional[str],
) -> None:
"""Initialize the Honeywell Lyric entity."""
super().__init__(coordinator)
self._key = key
self._name = name
self._icon = icon
self._location = location
self._mac_id = device.macID
self._device_name = device.name
self._device_model = device.deviceModel
self._update_thermostat = coordinator.data.update_thermostat
@property
def unique_id(self) -> str:
"""Return the unique ID for this entity."""
return self._key
@property
def name(self) -> str:
"""Return the name of the entity."""
return self._name
@property
def icon(self) -> str:
"""Return the mdi icon of the entity."""
return self._icon
@property
def location(self) -> LyricLocation:
"""Get the Lyric Location."""
return self.coordinator.data.locations_dict[self._location.locationID]
@property
def device(self) -> LyricDevice:
"""Get the Lyric Device."""
return self.location.devices_dict[self._mac_id]
class LyricDeviceEntity(LyricEntity):
"""Defines a Honeywell Lyric device entity."""
@property
def device_info(self) -> Dict[str, Any]:
"""Return device information about this Honeywell Lyric instance."""
return {
"connections": {(dr.CONNECTION_NETWORK_MAC, self._mac_id)},
"manufacturer": "Honeywell",
"model": self._device_model,
"name": self._device_name,
}