From 2df49b416c272858b3d888f4391622ceaa8393c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 30 May 2023 10:23:14 +0200 Subject: [PATCH] Add WebServer sensors to Airzone Cloud (#93757) --- .../components/airzone_cloud/entity.py | 42 ++++++++++-- .../components/airzone_cloud/sensor.py | 67 +++++++++++++++++-- tests/components/airzone_cloud/test_sensor.py | 7 ++ 3 files changed, 108 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/airzone_cloud/entity.py b/homeassistant/components/airzone_cloud/entity.py index e2a3142f1f5..59f6aa14bf8 100644 --- a/homeassistant/components/airzone_cloud/entity.py +++ b/homeassistant/components/airzone_cloud/entity.py @@ -6,13 +6,16 @@ from typing import Any from aioairzone_cloud.const import ( AZD_AIDOOS, + AZD_FIRMWARE, AZD_NAME, AZD_SYSTEM_ID, AZD_WEBSERVER, + AZD_WEBSERVERS, AZD_ZONES, ) from homeassistant.config_entries import ConfigEntry +from homeassistant.helpers import device_registry as dr from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -44,10 +47,10 @@ class AirzoneAidooEntity(AirzoneEntity): self.aidoo_id = aidoo_id self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, f"{entry.unique_id}_{aidoo_id}")}, + identifiers={(DOMAIN, aidoo_id)}, manufacturer=MANUFACTURER, name=aidoo_data[AZD_NAME], - via_device=(DOMAIN, f"{entry.unique_id}_{aidoo_data[AZD_WEBSERVER]}"), + via_device=(DOMAIN, aidoo_data[AZD_WEBSERVER]), ) def get_airzone_value(self, key: str) -> Any: @@ -58,6 +61,37 @@ class AirzoneAidooEntity(AirzoneEntity): return value +class AirzoneWebServerEntity(AirzoneEntity): + """Define an Airzone Cloud WebServer entity.""" + + def __init__( + self, + coordinator: AirzoneUpdateCoordinator, + entry: ConfigEntry, + ws_id: str, + ws_data: dict[str, Any], + ) -> None: + """Initialize.""" + super().__init__(coordinator) + + self.ws_id = ws_id + + self._attr_device_info = DeviceInfo( + connections={(dr.CONNECTION_NETWORK_MAC, ws_id)}, + identifiers={(DOMAIN, ws_id)}, + manufacturer=MANUFACTURER, + name=f"WebServer {ws_id}", + sw_version=ws_data[AZD_FIRMWARE], + ) + + def get_airzone_value(self, key: str) -> Any: + """Return WebServer value by key.""" + value = None + if webserver := self.coordinator.data[AZD_WEBSERVERS].get(self.ws_id): + value = webserver.get(key) + return value + + class AirzoneZoneEntity(AirzoneEntity): """Define an Airzone Cloud Zone entity.""" @@ -75,10 +109,10 @@ class AirzoneZoneEntity(AirzoneEntity): self.zone_id = zone_id self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, f"{entry.unique_id}_{zone_id}")}, + identifiers={(DOMAIN, zone_id)}, manufacturer=MANUFACTURER, name=zone_data[AZD_NAME], - via_device=(DOMAIN, f"{entry.unique_id}_{self.system_id}"), + via_device=(DOMAIN, self.system_id), ) def get_airzone_value(self, key: str) -> Any: diff --git a/homeassistant/components/airzone_cloud/sensor.py b/homeassistant/components/airzone_cloud/sensor.py index faeb62576fd..ee162ef5fec 100644 --- a/homeassistant/components/airzone_cloud/sensor.py +++ b/homeassistant/components/airzone_cloud/sensor.py @@ -8,6 +8,8 @@ from aioairzone_cloud.const import ( AZD_HUMIDITY, AZD_NAME, AZD_TEMP, + AZD_WEBSERVERS, + AZD_WIFI_RSSI, AZD_ZONES, ) @@ -18,13 +20,23 @@ from homeassistant.components.sensor import ( SensorStateClass, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import PERCENTAGE, UnitOfTemperature +from homeassistant.const import ( + PERCENTAGE, + SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + EntityCategory, + UnitOfTemperature, +) from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN from .coordinator import AirzoneUpdateCoordinator -from .entity import AirzoneAidooEntity, AirzoneEntity, AirzoneZoneEntity +from .entity import ( + AirzoneAidooEntity, + AirzoneEntity, + AirzoneWebServerEntity, + AirzoneZoneEntity, +) AIDOO_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = ( SensorEntityDescription( @@ -36,6 +48,19 @@ AIDOO_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = ( ), ) +WEBSERVER_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = ( + SensorEntityDescription( + device_class=SensorDeviceClass.SIGNAL_STRENGTH, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + has_entity_name=True, + key=AZD_WIFI_RSSI, + name="RSSI", + native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + state_class=SensorStateClass.MEASUREMENT, + ), +) + ZONE_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = ( SensorEntityDescription( device_class=SensorDeviceClass.TEMPERATURE, @@ -76,6 +101,20 @@ async def async_setup_entry( ) ) + # WebServers + for ws_id, ws_data in coordinator.data.get(AZD_WEBSERVERS, {}).items(): + for description in WEBSERVER_SENSOR_TYPES: + if description.key in ws_data: + sensors.append( + AirzoneWebServerSensor( + coordinator, + description, + entry, + ws_id, + ws_data, + ) + ) + # Zones for zone_id, zone_data in coordinator.data.get(AZD_ZONES, {}).items(): for description in ZONE_SENSOR_TYPES: @@ -123,7 +162,27 @@ class AirzoneAidooSensor(AirzoneAidooEntity, AirzoneSensor): super().__init__(coordinator, entry, aidoo_id, aidoo_data) self._attr_name = f"{aidoo_data[AZD_NAME]} {description.name}" - self._attr_unique_id = f"{entry.unique_id}_{aidoo_id}_{description.key}" + self._attr_unique_id = f"{aidoo_id}_{description.key}" + self.entity_description = description + + self._async_update_attrs() + + +class AirzoneWebServerSensor(AirzoneWebServerEntity, AirzoneSensor): + """Define an Airzone Cloud WebServer sensor.""" + + def __init__( + self, + coordinator: AirzoneUpdateCoordinator, + description: SensorEntityDescription, + entry: ConfigEntry, + ws_id: str, + ws_data: dict[str, Any], + ) -> None: + """Initialize.""" + super().__init__(coordinator, entry, ws_id, ws_data) + + self._attr_unique_id = f"{ws_id}_{description.key}" self.entity_description = description self._async_update_attrs() @@ -144,7 +203,7 @@ class AirzoneZoneSensor(AirzoneZoneEntity, AirzoneSensor): super().__init__(coordinator, entry, zone_id, zone_data) self._attr_name = f"{zone_data[AZD_NAME]} {description.name}" - self._attr_unique_id = f"{entry.unique_id}_{zone_id}_{description.key}" + self._attr_unique_id = f"{zone_id}_{description.key}" self.entity_description = description self._async_update_attrs() diff --git a/tests/components/airzone_cloud/test_sensor.py b/tests/components/airzone_cloud/test_sensor.py index 9de134d718b..41807fac78b 100644 --- a/tests/components/airzone_cloud/test_sensor.py +++ b/tests/components/airzone_cloud/test_sensor.py @@ -16,6 +16,13 @@ async def test_airzone_create_sensors( state = hass.states.get("sensor.bron_temperature") assert state.state == "21.0" + # WebServers + state = hass.states.get("sensor.webserver_11_22_33_44_55_66_rssi") + assert state.state == "-56" + + state = hass.states.get("sensor.webserver_11_22_33_44_55_67_rssi") + assert state.state == "-77" + # Zones state = hass.states.get("sensor.dormitorio_temperature") assert state.state == "25.0"