"""Base ScreenLogicEntity definitions.""" from datetime import datetime import logging from typing import Any from screenlogicpy import ScreenLogicGateway from screenlogicpy.const import CODE, DATA as SL_DATA, EQUIPMENT, ON_OFF from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import ScreenlogicDataUpdateCoordinator _LOGGER = logging.getLogger(__name__) class ScreenlogicEntity(CoordinatorEntity[ScreenlogicDataUpdateCoordinator]): """Base class for all ScreenLogic entities.""" def __init__( self, coordinator: ScreenlogicDataUpdateCoordinator, data_key: str, enabled: bool = True, ) -> None: """Initialize of the entity.""" super().__init__(coordinator) self._data_key = data_key self._attr_entity_registry_enabled_default = enabled self._attr_unique_id = f"{self.mac}_{self._data_key}" controller_type = self.config_data["controller_type"] hardware_type = self.config_data["hardware_type"] try: equipment_model = EQUIPMENT.CONTROLLER_HARDWARE[controller_type][ hardware_type ] except KeyError: equipment_model = f"Unknown Model C:{controller_type} H:{hardware_type}" mac = self.mac assert mac is not None self._attr_device_info = DeviceInfo( connections={(dr.CONNECTION_NETWORK_MAC, mac)}, manufacturer="Pentair", model=equipment_model, name=self.gateway_name, sw_version=self.gateway.version, ) @property def mac(self) -> str | None: """Mac address.""" assert self.coordinator.config_entry is not None return self.coordinator.config_entry.unique_id @property def config_data(self) -> dict[str | int, Any]: """Shortcut for config data.""" return self.gateway_data[SL_DATA.KEY_CONFIG] @property def gateway(self) -> ScreenLogicGateway: """Return the gateway.""" return self.coordinator.gateway @property def gateway_data(self) -> dict[str | int, Any]: """Return the gateway data.""" return self.gateway.get_data() @property def gateway_name(self) -> str: """Return the configured name of the gateway.""" return self.gateway.name async def _async_refresh(self) -> None: """Refresh the data from the gateway.""" await self.coordinator.async_refresh() # Second debounced refresh to catch any secondary # changes in the device await self.coordinator.async_request_refresh() async def _async_refresh_timed(self, now: datetime) -> None: """Refresh from a timed called.""" await self.coordinator.async_request_refresh() class ScreenLogicPushEntity(ScreenlogicEntity): """Base class for all ScreenLogic push entities.""" def __init__( self, coordinator: ScreenlogicDataUpdateCoordinator, data_key: str, message_code: CODE, enabled: bool = True, ) -> None: """Initialize the entity.""" super().__init__(coordinator, data_key, enabled) self._update_message_code = message_code self._last_update_success = True @callback def _async_data_updated(self) -> None: """Handle data updates.""" self._last_update_success = self.coordinator.last_update_success self.async_write_ha_state() async def async_added_to_hass(self) -> None: """When entity is added to hass.""" await super().async_added_to_hass() self.async_on_remove( await self.gateway.async_subscribe_client( self._async_data_updated, self._update_message_code ) ) @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" # For push entities, only take updates from the coordinator if availability changes. if self.coordinator.last_update_success != self._last_update_success: self._async_data_updated() class ScreenLogicCircuitEntity(ScreenLogicPushEntity): """Base class for all ScreenLogic switch and light entities.""" _attr_has_entity_name = True @property def name(self) -> str: """Get the name of the switch.""" return self.circuit["name"] @property def is_on(self) -> bool: """Get whether the switch is in on state.""" return self.circuit["value"] == ON_OFF.ON async def async_turn_on(self, **kwargs: Any) -> None: """Send the ON command.""" await self._async_set_circuit(ON_OFF.ON) async def async_turn_off(self, **kwargs: Any) -> None: """Send the OFF command.""" await self._async_set_circuit(ON_OFF.OFF) async def _async_set_circuit(self, circuit_value: int) -> None: if not await self.gateway.async_set_circuit(self._data_key, circuit_value): raise HomeAssistantError( f"Failed to set_circuit {self._data_key} {circuit_value}" ) _LOGGER.debug("Turn %s %s", self._data_key, circuit_value) @property def circuit(self) -> dict[str | int, Any]: """Shortcut to access the circuit.""" return self.gateway_data[SL_DATA.KEY_CIRCUITS][self._data_key]