Add Sensors for Airzone WebServer (#69748)
parent
4ea6e5dfc0
commit
e8a8d35289
|
@ -7,16 +7,19 @@ from aioairzone.const import (
|
|||
AZD_FIRMWARE,
|
||||
AZD_FULL_NAME,
|
||||
AZD_ID,
|
||||
AZD_MAC,
|
||||
AZD_MODEL,
|
||||
AZD_NAME,
|
||||
AZD_SYSTEM,
|
||||
AZD_SYSTEMS,
|
||||
AZD_THERMOSTAT_FW,
|
||||
AZD_THERMOSTAT_MODEL,
|
||||
AZD_WEBSERVER,
|
||||
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
|
||||
|
||||
|
@ -46,17 +49,15 @@ class AirzoneSystemEntity(AirzoneEntity):
|
|||
|
||||
self.system_id = system_data[AZD_ID]
|
||||
|
||||
self._attr_device_info: DeviceInfo = {
|
||||
"identifiers": {(DOMAIN, f"{entry.entry_id}_{self.system_id}")},
|
||||
"manufacturer": MANUFACTURER,
|
||||
"model": self.get_airzone_value(AZD_MODEL),
|
||||
"name": self.get_airzone_value(AZD_FULL_NAME),
|
||||
"sw_version": self.get_airzone_value(AZD_FIRMWARE),
|
||||
"via_device": (DOMAIN, f"{entry.entry_id}_ws"),
|
||||
}
|
||||
self._attr_unique_id = (
|
||||
entry.entry_id if entry.unique_id is None else entry.unique_id
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, f"{entry.entry_id}_{self.system_id}")},
|
||||
manufacturer=MANUFACTURER,
|
||||
model=self.get_airzone_value(AZD_MODEL),
|
||||
name=self.get_airzone_value(AZD_FULL_NAME),
|
||||
sw_version=self.get_airzone_value(AZD_FIRMWARE),
|
||||
via_device=(DOMAIN, f"{entry.entry_id}_ws"),
|
||||
)
|
||||
self._attr_unique_id = entry.unique_id or entry.entry_id
|
||||
|
||||
def get_airzone_value(self, key: str) -> Any:
|
||||
"""Return system value by key."""
|
||||
|
@ -67,6 +68,34 @@ class AirzoneSystemEntity(AirzoneEntity):
|
|||
return value
|
||||
|
||||
|
||||
class AirzoneWebServerEntity(AirzoneEntity):
|
||||
"""Define an Airzone WebServer entity."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: AirzoneUpdateCoordinator,
|
||||
entry: ConfigEntry,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator)
|
||||
|
||||
mac = self.get_airzone_value(AZD_MAC)
|
||||
|
||||
self._attr_device_info = DeviceInfo(
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, mac)},
|
||||
identifiers={(DOMAIN, f"{entry.entry_id}_ws")},
|
||||
manufacturer=MANUFACTURER,
|
||||
model=self.get_airzone_value(AZD_MODEL),
|
||||
name=self.get_airzone_value(AZD_FULL_NAME),
|
||||
sw_version=self.get_airzone_value(AZD_FIRMWARE),
|
||||
)
|
||||
self._attr_unique_id = entry.unique_id or entry.entry_id
|
||||
|
||||
def get_airzone_value(self, key: str) -> Any:
|
||||
"""Return system value by key."""
|
||||
return self.coordinator.data[AZD_WEBSERVER].get(key)
|
||||
|
||||
|
||||
class AirzoneZoneEntity(AirzoneEntity):
|
||||
"""Define an Airzone Zone entity."""
|
||||
|
||||
|
@ -84,17 +113,15 @@ class AirzoneZoneEntity(AirzoneEntity):
|
|||
self.system_zone_id = system_zone_id
|
||||
self.zone_id = zone_data[AZD_ID]
|
||||
|
||||
self._attr_device_info: DeviceInfo = {
|
||||
"identifiers": {(DOMAIN, f"{entry.entry_id}_{system_zone_id}")},
|
||||
"manufacturer": MANUFACTURER,
|
||||
"model": self.get_airzone_value(AZD_THERMOSTAT_MODEL),
|
||||
"name": f"Airzone [{system_zone_id}] {zone_data[AZD_NAME]}",
|
||||
"sw_version": self.get_airzone_value(AZD_THERMOSTAT_FW),
|
||||
"via_device": (DOMAIN, f"{entry.entry_id}_{self.system_id}"),
|
||||
}
|
||||
self._attr_unique_id = (
|
||||
entry.entry_id if entry.unique_id is None else entry.unique_id
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, f"{entry.entry_id}_{system_zone_id}")},
|
||||
manufacturer=MANUFACTURER,
|
||||
model=self.get_airzone_value(AZD_THERMOSTAT_MODEL),
|
||||
name=f"Airzone [{system_zone_id}] {zone_data[AZD_NAME]}",
|
||||
sw_version=self.get_airzone_value(AZD_THERMOSTAT_FW),
|
||||
via_device=(DOMAIN, f"{entry.entry_id}_{self.system_id}"),
|
||||
)
|
||||
self._attr_unique_id = entry.unique_id or entry.entry_id
|
||||
|
||||
def get_airzone_value(self, key: str) -> Any:
|
||||
"""Return zone value by key."""
|
||||
|
|
|
@ -3,7 +3,15 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any, Final
|
||||
|
||||
from aioairzone.const import AZD_HUMIDITY, AZD_NAME, AZD_TEMP, AZD_TEMP_UNIT, AZD_ZONES
|
||||
from aioairzone.const import (
|
||||
AZD_HUMIDITY,
|
||||
AZD_NAME,
|
||||
AZD_TEMP,
|
||||
AZD_TEMP_UNIT,
|
||||
AZD_WEBSERVER,
|
||||
AZD_WIFI_RSSI,
|
||||
AZD_ZONES,
|
||||
)
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
|
@ -12,13 +20,30 @@ from homeassistant.components.sensor import (
|
|||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
||||
from homeassistant.const import (
|
||||
PERCENTAGE,
|
||||
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN, TEMP_UNIT_LIB_TO_HASS
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneEntity, AirzoneZoneEntity
|
||||
from .entity import AirzoneEntity, AirzoneWebServerEntity, AirzoneZoneEntity
|
||||
|
||||
WEBSERVER_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
|
||||
SensorEntityDescription(
|
||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
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(
|
||||
|
@ -45,6 +70,19 @@ async def async_setup_entry(
|
|||
coordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
sensors: list[AirzoneSensor] = []
|
||||
|
||||
if AZD_WEBSERVER in coordinator.data:
|
||||
ws_data = coordinator.data[AZD_WEBSERVER]
|
||||
for description in WEBSERVER_SENSOR_TYPES:
|
||||
if description.key in ws_data:
|
||||
sensors.append(
|
||||
AirzoneWebServerSensor(
|
||||
coordinator,
|
||||
description,
|
||||
entry,
|
||||
)
|
||||
)
|
||||
|
||||
for system_zone_id, zone_data in coordinator.data[AZD_ZONES].items():
|
||||
for description in ZONE_SENSOR_TYPES:
|
||||
if description.key in zone_data:
|
||||
|
@ -70,6 +108,23 @@ class AirzoneSensor(AirzoneEntity, SensorEntity):
|
|||
self._attr_native_value = self.get_airzone_value(self.entity_description.key)
|
||||
|
||||
|
||||
class AirzoneWebServerSensor(AirzoneWebServerEntity, AirzoneSensor):
|
||||
"""Define an Airzone WebServer sensor."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: AirzoneUpdateCoordinator,
|
||||
description: SensorEntityDescription,
|
||||
entry: ConfigEntry,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator, entry)
|
||||
self._attr_name = f"WebServer {description.name}"
|
||||
self._attr_unique_id = f"{self._attr_unique_id}_ws_{description.key}"
|
||||
self.entity_description = description
|
||||
self._async_update_attrs()
|
||||
|
||||
|
||||
class AirzoneZoneSensor(AirzoneZoneEntity, AirzoneSensor):
|
||||
"""Define an Airzone Zone sensor."""
|
||||
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
"""The sensor tests for the Airzone platform."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .util import async_init_integration
|
||||
|
||||
|
||||
async def test_airzone_create_sensors(hass: HomeAssistant) -> None:
|
||||
async def test_airzone_create_sensors(
|
||||
hass: HomeAssistant, entity_registry_enabled_by_default: AsyncMock
|
||||
) -> None:
|
||||
"""Test creation of sensors."""
|
||||
|
||||
await async_init_integration(hass)
|
||||
|
||||
# WebServer
|
||||
state = hass.states.get("sensor.webserver_rssi")
|
||||
assert state.state == "-42"
|
||||
|
||||
# Zones
|
||||
state = hass.states.get("sensor.despacho_temperature")
|
||||
assert state.state == "21.2"
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ from aioairzone.const import (
|
|||
API_WIFI_RSSI,
|
||||
API_ZONE_ID,
|
||||
)
|
||||
from aioairzone.exceptions import InvalidMethod
|
||||
|
||||
from homeassistant.components.airzone import DOMAIN
|
||||
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT
|
||||
|
@ -219,7 +218,7 @@ async def async_init_integration(
|
|||
return_value=HVAC_SYSTEMS_MOCK,
|
||||
), patch(
|
||||
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
|
||||
side_effect=InvalidMethod,
|
||||
return_value=HVAC_WEBSERVER_MOCK,
|
||||
):
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
|
Loading…
Reference in New Issue