-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Airzone Cloud switch entities to zones (#125917)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
- Loading branch information
Showing
3 changed files
with
187 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
Platform.CLIMATE, | ||
Platform.SELECT, | ||
Platform.SENSOR, | ||
Platform.SWITCH, | ||
Platform.WATER_HEATER, | ||
] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
"""Support for the Airzone Cloud switch.""" | ||
|
||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
from typing import Any, Final | ||
|
||
from aioairzone_cloud.const import API_POWER, API_VALUE, AZD_POWER, AZD_ZONES | ||
|
||
from homeassistant.components.switch import ( | ||
SwitchDeviceClass, | ||
SwitchEntity, | ||
SwitchEntityDescription, | ||
) | ||
from homeassistant.core import HomeAssistant, callback | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
|
||
from . import AirzoneCloudConfigEntry | ||
from .coordinator import AirzoneUpdateCoordinator | ||
from .entity import AirzoneEntity, AirzoneZoneEntity | ||
|
||
|
||
@dataclass(frozen=True, kw_only=True) | ||
class AirzoneSwitchDescription(SwitchEntityDescription): | ||
"""Class to describe an Airzone switch entity.""" | ||
|
||
api_param: str | ||
|
||
|
||
ZONE_SWITCH_TYPES: Final[tuple[AirzoneSwitchDescription, ...]] = ( | ||
AirzoneSwitchDescription( | ||
api_param=API_POWER, | ||
device_class=SwitchDeviceClass.SWITCH, | ||
key=AZD_POWER, | ||
), | ||
) | ||
|
||
|
||
async def async_setup_entry( | ||
hass: HomeAssistant, | ||
entry: AirzoneCloudConfigEntry, | ||
async_add_entities: AddEntitiesCallback, | ||
) -> None: | ||
"""Add Airzone Cloud switch from a config_entry.""" | ||
coordinator = entry.runtime_data | ||
|
||
# Zones | ||
async_add_entities( | ||
AirzoneZoneSwitch( | ||
coordinator, | ||
description, | ||
zone_id, | ||
zone_data, | ||
) | ||
for description in ZONE_SWITCH_TYPES | ||
for zone_id, zone_data in coordinator.data.get(AZD_ZONES, {}).items() | ||
if description.key in zone_data | ||
) | ||
|
||
|
||
class AirzoneBaseSwitch(AirzoneEntity, SwitchEntity): | ||
"""Define an Airzone Cloud switch.""" | ||
|
||
entity_description: AirzoneSwitchDescription | ||
|
||
@callback | ||
def _handle_coordinator_update(self) -> None: | ||
"""Update attributes when the coordinator updates.""" | ||
self._async_update_attrs() | ||
super()._handle_coordinator_update() | ||
|
||
@callback | ||
def _async_update_attrs(self) -> None: | ||
"""Update switch attributes.""" | ||
self._attr_is_on = self.get_airzone_value(self.entity_description.key) | ||
|
||
|
||
class AirzoneZoneSwitch(AirzoneZoneEntity, AirzoneBaseSwitch): | ||
"""Define an Airzone Cloud Zone switch.""" | ||
|
||
def __init__( | ||
self, | ||
coordinator: AirzoneUpdateCoordinator, | ||
description: AirzoneSwitchDescription, | ||
zone_id: str, | ||
zone_data: dict[str, Any], | ||
) -> None: | ||
"""Initialize.""" | ||
super().__init__(coordinator, zone_id, zone_data) | ||
|
||
self._attr_name = None | ||
self._attr_unique_id = f"{zone_id}_{description.key}" | ||
self.entity_description = description | ||
|
||
self._async_update_attrs() | ||
|
||
async def async_turn_on(self, **kwargs: Any) -> None: | ||
"""Turn the entity on.""" | ||
param = self.entity_description.api_param | ||
params: dict[str, Any] = { | ||
param: { | ||
API_VALUE: True, | ||
} | ||
} | ||
await self._async_update_params(params) | ||
|
||
async def async_turn_off(self, **kwargs: Any) -> None: | ||
"""Turn the entity off.""" | ||
param = self.entity_description.api_param | ||
params: dict[str, Any] = { | ||
param: { | ||
API_VALUE: False, | ||
} | ||
} | ||
await self._async_update_params(params) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
"""The switch tests for the Airzone Cloud platform.""" | ||
|
||
from unittest.mock import patch | ||
|
||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN | ||
from homeassistant.const import ( | ||
ATTR_ENTITY_ID, | ||
SERVICE_TURN_OFF, | ||
SERVICE_TURN_ON, | ||
STATE_OFF, | ||
STATE_ON, | ||
) | ||
from homeassistant.core import HomeAssistant | ||
|
||
from .util import async_init_integration | ||
|
||
|
||
async def test_airzone_create_switches(hass: HomeAssistant) -> None: | ||
"""Test creation of switches.""" | ||
|
||
await async_init_integration(hass) | ||
|
||
state = hass.states.get("switch.dormitorio") | ||
assert state.state == STATE_OFF | ||
|
||
state = hass.states.get("switch.salon") | ||
assert state.state == STATE_ON | ||
|
||
|
||
async def test_airzone_switch_off(hass: HomeAssistant) -> None: | ||
"""Test switch off.""" | ||
|
||
await async_init_integration(hass) | ||
|
||
with patch( | ||
"homeassistant.components.airzone_cloud.AirzoneCloudApi.api_patch_device", | ||
return_value=None, | ||
): | ||
await hass.services.async_call( | ||
SWITCH_DOMAIN, | ||
SERVICE_TURN_OFF, | ||
{ | ||
ATTR_ENTITY_ID: "switch.salon", | ||
}, | ||
blocking=True, | ||
) | ||
|
||
state = hass.states.get("switch.salon") | ||
assert state.state == STATE_OFF | ||
|
||
|
||
async def test_airzone_switch_on(hass: HomeAssistant) -> None: | ||
"""Test switch on.""" | ||
|
||
await async_init_integration(hass) | ||
|
||
with patch( | ||
"homeassistant.components.airzone_cloud.AirzoneCloudApi.api_patch_device", | ||
return_value=None, | ||
): | ||
await hass.services.async_call( | ||
SWITCH_DOMAIN, | ||
SERVICE_TURN_ON, | ||
{ | ||
ATTR_ENTITY_ID: "switch.dormitorio", | ||
}, | ||
blocking=True, | ||
) | ||
|
||
state = hass.states.get("switch.dormitorio") | ||
assert state.state == STATE_ON |