mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 17:27:52 +00:00
Bump Advantage Air to 0.4.4 (#91147)
This commit is contained in:
parent
263901841f
commit
8fe900885a
@ -7,7 +7,6 @@ from advantage_air import ApiError, advantage_air
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_IP_ADDRESS, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
@ -53,30 +52,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
update_interval=timedelta(seconds=ADVANTAGE_AIR_SYNC_INTERVAL),
|
||||
)
|
||||
|
||||
def error_handle_factory(func):
|
||||
"""Return the provided API function wrapped.
|
||||
|
||||
Adds an error handler and coordinator refresh.
|
||||
"""
|
||||
|
||||
async def error_handle(param):
|
||||
try:
|
||||
if await func(param):
|
||||
await coordinator.async_refresh()
|
||||
except ApiError as err:
|
||||
raise HomeAssistantError(err) from err
|
||||
|
||||
return error_handle
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN][entry.entry_id] = {
|
||||
"coordinator": coordinator,
|
||||
"aircon": error_handle_factory(api.aircon.async_set),
|
||||
"lights": error_handle_factory(api.lights.async_set),
|
||||
"things": error_handle_factory(api.things.async_set),
|
||||
}
|
||||
hass.data[DOMAIN][entry.entry_id] = {"coordinator": coordinator, "api": api}
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
|
@ -161,67 +161,41 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
|
||||
async def async_turn_on(self) -> None:
|
||||
"""Set the HVAC State to on."""
|
||||
await self.aircon(
|
||||
{
|
||||
self.ac_key: {
|
||||
"info": {
|
||||
"state": ADVANTAGE_AIR_STATE_ON,
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
await self.async_update_ac({"state": ADVANTAGE_AIR_STATE_ON})
|
||||
|
||||
async def async_turn_off(self) -> None:
|
||||
"""Set the HVAC State to off."""
|
||||
await self.aircon(
|
||||
await self.async_update_ac(
|
||||
{
|
||||
self.ac_key: {
|
||||
"info": {
|
||||
"state": ADVANTAGE_AIR_STATE_OFF,
|
||||
}
|
||||
}
|
||||
"state": ADVANTAGE_AIR_STATE_OFF,
|
||||
}
|
||||
)
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set the HVAC Mode and State."""
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
await self.aircon(
|
||||
{self.ac_key: {"info": {"state": ADVANTAGE_AIR_STATE_OFF}}}
|
||||
)
|
||||
await self.async_update_ac({"state": ADVANTAGE_AIR_STATE_OFF})
|
||||
else:
|
||||
await self.aircon(
|
||||
await self.async_update_ac(
|
||||
{
|
||||
self.ac_key: {
|
||||
"info": {
|
||||
"state": ADVANTAGE_AIR_STATE_ON,
|
||||
"mode": HASS_HVAC_MODES.get(hvac_mode),
|
||||
}
|
||||
}
|
||||
"state": ADVANTAGE_AIR_STATE_ON,
|
||||
"mode": HASS_HVAC_MODES.get(hvac_mode),
|
||||
}
|
||||
)
|
||||
|
||||
async def async_set_fan_mode(self, fan_mode: str) -> None:
|
||||
"""Set the Fan Mode."""
|
||||
await self.aircon(
|
||||
{self.ac_key: {"info": {"fan": HASS_FAN_MODES.get(fan_mode)}}}
|
||||
)
|
||||
await self.async_update_ac({"fan": HASS_FAN_MODES.get(fan_mode)})
|
||||
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set the Temperature."""
|
||||
if ATTR_TEMPERATURE in kwargs:
|
||||
await self.aircon(
|
||||
{self.ac_key: {"info": {"setTemp": kwargs[ATTR_TEMPERATURE]}}}
|
||||
)
|
||||
await self.async_update_ac({"setTemp": kwargs[ATTR_TEMPERATURE]})
|
||||
if ATTR_TARGET_TEMP_LOW in kwargs and ATTR_TARGET_TEMP_HIGH in kwargs:
|
||||
await self.aircon(
|
||||
await self.async_update_ac(
|
||||
{
|
||||
self.ac_key: {
|
||||
"info": {
|
||||
ADVANTAGE_AIR_COOL_TARGET: kwargs[ATTR_TARGET_TEMP_HIGH],
|
||||
ADVANTAGE_AIR_HEAT_TARGET: kwargs[ATTR_TARGET_TEMP_LOW],
|
||||
}
|
||||
}
|
||||
ADVANTAGE_AIR_COOL_TARGET: kwargs[ATTR_TARGET_TEMP_HIGH],
|
||||
ADVANTAGE_AIR_HEAT_TARGET: kwargs[ATTR_TARGET_TEMP_LOW],
|
||||
}
|
||||
)
|
||||
|
||||
@ -260,23 +234,11 @@ class AdvantageAirZone(AdvantageAirZoneEntity, ClimateEntity):
|
||||
|
||||
async def async_turn_on(self) -> None:
|
||||
"""Set the HVAC State to on."""
|
||||
await self.aircon(
|
||||
{
|
||||
self.ac_key: {
|
||||
"zones": {self.zone_key: {"state": ADVANTAGE_AIR_STATE_OPEN}}
|
||||
}
|
||||
}
|
||||
)
|
||||
await self.async_update_zone({"state": ADVANTAGE_AIR_STATE_OPEN})
|
||||
|
||||
async def async_turn_off(self) -> None:
|
||||
"""Set the HVAC State to off."""
|
||||
await self.aircon(
|
||||
{
|
||||
self.ac_key: {
|
||||
"zones": {self.zone_key: {"state": ADVANTAGE_AIR_STATE_CLOSE}}
|
||||
}
|
||||
}
|
||||
)
|
||||
await self.async_update_zone({"state": ADVANTAGE_AIR_STATE_CLOSE})
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set the HVAC Mode and State."""
|
||||
@ -288,4 +250,4 @@ class AdvantageAirZone(AdvantageAirZoneEntity, ClimateEntity):
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set the Temperature."""
|
||||
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||
await self.aircon({self.ac_key: {"zones": {self.zone_key: {"setTemp": temp}}}})
|
||||
await self.async_update_zone({"setTemp": temp})
|
||||
|
@ -79,48 +79,24 @@ class AdvantageAirZoneVent(AdvantageAirZoneEntity, CoverEntity):
|
||||
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Fully open zone vent."""
|
||||
await self.aircon(
|
||||
{
|
||||
self.ac_key: {
|
||||
"zones": {
|
||||
self.zone_key: {"state": ADVANTAGE_AIR_STATE_OPEN, "value": 100}
|
||||
}
|
||||
}
|
||||
}
|
||||
await self.async_update_zone(
|
||||
{"state": ADVANTAGE_AIR_STATE_OPEN, "value": 100},
|
||||
)
|
||||
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Fully close zone vent."""
|
||||
await self.aircon(
|
||||
{
|
||||
self.ac_key: {
|
||||
"zones": {self.zone_key: {"state": ADVANTAGE_AIR_STATE_CLOSE}}
|
||||
}
|
||||
}
|
||||
)
|
||||
await self.async_update_zone({"state": ADVANTAGE_AIR_STATE_CLOSE})
|
||||
|
||||
async def async_set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Change vent position."""
|
||||
position = round(kwargs[ATTR_POSITION] / 5) * 5
|
||||
if position == 0:
|
||||
await self.aircon(
|
||||
{
|
||||
self.ac_key: {
|
||||
"zones": {self.zone_key: {"state": ADVANTAGE_AIR_STATE_CLOSE}}
|
||||
}
|
||||
}
|
||||
)
|
||||
await self.async_update_zone({"state": ADVANTAGE_AIR_STATE_CLOSE})
|
||||
else:
|
||||
await self.aircon(
|
||||
await self.async_update_zone(
|
||||
{
|
||||
self.ac_key: {
|
||||
"zones": {
|
||||
self.zone_key: {
|
||||
"state": ADVANTAGE_AIR_STATE_OPEN,
|
||||
"value": position,
|
||||
}
|
||||
}
|
||||
}
|
||||
"state": ADVANTAGE_AIR_STATE_OPEN,
|
||||
"value": position,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
"""Advantage Air parent entity class."""
|
||||
from typing import Any
|
||||
|
||||
from advantage_air import ApiError
|
||||
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
@ -17,6 +20,21 @@ class AdvantageAirEntity(CoordinatorEntity):
|
||||
super().__init__(instance["coordinator"])
|
||||
self._attr_unique_id: str = self.coordinator.data["system"]["rid"]
|
||||
|
||||
def update_handle_factory(self, func, *keys):
|
||||
"""Return the provided API function wrapped.
|
||||
|
||||
Adds an error handler and coordinator refresh, and presets keys.
|
||||
"""
|
||||
|
||||
async def update_handle(*values):
|
||||
try:
|
||||
if await func(*keys, *values):
|
||||
await self.coordinator.async_refresh()
|
||||
except ApiError as err:
|
||||
raise HomeAssistantError(err) from err
|
||||
|
||||
return update_handle
|
||||
|
||||
|
||||
class AdvantageAirAcEntity(AdvantageAirEntity):
|
||||
"""Parent class for Advantage Air AC Entities."""
|
||||
@ -24,7 +42,7 @@ class AdvantageAirAcEntity(AdvantageAirEntity):
|
||||
def __init__(self, instance: dict[str, Any], ac_key: str) -> None:
|
||||
"""Initialize common aspects of an Advantage Air ac entity."""
|
||||
super().__init__(instance)
|
||||
self.aircon = instance["aircon"]
|
||||
|
||||
self.ac_key: str = ac_key
|
||||
self._attr_unique_id += f"-{ac_key}"
|
||||
|
||||
@ -35,6 +53,9 @@ class AdvantageAirAcEntity(AdvantageAirEntity):
|
||||
model=self.coordinator.data["system"]["sysType"],
|
||||
name=self.coordinator.data["aircons"][self.ac_key]["info"]["name"],
|
||||
)
|
||||
self.async_update_ac = self.update_handle_factory(
|
||||
instance["api"].aircon.async_update_ac, self.ac_key
|
||||
)
|
||||
|
||||
@property
|
||||
def _ac(self) -> dict[str, Any]:
|
||||
@ -47,8 +68,12 @@ class AdvantageAirZoneEntity(AdvantageAirAcEntity):
|
||||
def __init__(self, instance: dict[str, Any], ac_key: str, zone_key: str) -> None:
|
||||
"""Initialize common aspects of an Advantage Air zone entity."""
|
||||
super().__init__(instance, ac_key)
|
||||
|
||||
self.zone_key: str = zone_key
|
||||
self._attr_unique_id += f"-{zone_key}"
|
||||
self.async_update_zone = self.update_handle_factory(
|
||||
instance["api"].aircon.async_update_zone, self.ac_key, self.zone_key
|
||||
)
|
||||
|
||||
@property
|
||||
def _zone(self) -> dict[str, Any]:
|
||||
@ -61,7 +86,7 @@ class AdvantageAirThingEntity(AdvantageAirEntity):
|
||||
def __init__(self, instance: dict[str, Any], thing: dict[str, Any]) -> None:
|
||||
"""Initialize common aspects of an Advantage Air Things entity."""
|
||||
super().__init__(instance)
|
||||
self.set = instance["things"]
|
||||
|
||||
self._id = thing["id"]
|
||||
self._attr_unique_id += f"-{self._id}"
|
||||
|
||||
@ -72,6 +97,9 @@ class AdvantageAirThingEntity(AdvantageAirEntity):
|
||||
model="MyPlace",
|
||||
name=thing["name"],
|
||||
)
|
||||
self.async_update_value = self.update_handle_factory(
|
||||
instance["api"].things.async_update_value, self._id
|
||||
)
|
||||
|
||||
@property
|
||||
def _data(self) -> dict:
|
||||
@ -85,8 +113,8 @@ class AdvantageAirThingEntity(AdvantageAirEntity):
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the thing on."""
|
||||
await self.set({self._id: {"id": self._id, "value": 100}})
|
||||
await self.async_update_value(True)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the thing off."""
|
||||
await self.set({self._id: {"id": self._id, "value": 0}})
|
||||
await self.async_update_value(False)
|
||||
|
@ -7,11 +7,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import (
|
||||
ADVANTAGE_AIR_STATE_OFF,
|
||||
ADVANTAGE_AIR_STATE_ON,
|
||||
DOMAIN as ADVANTAGE_AIR_DOMAIN,
|
||||
)
|
||||
from .const import ADVANTAGE_AIR_STATE_ON, DOMAIN as ADVANTAGE_AIR_DOMAIN
|
||||
from .entity import AdvantageAirEntity, AdvantageAirThingEntity
|
||||
|
||||
|
||||
@ -48,7 +44,7 @@ class AdvantageAirLight(AdvantageAirEntity, LightEntity):
|
||||
def __init__(self, instance: dict[str, Any], light: dict[str, Any]) -> None:
|
||||
"""Initialize an Advantage Air Light."""
|
||||
super().__init__(instance)
|
||||
self.set = instance["lights"]
|
||||
|
||||
self._id: str = light["id"]
|
||||
self._attr_unique_id += f"-{self._id}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
@ -58,6 +54,9 @@ class AdvantageAirLight(AdvantageAirEntity, LightEntity):
|
||||
model=light.get("moduleType"),
|
||||
name=light["name"],
|
||||
)
|
||||
self.async_update_state = self.update_handle_factory(
|
||||
instance["api"].lights.async_update_state, self._id
|
||||
)
|
||||
|
||||
@property
|
||||
def _data(self) -> dict[str, Any]:
|
||||
@ -71,11 +70,11 @@ class AdvantageAirLight(AdvantageAirEntity, LightEntity):
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on."""
|
||||
await self.set({self._id: {"id": self._id, "state": ADVANTAGE_AIR_STATE_ON}})
|
||||
await self.async_update_state(True)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the light off."""
|
||||
await self.set({self._id: {"id": self._id, "state": ADVANTAGE_AIR_STATE_OFF}})
|
||||
await self.async_update_state(False)
|
||||
|
||||
|
||||
class AdvantageAirLightDimmable(AdvantageAirLight):
|
||||
@ -83,6 +82,13 @@ class AdvantageAirLightDimmable(AdvantageAirLight):
|
||||
|
||||
_attr_supported_color_modes = {ColorMode.ONOFF, ColorMode.BRIGHTNESS}
|
||||
|
||||
def __init__(self, instance: dict[str, Any], light: dict[str, Any]) -> None:
|
||||
"""Initialize an Advantage Air Dimmable Light."""
|
||||
super().__init__(instance, light)
|
||||
self.async_update_value = self.update_handle_factory(
|
||||
instance["api"].lights.async_update_value, self._id
|
||||
)
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
@ -90,12 +96,9 @@ class AdvantageAirLightDimmable(AdvantageAirLight):
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on and optionally set the brightness."""
|
||||
data: dict[str, Any] = {
|
||||
self._id: {"id": self._id, "state": ADVANTAGE_AIR_STATE_ON}
|
||||
}
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
data[self._id]["value"] = round(kwargs[ATTR_BRIGHTNESS] * 100 / 255)
|
||||
await self.set(data)
|
||||
return await self.async_update_value(round(kwargs[ATTR_BRIGHTNESS] / 2.55))
|
||||
return await self.async_update_state(True)
|
||||
|
||||
|
||||
class AdvantageAirThingLight(AdvantageAirThingEntity, LightEntity):
|
||||
@ -116,11 +119,4 @@ class AdvantageAirThingLightDimmable(AdvantageAirThingEntity, LightEntity):
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on by setting the brightness."""
|
||||
await self.set(
|
||||
{
|
||||
self._id: {
|
||||
"id": self._id,
|
||||
"value": round(kwargs.get(ATTR_BRIGHTNESS, 255) * 100 / 255),
|
||||
}
|
||||
}
|
||||
)
|
||||
await self.async_update_value(round(kwargs.get(ATTR_BRIGHTNESS, 255) / 2.55))
|
||||
|
@ -7,5 +7,5 @@
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["advantage_air"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["advantage_air==0.4.2"]
|
||||
"requirements": ["advantage_air==0.4.4"]
|
||||
}
|
||||
|
@ -58,6 +58,4 @@ class AdvantageAirMyZone(AdvantageAirAcEntity, SelectEntity):
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Set the MyZone."""
|
||||
await self.aircon(
|
||||
{self.ac_key: {"info": {"myZone": self._name_to_number[option]}}}
|
||||
)
|
||||
await self.async_update_ac({"myZone": self._name_to_number[option]})
|
||||
|
@ -88,7 +88,7 @@ class AdvantageAirTimeTo(AdvantageAirAcEntity, SensorEntity):
|
||||
async def set_time_to(self, **kwargs: Any) -> None:
|
||||
"""Set the timer value."""
|
||||
value = min(720, max(0, int(kwargs[ADVANTAGE_AIR_SET_COUNTDOWN_VALUE])))
|
||||
await self.aircon({self.ac_key: {"info": {self._time_key: value}}})
|
||||
await self.async_update_ac({self._time_key: value})
|
||||
|
||||
|
||||
class AdvantageAirZoneVent(AdvantageAirZoneEntity, SensorEntity):
|
||||
|
@ -54,15 +54,11 @@ class AdvantageAirFreshAir(AdvantageAirAcEntity, SwitchEntity):
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn fresh air on."""
|
||||
await self.aircon(
|
||||
{self.ac_key: {"info": {"freshAirStatus": ADVANTAGE_AIR_STATE_ON}}}
|
||||
)
|
||||
await self.async_update_ac({"freshAirStatus": ADVANTAGE_AIR_STATE_ON})
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn fresh air off."""
|
||||
await self.aircon(
|
||||
{self.ac_key: {"info": {"freshAirStatus": ADVANTAGE_AIR_STATE_OFF}}}
|
||||
)
|
||||
await self.async_update_ac({"freshAirStatus": ADVANTAGE_AIR_STATE_OFF})
|
||||
|
||||
|
||||
class AdvantageAirRelay(AdvantageAirThingEntity, SwitchEntity):
|
||||
|
@ -86,7 +86,7 @@ adext==0.4.2
|
||||
adguardhome==0.6.1
|
||||
|
||||
# homeassistant.components.advantage_air
|
||||
advantage_air==0.4.2
|
||||
advantage_air==0.4.4
|
||||
|
||||
# homeassistant.components.frontier_silicon
|
||||
afsapi==0.2.7
|
||||
|
@ -76,7 +76,7 @@ adext==0.4.2
|
||||
adguardhome==0.6.1
|
||||
|
||||
# homeassistant.components.advantage_air
|
||||
advantage_air==0.4.2
|
||||
advantage_air==0.4.4
|
||||
|
||||
# homeassistant.components.frontier_silicon
|
||||
afsapi==0.2.7
|
||||
|
@ -90,6 +90,20 @@ async def test_light(hass: HomeAssistant, aioclient_mock: AiohttpClientMocker) -
|
||||
assert entry
|
||||
assert entry.unique_id == f"uniqueid-{light_id}"
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: [entity_id]},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[-2][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-2][1].path == "/setLights"
|
||||
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(light_id)
|
||||
assert data["id"] == light_id
|
||||
assert data["state"] == ADVANTAGE_AIR_STATE_ON
|
||||
assert aioclient_mock.mock_calls[-1][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
|
Loading…
x
Reference in New Issue
Block a user