From 99798223d9bcf8d39b5b349fe1697321c7f0214c Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 13 Jan 2022 13:09:08 +0100 Subject: [PATCH] Elgato refactoring; add base entity (#64034) --- homeassistant/components/elgato/__init__.py | 22 ++++++++---- homeassistant/components/elgato/button.py | 29 +++++----------- homeassistant/components/elgato/entity.py | 22 ++++++++++++ homeassistant/components/elgato/light.py | 37 +++++++-------------- 4 files changed, 59 insertions(+), 51 deletions(-) create mode 100644 homeassistant/components/elgato/entity.py diff --git a/homeassistant/components/elgato/__init__.py b/homeassistant/components/elgato/__init__.py index 6ef540365be..d90b4a2dccf 100644 --- a/homeassistant/components/elgato/__init__.py +++ b/homeassistant/components/elgato/__init__.py @@ -1,7 +1,8 @@ """Support for Elgato Lights.""" import logging +from typing import NamedTuple -from elgato import Elgato, ElgatoConnectionError +from elgato import Elgato, ElgatoConnectionError, Info from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_PORT, Platform @@ -14,6 +15,13 @@ from .const import DOMAIN PLATFORMS = [Platform.BUTTON, Platform.LIGHT] +class HomeAssistantElgatoData(NamedTuple): + """Elgato data stored in the Home Assistant data object.""" + + client: Elgato + info: Info + + async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Elgato Light from a config entry.""" session = async_get_clientsession(hass) @@ -25,12 +33,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Ensure we can connect to it try: - await elgato.info() + info = await elgato.info() except ElgatoConnectionError as exception: logging.getLogger(__name__).debug("Unable to connect: %s", exception) raise ConfigEntryNotReady from exception - hass.data.setdefault(DOMAIN, {})[entry.entry_id] = elgato + hass.data.setdefault(DOMAIN, {})[entry.entry_id] = HomeAssistantElgatoData( + client=elgato, + info=info, + ) + hass.config_entries.async_setup_platforms(entry, PLATFORMS) return True @@ -38,9 +50,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload Elgato Light config entry.""" - # Unload entities for this entry/device. - unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) - if unload_ok: + if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): # Cleanup del hass.data[DOMAIN][entry.entry_id] if not hass.data[DOMAIN]: diff --git a/homeassistant/components/elgato/button.py b/homeassistant/components/elgato/button.py index 5e53ecfad40..5baff347fdf 100644 --- a/homeassistant/components/elgato/button.py +++ b/homeassistant/components/elgato/button.py @@ -8,10 +8,12 @@ from elgato import Elgato, ElgatoError, Info from homeassistant.components.button import ButtonEntity, ButtonEntityDescription from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant -from homeassistant.helpers.entity import DeviceInfo, EntityCategory +from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback +from . import HomeAssistantElgatoData from .const import DOMAIN +from .entity import ElgatoEntity _LOGGER = logging.getLogger(__name__) @@ -22,18 +24,16 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up Elgato button based on a config entry.""" - elgato: Elgato = hass.data[DOMAIN][entry.entry_id] - info = await elgato.info() - async_add_entities([ElgatoIdentifyButton(elgato, info)]) + data: HomeAssistantElgatoData = hass.data[DOMAIN][entry.entry_id] + async_add_entities([ElgatoIdentifyButton(data.client, data.info)]) -class ElgatoIdentifyButton(ButtonEntity): +class ElgatoIdentifyButton(ElgatoEntity, ButtonEntity): """Defines an Elgato identify button.""" - def __init__(self, elgato: Elgato, info: Info) -> None: + def __init__(self, client: Elgato, info: Info) -> None: """Initialize the button entity.""" - self.elgato = elgato - self._info = info + super().__init__(client, info) self.entity_description = ButtonEntityDescription( key="identify", name="Identify", @@ -42,20 +42,9 @@ class ElgatoIdentifyButton(ButtonEntity): ) self._attr_unique_id = f"{info.serial_number}_{self.entity_description.key}" - @property - def device_info(self) -> DeviceInfo: - """Return device information about this Elgato Light.""" - return DeviceInfo( - identifiers={(DOMAIN, self._info.serial_number)}, - manufacturer="Elgato", - model=self._info.product_name, - name=self._info.product_name, - sw_version=f"{self._info.firmware_version} ({self._info.firmware_build_number})", - ) - async def async_press(self) -> None: """Identify the light, will make it blink.""" try: - await self.elgato.identify() + await self.client.identify() except ElgatoError: _LOGGER.exception("An error occurred while identifying the Elgato Light") diff --git a/homeassistant/components/elgato/entity.py b/homeassistant/components/elgato/entity.py new file mode 100644 index 00000000000..e4f7cc440e5 --- /dev/null +++ b/homeassistant/components/elgato/entity.py @@ -0,0 +1,22 @@ +"""Base entity for the Elgato integration.""" + +from elgato import Elgato, Info + +from homeassistant.helpers.entity import DeviceInfo, Entity + +from .const import DOMAIN + + +class ElgatoEntity(Entity): + """Defines an Elgato entity.""" + + def __init__(self, client: Elgato, info: Info) -> None: + """Initialize an Elgato entity.""" + self.client = client + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, info.serial_number)}, + manufacturer="Elgato", + model=info.product_name, + name=info.product_name, + sw_version=f"{info.firmware_version} ({info.firmware_build_number})", + ) diff --git a/homeassistant/components/elgato/light.py b/homeassistant/components/elgato/light.py index d8a6e74c41a..6f4209f23fe 100644 --- a/homeassistant/components/elgato/light.py +++ b/homeassistant/components/elgato/light.py @@ -17,13 +17,14 @@ from homeassistant.components.light import ( ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant -from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import ( AddEntitiesCallback, async_get_current_platform, ) +from . import HomeAssistantElgatoData from .const import DOMAIN, SERVICE_IDENTIFY +from .entity import ElgatoEntity _LOGGER = logging.getLogger(__name__) @@ -37,10 +38,9 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up Elgato Light based on a config entry.""" - elgato: Elgato = hass.data[DOMAIN][entry.entry_id] - info = await elgato.info() - settings = await elgato.settings() - async_add_entities([ElgatoLight(elgato, info, settings)], True) + data: HomeAssistantElgatoData = hass.data[DOMAIN][entry.entry_id] + settings = await data.client.settings() + async_add_entities([ElgatoLight(data.client, data.info, settings)], True) platform = async_get_current_platform() platform.async_register_entity_service( @@ -50,15 +50,13 @@ async def async_setup_entry( ) -class ElgatoLight(LightEntity): +class ElgatoLight(ElgatoEntity, LightEntity): """Defines an Elgato Light.""" - def __init__(self, elgato: Elgato, info: Info, settings: Settings) -> None: + def __init__(self, client: Elgato, info: Info, settings: Settings) -> None: """Initialize Elgato Light.""" - self._info = info - self._settings = settings + super().__init__(client, info) self._state: State | None = None - self.elgato = elgato min_mired = 143 max_mired = 344 @@ -122,7 +120,7 @@ class ElgatoLight(LightEntity): async def async_turn_off(self, **kwargs: Any) -> None: """Turn off the light.""" try: - await self.elgato.light(on=False) + await self.client.light(on=False) except ElgatoError: _LOGGER.error("An error occurred while updating the Elgato Light") self._state = None @@ -154,7 +152,7 @@ class ElgatoLight(LightEntity): temperature = self.color_temp try: - await self.elgato.light( + await self.client.light( on=True, brightness=brightness, hue=hue, @@ -169,7 +167,7 @@ class ElgatoLight(LightEntity): """Update Elgato entity.""" restoring = self._state is None try: - self._state = await self.elgato.state() + self._state = await self.client.state() if restoring: _LOGGER.info("Connection restored") except ElgatoError as err: @@ -177,21 +175,10 @@ class ElgatoLight(LightEntity): meth("An error occurred while updating the Elgato Light: %s", err) self._state = None - @property - def device_info(self) -> DeviceInfo: - """Return device information about this Elgato Light.""" - return DeviceInfo( - identifiers={(DOMAIN, self._info.serial_number)}, - manufacturer="Elgato", - model=self._info.product_name, - name=self._info.product_name, - sw_version=f"{self._info.firmware_version} ({self._info.firmware_build_number})", - ) - async def async_identify(self) -> None: """Identify the light, will make it blink.""" try: - await self.elgato.identify() + await self.client.identify() except ElgatoError: _LOGGER.exception("An error occurred while identifying the Elgato Light") self._state = None