Skip to content

Commit

Permalink
airzone: add WebServer sensors
Browse files Browse the repository at this point in the history
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
  • Loading branch information
Noltari committed Apr 22, 2022
1 parent 5b5748b commit 84b60d9
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 5 deletions.
32 changes: 32 additions & 0 deletions homeassistant/components/airzone/__init__.py
Expand Up @@ -4,11 +4,14 @@
from typing import Any

from aioairzone.const import (
AZD_FIRMWARE,
AZD_ID,
AZD_MODEL,
AZD_NAME,
AZD_SYSTEM,
AZD_THERMOSTAT_FW,
AZD_THERMOSTAT_MODEL,
AZD_WEBSERVER,
AZD_ZONES,
DEFAULT_SYSTEM_ID,
)
Expand All @@ -35,6 +38,34 @@ def get_airzone_value(self, key) -> Any:
raise NotImplementedError()


class AirzoneWebServerEntity(AirzoneEntity):
"""Define an Airzone WebServer entity."""

def __init__(
self,
coordinator: AirzoneUpdateCoordinator,
entry: ConfigEntry,
) -> None:
"""Initialize."""
super().__init__(coordinator)

self._attr_device_info: DeviceInfo = {
"identifiers": {(DOMAIN, f"{entry.entry_id}_ws")},
"manufacturer": MANUFACTURER,
"model": self.get_airzone_value(AZD_MODEL),
"name": "Airzone WebServer",
"sw_version": self.get_airzone_value(AZD_FIRMWARE),
}

def get_airzone_value(self, key) -> Any:
"""Return system value by key."""
value = None
webserver = self.coordinator.data[AZD_WEBSERVER]
if key in webserver:
value = webserver[key]
return value


class AirzoneZoneEntity(AirzoneEntity):
"""Define an Airzone Zone entity."""

Expand All @@ -58,6 +89,7 @@ def __init__(
"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}"),
}

def get_airzone_value(self, key) -> Any:
Expand Down
59 changes: 56 additions & 3 deletions homeassistant/components/airzone/sensor.py
Expand Up @@ -3,7 +3,15 @@

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,
Expand All @@ -12,14 +20,30 @@
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
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import AirzoneEntity, AirzoneZoneEntity
from . import AirzoneEntity, AirzoneWebServerEntity, AirzoneZoneEntity
from .const import DOMAIN, TEMP_UNIT_LIB_TO_HASS
from .coordinator import AirzoneUpdateCoordinator

WEBSERVER_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
SensorEntityDescription(
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
entity_category=EntityCategory.DIAGNOSTIC,
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,
Expand All @@ -45,6 +69,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:
Expand All @@ -70,6 +107,22 @@ def native_value(self):
return 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"{entry.entry_id}_ws_{description.key}"
self.entity_description = description


class AirzoneZoneSensor(AirzoneZoneEntity, AirzoneSensor):
"""Define an Airzone Zone sensor."""

Expand Down
5 changes: 5 additions & 0 deletions tests/components/airzone/test_sensor.py
Expand Up @@ -10,6 +10,11 @@ async def test_airzone_create_sensors(hass: HomeAssistant) -> None:

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"

Expand Down
13 changes: 11 additions & 2 deletions tests/components/airzone/util.py
Expand Up @@ -12,6 +12,7 @@
API_HEAT_STAGE,
API_HEAT_STAGES,
API_HUMIDITY,
API_MAC,
API_MAX_TEMP,
API_MIN_TEMP,
API_MODE,
Expand All @@ -23,9 +24,11 @@
API_SYSTEM_ID,
API_SYSTEMS,
API_UNITS,
API_WIFI_CHANNEL,
API_WIFI_RSSI,
API_ZONE_ID,
)
from aioairzone.exceptions import InvalidMethod, SystemOutOfRange
from aioairzone.exceptions import SystemOutOfRange

from homeassistant.components.airzone import DOMAIN
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT
Expand Down Expand Up @@ -160,6 +163,12 @@
]
}

HVAC_WEBSERVER_MOCK = {
API_MAC: "DUMMY-MAC",
API_WIFI_CHANNEL: 6,
API_WIFI_RSSI: -42,
}


async def async_init_integration(
hass: HomeAssistant,
Expand All @@ -177,7 +186,7 @@ async def async_init_integration(
side_effect=SystemOutOfRange,
), patch(
"homeassistant.components.airzone.AirzoneLocalApi.get_webserver",
side_effect=InvalidMethod,
return_value=HVAC_WEBSERVER_MOCK,
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()

0 comments on commit 84b60d9

Please sign in to comment.