diff --git a/homeassistant/components/airzone/__init__.py b/homeassistant/components/airzone/__init__.py index 77c9445385a..1fd159be9bd 100644 --- a/homeassistant/components/airzone/__init__.py +++ b/homeassistant/components/airzone/__init__.py @@ -30,6 +30,14 @@ PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform. class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]): """Define an Airzone entity.""" + def get_airzone_value(self, key) -> Any: + """Return Airzone entity value by key.""" + raise NotImplementedError() + + +class AirzoneZoneEntity(AirzoneEntity): + """Define an Airzone Zone entity.""" + def __init__( self, coordinator: AirzoneUpdateCoordinator, @@ -47,12 +55,12 @@ class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]): self._attr_device_info: DeviceInfo = { "identifiers": {(DOMAIN, f"{entry.entry_id}_{system_zone_id}")}, "manufacturer": MANUFACTURER, - "model": self.get_zone_value(AZD_THERMOSTAT_MODEL), + "model": self.get_airzone_value(AZD_THERMOSTAT_MODEL), "name": f"Airzone [{system_zone_id}] {zone_data[AZD_NAME]}", - "sw_version": self.get_zone_value(AZD_THERMOSTAT_FW), + "sw_version": self.get_airzone_value(AZD_THERMOSTAT_FW), } - def get_zone_value(self, key): + def get_airzone_value(self, key) -> Any: """Return zone value by key.""" value = None if self.system_zone_id in self.coordinator.data[AZD_ZONES]: diff --git a/homeassistant/components/airzone/binary_sensor.py b/homeassistant/components/airzone/binary_sensor.py index 79877d1cbbd..e0f4027e951 100644 --- a/homeassistant/components/airzone/binary_sensor.py +++ b/homeassistant/components/airzone/binary_sensor.py @@ -24,7 +24,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AirzoneEntity +from . import AirzoneEntity, AirzoneZoneEntity from .const import DOMAIN from .coordinator import AirzoneUpdateCoordinator @@ -36,7 +36,7 @@ class AirzoneBinarySensorEntityDescription(BinarySensorEntityDescription): attributes: dict[str, str] | None = None -BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = ( +ZONE_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = ( AirzoneBinarySensorEntityDescription( device_class=BinarySensorDeviceClass.RUNNING, key=AZD_AIR_DEMAND, @@ -65,12 +65,12 @@ async def async_setup_entry( """Add Airzone binary sensors from a config_entry.""" coordinator = hass.data[DOMAIN][entry.entry_id] - binary_sensors = [] + binary_sensors: list[AirzoneBinarySensor] = [] for system_zone_id, zone_data in coordinator.data[AZD_ZONES].items(): - for description in BINARY_SENSOR_TYPES: + for description in ZONE_BINARY_SENSOR_TYPES: if description.key in zone_data: binary_sensors.append( - AirzoneBinarySensor( + AirzoneZoneBinarySensor( coordinator, description, entry, @@ -83,7 +83,28 @@ async def async_setup_entry( class AirzoneBinarySensor(AirzoneEntity, BinarySensorEntity): - """Define an Airzone sensor.""" + """Define an Airzone binary sensor.""" + + entity_description: AirzoneBinarySensorEntityDescription + + @property + def extra_state_attributes(self) -> Mapping[str, Any] | None: + """Return state attributes.""" + if not self.entity_description.attributes: + return None + return { + key: self.get_airzone_value(val) + for key, val in self.entity_description.attributes.items() + } + + @property + def is_on(self) -> bool | None: + """Return true if the binary sensor is on.""" + return self.get_airzone_value(self.entity_description.key) + + +class AirzoneZoneBinarySensor(AirzoneZoneEntity, AirzoneBinarySensor): + """Define an Airzone Zone binary sensor.""" def __init__( self, @@ -97,17 +118,4 @@ class AirzoneBinarySensor(AirzoneEntity, BinarySensorEntity): super().__init__(coordinator, entry, system_zone_id, zone_data) self._attr_name = f"{zone_data[AZD_NAME]} {description.name}" self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}_{description.key}" - self.attributes = description.attributes self.entity_description = description - - @property - def extra_state_attributes(self) -> Mapping[str, Any] | None: - """Return state attributes.""" - if not self.attributes: - return None - return {key: self.get_zone_value(val) for key, val in self.attributes.items()} - - @property - def is_on(self) -> bool | None: - """Return true if the binary sensor is on.""" - return self.get_zone_value(self.entity_description.key) diff --git a/homeassistant/components/airzone/climate.py b/homeassistant/components/airzone/climate.py index ee28f61a20e..ae62e57ed72 100644 --- a/homeassistant/components/airzone/climate.py +++ b/homeassistant/components/airzone/climate.py @@ -49,7 +49,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AirzoneEntity +from . import AirzoneZoneEntity from .const import API_TEMPERATURE_STEP, DOMAIN, TEMP_UNIT_LIB_TO_HASS from .coordinator import AirzoneUpdateCoordinator @@ -97,7 +97,7 @@ async def async_setup_entry( ) -class AirzoneClimate(AirzoneEntity, ClimateEntity): +class AirzoneClimate(AirzoneZoneEntity, ClimateEntity): """Define an Airzone sensor.""" def __init__( @@ -113,13 +113,13 @@ class AirzoneClimate(AirzoneEntity, ClimateEntity): self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}" self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE self._attr_target_temperature_step = API_TEMPERATURE_STEP - self._attr_max_temp = self.get_zone_value(AZD_TEMP_MAX) - self._attr_min_temp = self.get_zone_value(AZD_TEMP_MIN) + self._attr_max_temp = self.get_airzone_value(AZD_TEMP_MAX) + self._attr_min_temp = self.get_airzone_value(AZD_TEMP_MIN) self._attr_temperature_unit = TEMP_UNIT_LIB_TO_HASS[ - self.get_zone_value(AZD_TEMP_UNIT) + self.get_airzone_value(AZD_TEMP_UNIT) ] self._attr_hvac_modes = [ - HVAC_MODE_LIB_TO_HASS[mode] for mode in self.get_zone_value(AZD_MODES) + HVAC_MODE_LIB_TO_HASS[mode] for mode in self.get_airzone_value(AZD_MODES) ] self._async_update_attrs() @@ -161,8 +161,8 @@ class AirzoneClimate(AirzoneEntity, ClimateEntity): params[API_ON] = 0 else: mode = HVAC_MODE_HASS_TO_LIB[hvac_mode] - if mode != self.get_zone_value(AZD_MODE): - if self.get_zone_value(AZD_MASTER): + if mode != self.get_airzone_value(AZD_MODE): + if self.get_airzone_value(AZD_MASTER): params[API_MODE] = mode else: raise HomeAssistantError( @@ -187,16 +187,16 @@ class AirzoneClimate(AirzoneEntity, ClimateEntity): @callback def _async_update_attrs(self) -> None: """Update climate attributes.""" - self._attr_current_temperature = self.get_zone_value(AZD_TEMP) - self._attr_current_humidity = self.get_zone_value(AZD_HUMIDITY) - if self.get_zone_value(AZD_ON): - mode = self.get_zone_value(AZD_MODE) + self._attr_current_temperature = self.get_airzone_value(AZD_TEMP) + self._attr_current_humidity = self.get_airzone_value(AZD_HUMIDITY) + if self.get_airzone_value(AZD_ON): + mode = self.get_airzone_value(AZD_MODE) self._attr_hvac_mode = HVAC_MODE_LIB_TO_HASS[mode] - if self.get_zone_value(AZD_DEMAND): + if self.get_airzone_value(AZD_DEMAND): self._attr_hvac_action = HVAC_ACTION_LIB_TO_HASS[mode] else: self._attr_hvac_action = CURRENT_HVAC_IDLE else: self._attr_hvac_action = CURRENT_HVAC_OFF self._attr_hvac_mode = HVAC_MODE_OFF - self._attr_target_temperature = self.get_zone_value(AZD_TEMP_SET) + self._attr_target_temperature = self.get_airzone_value(AZD_TEMP_SET) diff --git a/homeassistant/components/airzone/sensor.py b/homeassistant/components/airzone/sensor.py index b40f306bf02..9e6e886ccac 100644 --- a/homeassistant/components/airzone/sensor.py +++ b/homeassistant/components/airzone/sensor.py @@ -16,11 +16,11 @@ from homeassistant.const import PERCENTAGE, TEMP_CELSIUS from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import AirzoneEntity +from . import AirzoneEntity, AirzoneZoneEntity from .const import DOMAIN, TEMP_UNIT_LIB_TO_HASS from .coordinator import AirzoneUpdateCoordinator -SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = ( +ZONE_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = ( SensorEntityDescription( device_class=SensorDeviceClass.TEMPERATURE, key=AZD_TEMP, @@ -44,12 +44,12 @@ async def async_setup_entry( """Add Airzone sensors from a config_entry.""" coordinator = hass.data[DOMAIN][entry.entry_id] - sensors = [] + sensors: list[AirzoneSensor] = [] for system_zone_id, zone_data in coordinator.data[AZD_ZONES].items(): - for description in SENSOR_TYPES: + for description in ZONE_SENSOR_TYPES: if description.key in zone_data: sensors.append( - AirzoneSensor( + AirzoneZoneSensor( coordinator, description, entry, @@ -64,6 +64,15 @@ async def async_setup_entry( class AirzoneSensor(AirzoneEntity, SensorEntity): """Define an Airzone sensor.""" + @property + def native_value(self): + """Return the state.""" + return self.get_airzone_value(self.entity_description.key) + + +class AirzoneZoneSensor(AirzoneZoneEntity, AirzoneSensor): + """Define an Airzone Zone sensor.""" + def __init__( self, coordinator: AirzoneUpdateCoordinator, @@ -80,10 +89,5 @@ class AirzoneSensor(AirzoneEntity, SensorEntity): if description.key == AZD_TEMP: self._attr_native_unit_of_measurement = TEMP_UNIT_LIB_TO_HASS.get( - self.get_zone_value(AZD_TEMP_UNIT) + self.get_airzone_value(AZD_TEMP_UNIT) ) - - @property - def native_value(self): - """Return the state.""" - return self.get_zone_value(self.entity_description.key)