From 42a5e2d4fe8ab9b4bca46074a45a759c47020c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sun, 27 Mar 2022 22:39:46 +0200 Subject: [PATCH] Add Airzone binary sensor platform (#68140) Co-authored-by: J. Nick Koston --- homeassistant/components/airzone/__init__.py | 2 +- .../components/airzone/binary_sensor.py | 114 ++++++++++++++++++ .../components/airzone/test_binary_sensor.py | 56 +++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/airzone/binary_sensor.py create mode 100644 tests/components/airzone/test_binary_sensor.py diff --git a/homeassistant/components/airzone/__init__.py b/homeassistant/components/airzone/__init__.py index 5d5350d7a29..0555b888fd8 100644 --- a/homeassistant/components/airzone/__init__.py +++ b/homeassistant/components/airzone/__init__.py @@ -17,7 +17,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import DOMAIN, MANUFACTURER from .coordinator import AirzoneUpdateCoordinator -PLATFORMS: list[Platform] = [Platform.CLIMATE, Platform.SENSOR] +PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR] class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]): diff --git a/homeassistant/components/airzone/binary_sensor.py b/homeassistant/components/airzone/binary_sensor.py new file mode 100644 index 00000000000..1d0c76906e8 --- /dev/null +++ b/homeassistant/components/airzone/binary_sensor.py @@ -0,0 +1,114 @@ +"""Support for the Airzone sensors.""" +from __future__ import annotations + +from collections.abc import Mapping +from dataclasses import dataclass +from typing import Any, Final + +from aioairzone.const import ( + AZD_AIR_DEMAND, + AZD_ERRORS, + AZD_FLOOR_DEMAND, + AZD_NAME, + AZD_PROBLEMS, + AZD_ZONES, +) + +from homeassistant.components.binary_sensor import ( + DEVICE_CLASS_PROBLEM, + DEVICE_CLASS_RUNNING, + BinarySensorEntity, + BinarySensorEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import AirzoneEntity +from .const import DOMAIN +from .coordinator import AirzoneUpdateCoordinator + + +@dataclass +class AirzoneBinarySensorEntityDescription(BinarySensorEntityDescription): + """A class that describes airzone binary sensor entities.""" + + attributes: dict[str, str] | None = None + + +BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = ( + AirzoneBinarySensorEntityDescription( + device_class=DEVICE_CLASS_RUNNING, + key=AZD_AIR_DEMAND, + name="Air Demand", + ), + AirzoneBinarySensorEntityDescription( + device_class=DEVICE_CLASS_RUNNING, + key=AZD_FLOOR_DEMAND, + name="Floor Demand", + ), + AirzoneBinarySensorEntityDescription( + attributes={ + "errors": AZD_ERRORS, + }, + device_class=DEVICE_CLASS_PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + key=AZD_PROBLEMS, + name="Problem", + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Add Airzone binary sensors from a config_entry.""" + coordinator = hass.data[DOMAIN][entry.entry_id] + + binary_sensors = [] + for system_zone_id, zone_data in coordinator.data[AZD_ZONES].items(): + for description in BINARY_SENSOR_TYPES: + if description.key in zone_data: + binary_sensors.append( + AirzoneBinarySensor( + coordinator, + description, + entry, + system_zone_id, + zone_data, + ) + ) + + async_add_entities(binary_sensors) + + +class AirzoneBinarySensor(AirzoneEntity, BinarySensorEntity): + """Define an Airzone sensor.""" + + def __init__( + self, + coordinator: AirzoneUpdateCoordinator, + description: AirzoneBinarySensorEntityDescription, + entry: ConfigEntry, + system_zone_id: str, + zone_data: dict[str, Any], + ) -> None: + """Initialize.""" + 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/tests/components/airzone/test_binary_sensor.py b/tests/components/airzone/test_binary_sensor.py new file mode 100644 index 00000000000..ee3a8324ea4 --- /dev/null +++ b/tests/components/airzone/test_binary_sensor.py @@ -0,0 +1,56 @@ +"""The sensor tests for the Airzone platform.""" + +from homeassistant.const import STATE_OFF, STATE_ON + +from .util import async_init_integration + + +async def test_airzone_create_binary_sensors(hass): + """Test creation of binary sensors.""" + + await async_init_integration(hass) + + state = hass.states.get("binary_sensor.despacho_air_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.despacho_floor_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.despacho_problem") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_1_air_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_1_floor_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_1_problem") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_2_air_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_2_floor_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_2_problem") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_ppal_air_demand") + assert state.state == STATE_ON + + state = hass.states.get("binary_sensor.dorm_ppal_floor_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.dorm_ppal_problem") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.salon_air_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.salon_floor_demand") + assert state.state == STATE_OFF + + state = hass.states.get("binary_sensor.salon_problem") + assert state.state == STATE_OFF