mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Code Quality improvements for Advantage Air integration (#41861)
* Readability improvements * Code quality and more tests * Created a parent entity * Apply parent entity to cover platform * Update _zone property Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Remove device_state_attributes * Correct attribute tests Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
1e0663e986
commit
731d617c5e
@ -8,7 +8,11 @@ from advantage_air import ApiError, advantage_air
|
||||
from homeassistant.const import CONF_IP_ADDRESS, CONF_PORT
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
UpdateFailed,
|
||||
)
|
||||
|
||||
from .const import ADVANTAGE_AIR_RETRY, DOMAIN
|
||||
|
||||
@ -72,3 +76,35 @@ async def async_setup_entry(hass, config_entry):
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class AdvantageAirEntity(CoordinatorEntity):
|
||||
"""Parent class for Advantage Air Entities."""
|
||||
|
||||
def __init__(self, instance, ac_key, zone_key=None):
|
||||
"""Initialize common aspects of an Advantage Air sensor."""
|
||||
super().__init__(instance["coordinator"])
|
||||
self.async_change = instance["async_change"]
|
||||
self.ac_key = ac_key
|
||||
self.zone_key = zone_key
|
||||
|
||||
@property
|
||||
def _ac(self):
|
||||
return self.coordinator.data["aircons"][self.ac_key]["info"]
|
||||
|
||||
@property
|
||||
def _zone(self):
|
||||
if not self.zone_key:
|
||||
return None
|
||||
return self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key]
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return parent device information."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self.coordinator.data["system"]["rid"])},
|
||||
"name": self.coordinator.data["system"]["name"],
|
||||
"manufacturer": "Advantage Air",
|
||||
"model": self.coordinator.data["system"]["sysType"],
|
||||
"sw_version": self.coordinator.data["system"]["myAppRev"],
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
"""Climate platform for Advantage Air integration."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.advantage_air import AdvantageAirEntity
|
||||
from homeassistant.components.climate import ClimateEntity
|
||||
from homeassistant.components.climate.const import (
|
||||
FAN_AUTO,
|
||||
FAN_HIGH,
|
||||
FAN_LOW,
|
||||
FAN_MEDIUM,
|
||||
FAN_OFF,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_DRY,
|
||||
HVAC_MODE_FAN_ONLY,
|
||||
@ -17,7 +16,6 @@ from homeassistant.components.climate.const import (
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
)
|
||||
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, TEMP_CELSIUS
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import (
|
||||
ADVANTAGE_AIR_STATE_CLOSE,
|
||||
@ -53,8 +51,6 @@ AC_HVAC_MODES = [
|
||||
]
|
||||
ZONE_HVAC_MODES = [HVAC_MODE_OFF, HVAC_MODE_FAN_ONLY]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up AdvantageAir climate platform."""
|
||||
@ -62,28 +58,18 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
instance = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
entities = []
|
||||
for ac_key in instance["coordinator"].data["aircons"]:
|
||||
for ac_key, ac_device in instance["coordinator"].data["aircons"].items():
|
||||
entities.append(AdvantageAirAC(instance, ac_key))
|
||||
for zone_key in instance["coordinator"].data["aircons"][ac_key]["zones"]:
|
||||
for zone_key, zone in ac_device["zones"].items():
|
||||
# Only add zone climate control when zone is in temperature control
|
||||
if (
|
||||
instance["coordinator"].data["aircons"][ac_key]["zones"][zone_key][
|
||||
"type"
|
||||
]
|
||||
!= 0
|
||||
):
|
||||
if zone["type"] != 0:
|
||||
entities.append(AdvantageAirZone(instance, ac_key, zone_key))
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class AdvantageAirClimateEntity(CoordinatorEntity, ClimateEntity):
|
||||
class AdvantageAirClimateEntity(AdvantageAirEntity, ClimateEntity):
|
||||
"""AdvantageAir Climate class."""
|
||||
|
||||
def __init__(self, instance):
|
||||
"""Initialize the base Advantage Air climate entity."""
|
||||
super().__init__(instance["coordinator"])
|
||||
self.async_change = instance["async_change"]
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the temperature unit."""
|
||||
@ -104,30 +90,14 @@ class AdvantageAirClimateEntity(CoordinatorEntity, ClimateEntity):
|
||||
"""Return the minimum supported temperature."""
|
||||
return 16
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return parent device information."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self.coordinator.data["system"]["rid"])},
|
||||
"name": self.coordinator.data["system"]["name"],
|
||||
"manufacturer": "Advantage Air",
|
||||
"model": self.coordinator.data["system"]["sysType"],
|
||||
"sw_version": self.coordinator.data["system"]["myAppRev"],
|
||||
}
|
||||
|
||||
|
||||
class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
"""AdvantageAir AC unit."""
|
||||
|
||||
def __init__(self, instance, ac_key):
|
||||
"""Initialize the Advantage Air AC climate entity."""
|
||||
super().__init__(instance)
|
||||
self.ac_key = ac_key
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
return self.coordinator.data["aircons"][self.ac_key]["info"]["name"]
|
||||
return self._ac["name"]
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
@ -137,18 +107,13 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
@property
|
||||
def target_temperature(self):
|
||||
"""Return the current target temperature."""
|
||||
return self.coordinator.data["aircons"][self.ac_key]["info"]["setTemp"]
|
||||
return self._ac["setTemp"]
|
||||
|
||||
@property
|
||||
def hvac_mode(self):
|
||||
"""Return the current HVAC modes."""
|
||||
if (
|
||||
self.coordinator.data["aircons"][self.ac_key]["info"]["state"]
|
||||
== ADVANTAGE_AIR_STATE_ON
|
||||
):
|
||||
return ADVANTAGE_AIR_HVAC_MODES.get(
|
||||
self.coordinator.data["aircons"][self.ac_key]["info"]["mode"]
|
||||
)
|
||||
if self._ac["state"] == ADVANTAGE_AIR_STATE_ON:
|
||||
return ADVANTAGE_AIR_HVAC_MODES.get(self._ac["mode"])
|
||||
return HVAC_MODE_OFF
|
||||
|
||||
@property
|
||||
@ -159,9 +124,7 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
@property
|
||||
def fan_mode(self):
|
||||
"""Return the current fan modes."""
|
||||
return ADVANTAGE_AIR_FAN_MODES.get(
|
||||
self.coordinator.data["aircons"][self.ac_key]["info"]["fan"], FAN_OFF
|
||||
)
|
||||
return ADVANTAGE_AIR_FAN_MODES.get(self._ac["fan"])
|
||||
|
||||
@property
|
||||
def fan_modes(self):
|
||||
@ -173,11 +136,6 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
"""Return the supported features."""
|
||||
return SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return additional attributes about AC unit."""
|
||||
return self.coordinator.data["aircons"][self.ac_key]["info"]
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode):
|
||||
"""Set the HVAC Mode and State."""
|
||||
if hvac_mode == HVAC_MODE_OFF:
|
||||
@ -211,18 +169,10 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
class AdvantageAirZone(AdvantageAirClimateEntity):
|
||||
"""AdvantageAir Zone control."""
|
||||
|
||||
def __init__(self, instance, ac_key, zone_key):
|
||||
"""Initialize the Advantage Air Zone climate entity."""
|
||||
super().__init__(instance)
|
||||
self.ac_key = ac_key
|
||||
self.zone_key = zone_key
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
return self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key][
|
||||
"name"
|
||||
]
|
||||
return self._zone["name"]
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
@ -232,26 +182,17 @@ class AdvantageAirZone(AdvantageAirClimateEntity):
|
||||
@property
|
||||
def current_temperature(self):
|
||||
"""Return the current temperature."""
|
||||
return self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key][
|
||||
"measuredTemp"
|
||||
]
|
||||
return self._zone["measuredTemp"]
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
"""Return the target temperature."""
|
||||
return self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key][
|
||||
"setTemp"
|
||||
]
|
||||
return self._zone["setTemp"]
|
||||
|
||||
@property
|
||||
def hvac_mode(self):
|
||||
"""Return the current HVAC modes."""
|
||||
if (
|
||||
self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key][
|
||||
"state"
|
||||
]
|
||||
== ADVANTAGE_AIR_STATE_OPEN
|
||||
):
|
||||
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
||||
return HVAC_MODE_FAN_ONLY
|
||||
return HVAC_MODE_OFF
|
||||
|
||||
@ -260,11 +201,6 @@ class AdvantageAirZone(AdvantageAirClimateEntity):
|
||||
"""Return supported HVAC modes."""
|
||||
return ZONE_HVAC_MODES
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return additional attributes about Zone."""
|
||||
return self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key]
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Return the supported features."""
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""Cover platform for Advantage Air integration."""
|
||||
|
||||
from homeassistant.components.advantage_air import AdvantageAirEntity
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
DEVICE_CLASS_DAMPER,
|
||||
@ -8,7 +9,6 @@ from homeassistant.components.cover import (
|
||||
SUPPORT_SET_POSITION,
|
||||
CoverEntity,
|
||||
)
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import ADVANTAGE_AIR_STATE_CLOSE, ADVANTAGE_AIR_STATE_OPEN, DOMAIN
|
||||
|
||||
@ -27,20 +27,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class AdvantageAirZoneVent(CoordinatorEntity, CoverEntity):
|
||||
class AdvantageAirZoneVent(AdvantageAirEntity, CoverEntity):
|
||||
"""Advantage Air Cover Class."""
|
||||
|
||||
def __init__(self, instance, ac_key, zone_key):
|
||||
"""Initialize the Advantage Air Zone Vent cover entity."""
|
||||
super().__init__(instance["coordinator"])
|
||||
self.async_change = instance["async_change"]
|
||||
self.ac_key = ac_key
|
||||
self.zone_key = zone_key
|
||||
|
||||
@property
|
||||
def _zone(self):
|
||||
return self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
@ -73,17 +62,6 @@ class AdvantageAirZoneVent(CoordinatorEntity, CoverEntity):
|
||||
return self._zone["value"]
|
||||
return 0
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return parent device information."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self.coordinator.data["system"]["rid"])},
|
||||
"name": self.coordinator.data["system"]["name"],
|
||||
"manufacturer": "Advantage Air",
|
||||
"model": self.coordinator.data["system"]["sysType"],
|
||||
"sw_version": self.coordinator.data["system"]["myAppRev"],
|
||||
}
|
||||
|
||||
async def async_open_cover(self, **kwargs):
|
||||
"""Fully open zone vent."""
|
||||
await self.async_change(
|
||||
|
@ -1,10 +1,20 @@
|
||||
"""Test the Advantage Air Climate Platform."""
|
||||
|
||||
from json import loads
|
||||
|
||||
from homeassistant.components.advantage_air.climate import (
|
||||
HASS_FAN_MODES,
|
||||
HASS_HVAC_MODES,
|
||||
)
|
||||
from homeassistant.components.advantage_air.const import (
|
||||
ADVANTAGE_AIR_STATE_OFF,
|
||||
ADVANTAGE_AIR_STATE_ON,
|
||||
)
|
||||
from homeassistant.components.climate.const import (
|
||||
ATTR_FAN_MODE,
|
||||
ATTR_HVAC_MODE,
|
||||
DOMAIN as CLIMATE_DOMAIN,
|
||||
FAN_OFF,
|
||||
FAN_LOW,
|
||||
HVAC_MODE_FAN_ONLY,
|
||||
HVAC_MODE_OFF,
|
||||
SERVICE_SET_FAN_MODE,
|
||||
@ -46,6 +56,7 @@ async def test_climate_async_setup_entry(hass, aioclient_mock):
|
||||
assert state.state == HVAC_MODE_FAN_ONLY
|
||||
assert state.attributes.get("min_temp") == 16
|
||||
assert state.attributes.get("max_temp") == 32
|
||||
assert state.attributes.get("temperature") == 24
|
||||
assert state.attributes.get("current_temperature") is None
|
||||
|
||||
entry = registry.async_get(entity_id)
|
||||
@ -61,6 +72,9 @@ async def test_climate_async_setup_entry(hass, aioclient_mock):
|
||||
assert len(aioclient_mock.mock_calls) == 3
|
||||
assert aioclient_mock.mock_calls[-2][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-2][1].path == "/setAircon"
|
||||
data = loads(aioclient_mock.mock_calls[-2][1].query["json"])
|
||||
assert data["ac1"]["info"]["state"] == ADVANTAGE_AIR_STATE_ON
|
||||
assert data["ac1"]["info"]["mode"] == HASS_HVAC_MODES[HVAC_MODE_FAN_ONLY]
|
||||
assert aioclient_mock.mock_calls[-1][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
|
||||
|
||||
@ -73,18 +87,22 @@ async def test_climate_async_setup_entry(hass, aioclient_mock):
|
||||
assert len(aioclient_mock.mock_calls) == 5
|
||||
assert aioclient_mock.mock_calls[-2][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-2][1].path == "/setAircon"
|
||||
data = loads(aioclient_mock.mock_calls[-2][1].query["json"])
|
||||
assert data["ac1"]["info"]["state"] == ADVANTAGE_AIR_STATE_OFF
|
||||
assert aioclient_mock.mock_calls[-1][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
|
||||
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_FAN_MODE,
|
||||
{ATTR_ENTITY_ID: [entity_id], ATTR_FAN_MODE: FAN_OFF},
|
||||
{ATTR_ENTITY_ID: [entity_id], ATTR_FAN_MODE: FAN_LOW},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(aioclient_mock.mock_calls) == 7
|
||||
assert aioclient_mock.mock_calls[-2][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-2][1].path == "/setAircon"
|
||||
data = loads(aioclient_mock.mock_calls[-2][1].query["json"])
|
||||
assert data["ac1"]["info"]["fan"] == HASS_FAN_MODES[FAN_LOW]
|
||||
assert aioclient_mock.mock_calls[-1][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
|
||||
|
||||
@ -97,6 +115,8 @@ async def test_climate_async_setup_entry(hass, aioclient_mock):
|
||||
assert len(aioclient_mock.mock_calls) == 9
|
||||
assert aioclient_mock.mock_calls[-2][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-2][1].path == "/setAircon"
|
||||
data = loads(aioclient_mock.mock_calls[-2][1].query["json"])
|
||||
assert data["ac1"]["info"]["setTemp"] == 25
|
||||
assert aioclient_mock.mock_calls[-1][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
|
||||
|
||||
@ -106,8 +126,8 @@ async def test_climate_async_setup_entry(hass, aioclient_mock):
|
||||
assert state
|
||||
assert state.attributes.get("min_temp") == 16
|
||||
assert state.attributes.get("max_temp") == 32
|
||||
assert state.attributes.get("measuredTemp") == 25
|
||||
assert state.attributes.get("setTemp") == 24
|
||||
assert state.attributes.get("temperature") == 24
|
||||
assert state.attributes.get("current_temperature") == 25
|
||||
|
||||
entry = registry.async_get(entity_id)
|
||||
assert entry
|
||||
|
Loading…
x
Reference in New Issue
Block a user