From 87049283c17ee0995afc1b3d6e4e5e25cceb9715 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sat, 5 Feb 2022 19:09:37 +0100 Subject: [PATCH] Extract base entity class in Plugwise (#65821) --- .../components/plugwise/binary_sensor.py | 4 +- homeassistant/components/plugwise/climate.py | 4 +- homeassistant/components/plugwise/entity.py | 82 +++++++++++++++++++ homeassistant/components/plugwise/gateway.py | 80 +----------------- homeassistant/components/plugwise/sensor.py | 4 +- homeassistant/components/plugwise/switch.py | 4 +- 6 files changed, 93 insertions(+), 85 deletions(-) create mode 100644 homeassistant/components/plugwise/entity.py diff --git a/homeassistant/components/plugwise/binary_sensor.py b/homeassistant/components/plugwise/binary_sensor.py index e8bb0f3366a..25b1578cd8a 100644 --- a/homeassistant/components/plugwise/binary_sensor.py +++ b/homeassistant/components/plugwise/binary_sensor.py @@ -19,7 +19,7 @@ from .const import ( NO_NOTIFICATION_ICON, NOTIFICATION_ICON, ) -from .gateway import SmileGateway +from .entity import PlugwiseEntity BINARY_SENSOR_MAP = { "dhw_state": ["Domestic Hot Water State", None], @@ -77,7 +77,7 @@ async def async_setup_entry( async_add_entities(entities, True) -class SmileBinarySensor(SmileGateway, BinarySensorEntity): +class SmileBinarySensor(PlugwiseEntity, BinarySensorEntity): """Represent Smile Binary Sensors.""" def __init__( diff --git a/homeassistant/components/plugwise/climate.py b/homeassistant/components/plugwise/climate.py index 600b6184191..e3185c0701d 100644 --- a/homeassistant/components/plugwise/climate.py +++ b/homeassistant/components/plugwise/climate.py @@ -30,7 +30,7 @@ from .const import ( SCHEDULE_OFF, SCHEDULE_ON, ) -from .gateway import SmileGateway +from .entity import PlugwiseEntity HVAC_MODES_HEAT_ONLY = [HVAC_MODE_HEAT, HVAC_MODE_AUTO] HVAC_MODES_HEAT_COOL = [HVAC_MODE_HEAT_COOL, HVAC_MODE_AUTO] @@ -74,7 +74,7 @@ async def async_setup_entry( async_add_entities(entities, True) -class PwThermostat(SmileGateway, ClimateEntity): +class PwThermostat(PlugwiseEntity, ClimateEntity): """Representation of an Plugwise thermostat.""" _attr_hvac_mode = HVAC_MODE_HEAT diff --git a/homeassistant/components/plugwise/entity.py b/homeassistant/components/plugwise/entity.py new file mode 100644 index 00000000000..ed9f2c61a78 --- /dev/null +++ b/homeassistant/components/plugwise/entity.py @@ -0,0 +1,82 @@ +"""Generic Plugwise Entity Class.""" +from __future__ import annotations + +from plugwise.smile import Smile + +from homeassistant.const import ( + ATTR_CONFIGURATION_URL, + ATTR_MODEL, + ATTR_VIA_DEVICE, + CONF_HOST, +) +from homeassistant.core import callback +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) + +from .const import DOMAIN + + +class PlugwiseEntity(CoordinatorEntity): + """Represent a PlugWise Entity.""" + + def __init__( + self, api: Smile, coordinator: DataUpdateCoordinator, name: str, dev_id: str + ) -> None: + """Initialise the gateway.""" + super().__init__(coordinator) + + self._api = api + self._name = name + self._dev_id = dev_id + + self._unique_id: str | None = None + self._model: str | None = None + + self._entity_name = self._name + + @property + def unique_id(self) -> str | None: + """Return a unique ID.""" + return self._unique_id + + @property + def name(self) -> str | None: + """Return the name of the entity, if any.""" + return self._name + + @property + def device_info(self) -> DeviceInfo: + """Return the device information.""" + device_information = DeviceInfo( + identifiers={(DOMAIN, self._dev_id)}, + name=self._entity_name, + manufacturer="Plugwise", + ) + + if entry := self.coordinator.config_entry: + device_information[ + ATTR_CONFIGURATION_URL + ] = f"http://{entry.data[CONF_HOST]}" + + if self._model is not None: + device_information[ATTR_MODEL] = self._model.replace("_", " ").title() + + if self._dev_id != self._api.gateway_id: + device_information[ATTR_VIA_DEVICE] = (DOMAIN, str(self._api.gateway_id)) + + return device_information + + async def async_added_to_hass(self) -> None: + """Subscribe to updates.""" + self._async_process_data() + self.async_on_remove( + self.coordinator.async_add_listener(self._async_process_data) + ) + + @callback + def _async_process_data(self) -> None: + """Interpret and process API data.""" + raise NotImplementedError diff --git a/homeassistant/components/plugwise/gateway.py b/homeassistant/components/plugwise/gateway.py index 24c937799ba..9d453596450 100644 --- a/homeassistant/components/plugwise/gateway.py +++ b/homeassistant/components/plugwise/gateway.py @@ -13,25 +13,12 @@ from plugwise.exceptions import ( from plugwise.smile import Smile from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - ATTR_CONFIGURATION_URL, - ATTR_MODEL, - ATTR_VIA_DEVICE, - CONF_HOST, - CONF_PASSWORD, - CONF_PORT, - CONF_USERNAME, -) -from homeassistant.core import HomeAssistant, callback +from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME +from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import device_registry as dr from homeassistant.helpers.aiohttp_client import async_get_clientsession -from homeassistant.helpers.entity import DeviceInfo -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, - UpdateFailed, -) +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import ( COORDINATOR, @@ -139,64 +126,3 @@ async def async_unload_entry_gw(hass: HomeAssistant, entry: ConfigEntry): ): hass.data[DOMAIN].pop(entry.entry_id) return unload_ok - - -class SmileGateway(CoordinatorEntity): - """Represent Smile Gateway.""" - - def __init__(self, api, coordinator, name, dev_id): - """Initialise the gateway.""" - super().__init__(coordinator) - - self._api = api - self._name = name - self._dev_id = dev_id - - self._unique_id = None - self._model = None - - self._entity_name = self._name - - @property - def unique_id(self): - """Return a unique ID.""" - return self._unique_id - - @property - def name(self): - """Return the name of the entity, if any.""" - return self._name - - @property - def device_info(self) -> DeviceInfo: - """Return the device information.""" - device_information = DeviceInfo( - identifiers={(DOMAIN, self._dev_id)}, - name=self._entity_name, - manufacturer="Plugwise", - ) - - if entry := self.coordinator.config_entry: - device_information[ - ATTR_CONFIGURATION_URL - ] = f"http://{entry.data[CONF_HOST]}" - - if self._model is not None: - device_information[ATTR_MODEL] = self._model.replace("_", " ").title() - - if self._dev_id != self._api.gateway_id: - device_information[ATTR_VIA_DEVICE] = (DOMAIN, self._api.gateway_id) - - return device_information - - async def async_added_to_hass(self): - """Subscribe to updates.""" - self._async_process_data() - self.async_on_remove( - self.coordinator.async_add_listener(self._async_process_data) - ) - - @callback - def _async_process_data(self): - """Interpret and process API data.""" - raise NotImplementedError diff --git a/homeassistant/components/plugwise/sensor.py b/homeassistant/components/plugwise/sensor.py index 2fdfd952d8e..da09d4afa13 100644 --- a/homeassistant/components/plugwise/sensor.py +++ b/homeassistant/components/plugwise/sensor.py @@ -37,7 +37,7 @@ from .const import ( SENSOR_MAP_UOM, UNIT_LUMEN, ) -from .gateway import SmileGateway +from .entity import PlugwiseEntity _LOGGER = logging.getLogger(__name__) @@ -300,7 +300,7 @@ async def async_setup_entry( async_add_entities(entities, True) -class SmileSensor(SmileGateway, SensorEntity): +class SmileSensor(PlugwiseEntity, SensorEntity): """Represent Smile Sensors.""" def __init__( diff --git a/homeassistant/components/plugwise/switch.py b/homeassistant/components/plugwise/switch.py index 1aa8bdc51d7..baefcaeb710 100644 --- a/homeassistant/components/plugwise/switch.py +++ b/homeassistant/components/plugwise/switch.py @@ -9,7 +9,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import COORDINATOR, DOMAIN, SWITCH_ICON -from .gateway import SmileGateway +from .entity import PlugwiseEntity _LOGGER = logging.getLogger(__name__) @@ -56,7 +56,7 @@ async def async_setup_entry_gateway(hass, config_entry, async_add_entities): async_add_entities(entities, True) -class GwSwitch(SmileGateway, SwitchEntity): +class GwSwitch(PlugwiseEntity, SwitchEntity): """Representation of a Plugwise plug.""" def __init__(self, api, coordinator, name, dev_id, members, model):