Add Overkiz AtlanticPassAPCHeatingAndCoolingZone (#78659)
* Add Overkiz AtlanticPassAPCHeatingAndCoolingZone * Fix commands instanciations to be simpler * Update AtlanticPassAPCHeatingAndCoolingZone to show temperature and fix HA threads * Simplify async_execute_commands in order to receive simpler list * Fix get and set temperature in derogation or auto mode * Remove hvac_action from AtlanticPassAPCHeatingAndCoolingZone * Remove unused lines * Update async_execute_commands to work like async_execute_command Implement cancel for multiple commands * Improve to use preset_home for internal scheduling * Remove async_execute_commands * Improvement for AtlanticPassAPCHeatingAndCoolingZone * Update homeassistant/components/overkiz/climate_entities/__init__.py Co-authored-by: Quentame <polletquentin74@me.com> * Update homeassistant/components/overkiz/climate_entities/atlantic_pass_apc_heating_and_cooling_zone.py Co-authored-by: Quentame <polletquentin74@me.com> * Update homeassistant/components/overkiz/climate_entities/atlantic_pass_apc_heating_and_cooling_zone.py Co-authored-by: Quentame <polletquentin74@me.com> * Update homeassistant/components/overkiz/const.py Co-authored-by: Quentame <polletquentin74@me.com> Co-authored-by: Quentame <polletquentin74@me.com>pull/78665/head
parent
93072d8ac5
commit
1a5eeb2db1
|
@ -4,6 +4,9 @@ from pyoverkiz.enums.ui import UIWidget
|
|||
from .atlantic_electrical_heater import AtlanticElectricalHeater
|
||||
from .atlantic_electrical_towel_dryer import AtlanticElectricalTowelDryer
|
||||
from .atlantic_heat_recovery_ventilation import AtlanticHeatRecoveryVentilation
|
||||
from .atlantic_pass_apc_heating_and_cooling_zone import (
|
||||
AtlanticPassAPCHeatingAndCoolingZone,
|
||||
)
|
||||
from .atlantic_pass_apc_zone_control import AtlanticPassAPCZoneControl
|
||||
from .somfy_thermostat import SomfyThermostat
|
||||
|
||||
|
@ -11,6 +14,7 @@ WIDGET_TO_CLIMATE_ENTITY = {
|
|||
UIWidget.ATLANTIC_ELECTRICAL_HEATER: AtlanticElectricalHeater,
|
||||
UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: AtlanticElectricalTowelDryer,
|
||||
UIWidget.ATLANTIC_HEAT_RECOVERY_VENTILATION: AtlanticHeatRecoveryVentilation,
|
||||
UIWidget.ATLANTIC_PASS_APC_HEATING_AND_COOLING_ZONE: AtlanticPassAPCHeatingAndCoolingZone,
|
||||
UIWidget.ATLANTIC_PASS_APC_ZONE_CONTROL: AtlanticPassAPCZoneControl,
|
||||
UIWidget.SOMFY_THERMOSTAT: SomfyThermostat,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
"""Support for Atlantic Pass APC Heating And Cooling Zone Control."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, cast
|
||||
|
||||
from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
PRESET_AWAY,
|
||||
PRESET_COMFORT,
|
||||
PRESET_ECO,
|
||||
PRESET_HOME,
|
||||
PRESET_SLEEP,
|
||||
ClimateEntity,
|
||||
ClimateEntityFeature,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
||||
|
||||
from ..coordinator import OverkizDataUpdateCoordinator
|
||||
from ..entity import OverkizEntity
|
||||
|
||||
OVERKIZ_TO_HVAC_MODE: dict[str, str] = {
|
||||
OverkizCommandParam.AUTO: HVACMode.AUTO,
|
||||
OverkizCommandParam.ECO: HVACMode.AUTO,
|
||||
OverkizCommandParam.MANU: HVACMode.HEAT,
|
||||
OverkizCommandParam.HEATING: HVACMode.HEAT,
|
||||
OverkizCommandParam.STOP: HVACMode.OFF,
|
||||
OverkizCommandParam.INTERNAL_SCHEDULING: HVACMode.AUTO,
|
||||
OverkizCommandParam.COMFORT: HVACMode.HEAT,
|
||||
}
|
||||
|
||||
HVAC_MODE_TO_OVERKIZ = {v: k for k, v in OVERKIZ_TO_HVAC_MODE.items()}
|
||||
|
||||
OVERKIZ_TO_PRESET_MODES: dict[str, str] = {
|
||||
OverkizCommandParam.OFF: PRESET_ECO,
|
||||
OverkizCommandParam.STOP: PRESET_ECO,
|
||||
OverkizCommandParam.MANU: PRESET_COMFORT,
|
||||
OverkizCommandParam.COMFORT: PRESET_COMFORT,
|
||||
OverkizCommandParam.ABSENCE: PRESET_AWAY,
|
||||
OverkizCommandParam.ECO: PRESET_ECO,
|
||||
OverkizCommandParam.INTERNAL_SCHEDULING: PRESET_HOME,
|
||||
}
|
||||
|
||||
PRESET_MODES_TO_OVERKIZ = {v: k for k, v in OVERKIZ_TO_PRESET_MODES.items()}
|
||||
|
||||
OVERKIZ_TO_PROFILE_MODES: dict[str, str] = {
|
||||
OverkizCommandParam.OFF: PRESET_SLEEP,
|
||||
OverkizCommandParam.STOP: PRESET_SLEEP,
|
||||
OverkizCommandParam.ECO: PRESET_ECO,
|
||||
OverkizCommandParam.ABSENCE: PRESET_AWAY,
|
||||
OverkizCommandParam.MANU: PRESET_COMFORT,
|
||||
OverkizCommandParam.DEROGATION: PRESET_COMFORT,
|
||||
OverkizCommandParam.COMFORT: PRESET_COMFORT,
|
||||
}
|
||||
|
||||
OVERKIZ_TEMPERATURE_STATE_BY_PROFILE: dict[str, str] = {
|
||||
OverkizCommandParam.ECO: OverkizState.CORE_ECO_HEATING_TARGET_TEMPERATURE,
|
||||
OverkizCommandParam.COMFORT: OverkizState.CORE_COMFORT_HEATING_TARGET_TEMPERATURE,
|
||||
OverkizCommandParam.DEROGATION: OverkizState.CORE_DEROGATED_TARGET_TEMPERATURE,
|
||||
}
|
||||
|
||||
|
||||
class AtlanticPassAPCHeatingAndCoolingZone(OverkizEntity, ClimateEntity):
|
||||
"""Representation of Atlantic Pass APC Heating And Cooling Zone Control."""
|
||||
|
||||
_attr_hvac_modes = [*HVAC_MODE_TO_OVERKIZ]
|
||||
_attr_preset_modes = [*PRESET_MODES_TO_OVERKIZ]
|
||||
_attr_supported_features = (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
|
||||
)
|
||||
_attr_temperature_unit = TEMP_CELSIUS
|
||||
|
||||
def __init__(
|
||||
self, device_url: str, coordinator: OverkizDataUpdateCoordinator
|
||||
) -> None:
|
||||
"""Init method."""
|
||||
super().__init__(device_url, coordinator)
|
||||
|
||||
# Temperature sensor use the same base_device_url and use the n+1 index
|
||||
self.temperature_device = self.executor.linked_device(
|
||||
int(self.index_device_url) + 1
|
||||
)
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the current temperature."""
|
||||
if temperature := self.temperature_device.states[OverkizState.CORE_TEMPERATURE]:
|
||||
return cast(float, temperature.value)
|
||||
|
||||
return None
|
||||
|
||||
@property
|
||||
def hvac_mode(self) -> str:
|
||||
"""Return hvac operation ie. heat, cool mode."""
|
||||
return OVERKIZ_TO_HVAC_MODE[
|
||||
cast(str, self.executor.select_state(OverkizState.IO_PASS_APC_HEATING_MODE))
|
||||
]
|
||||
|
||||
@property
|
||||
def current_heating_profile(self) -> str:
|
||||
"""Return current heating profile."""
|
||||
return cast(
|
||||
str,
|
||||
self.executor.select_state(OverkizState.IO_PASS_APC_HEATING_PROFILE),
|
||||
)
|
||||
|
||||
async def async_set_heating_mode(self, mode: str) -> None:
|
||||
"""Set new heating mode and refresh states."""
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.SET_PASS_APC_HEATING_MODE, mode
|
||||
)
|
||||
|
||||
if self.current_heating_profile == OverkizCommandParam.DEROGATION:
|
||||
# If current mode is in derogation, disable it
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.SET_DEROGATION_ON_OFF_STATE, OverkizCommandParam.OFF
|
||||
)
|
||||
|
||||
# We also needs to execute these 2 commands to make it work correctly
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_PASS_APC_HEATING_MODE
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_PASS_APC_HEATING_PROFILE
|
||||
)
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: str) -> None:
|
||||
"""Set new target hvac mode."""
|
||||
await self.async_set_heating_mode(HVAC_MODE_TO_OVERKIZ[hvac_mode])
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Set new preset mode."""
|
||||
await self.async_set_heating_mode(PRESET_MODES_TO_OVERKIZ[preset_mode])
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str:
|
||||
"""Return the current preset mode, e.g., home, away, temp."""
|
||||
heating_mode = cast(
|
||||
str, self.executor.select_state(OverkizState.IO_PASS_APC_HEATING_MODE)
|
||||
)
|
||||
|
||||
if heating_mode == OverkizCommandParam.INTERNAL_SCHEDULING:
|
||||
# In Internal scheduling, it could be comfort or eco
|
||||
return OVERKIZ_TO_PROFILE_MODES[
|
||||
cast(
|
||||
str,
|
||||
self.executor.select_state(
|
||||
OverkizState.IO_PASS_APC_HEATING_PROFILE
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
return OVERKIZ_TO_PRESET_MODES[heating_mode]
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float:
|
||||
"""Return hvac target temperature."""
|
||||
current_heating_profile = self.current_heating_profile
|
||||
if current_heating_profile in OVERKIZ_TEMPERATURE_STATE_BY_PROFILE:
|
||||
return cast(
|
||||
float,
|
||||
self.executor.select_state(
|
||||
OVERKIZ_TEMPERATURE_STATE_BY_PROFILE[current_heating_profile]
|
||||
),
|
||||
)
|
||||
return cast(
|
||||
float, self.executor.select_state(OverkizState.CORE_TARGET_TEMPERATURE)
|
||||
)
|
||||
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set new temperature."""
|
||||
temperature = kwargs[ATTR_TEMPERATURE]
|
||||
|
||||
if self.hvac_mode == HVACMode.AUTO:
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.SET_COMFORT_HEATING_TARGET_TEMPERATURE,
|
||||
temperature,
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_COMFORT_HEATING_TARGET_TEMPERATURE
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_TARGET_TEMPERATURE
|
||||
)
|
||||
else:
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.SET_DEROGATED_TARGET_TEMPERATURE,
|
||||
temperature,
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.SET_DEROGATION_ON_OFF_STATE,
|
||||
OverkizCommandParam.ON,
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_TARGET_TEMPERATURE
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_PASS_APC_HEATING_MODE
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_PASS_APC_HEATING_PROFILE
|
||||
)
|
|
@ -64,6 +64,7 @@ OVERKIZ_DEVICE_TO_PLATFORM: dict[UIClass | UIWidget, Platform | None] = {
|
|||
UIWidget.ATLANTIC_ELECTRICAL_HEATER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
|
||||
UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
|
||||
UIWidget.ATLANTIC_HEAT_RECOVERY_VENTILATION: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
|
||||
UIWidget.ATLANTIC_PASS_APC_HEATING_AND_COOLING_ZONE: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
|
||||
UIWidget.ATLANTIC_PASS_APC_ZONE_CONTROL: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
|
||||
UIWidget.DOMESTIC_HOT_WATER_TANK: Platform.SWITCH, # widgetName, uiClass is WaterHeatingSystem (not supported)
|
||||
UIWidget.MY_FOX_ALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported)
|
||||
|
|
|
@ -27,7 +27,10 @@ class OverkizEntity(CoordinatorEntity[OverkizDataUpdateCoordinator]):
|
|||
"""Initialize the device."""
|
||||
super().__init__(coordinator)
|
||||
self.device_url = device_url
|
||||
self.base_device_url, *_ = self.device_url.split("#")
|
||||
split_device_url = self.device_url.split("#")
|
||||
self.base_device_url = split_device_url[0]
|
||||
if len(split_device_url) == 2:
|
||||
self.index_device_url = split_device_url[1]
|
||||
self.executor = OverkizExecutor(device_url, coordinator)
|
||||
|
||||
self._attr_assumed_state = not self.device.states
|
||||
|
|
Loading…
Reference in New Issue