Skip to content

Commit

Permalink
new mode and preset map for vrc700
Browse files Browse the repository at this point in the history
  • Loading branch information
signalkraft committed Feb 21, 2024
1 parent af0df63 commit f3ae76b
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 45 deletions.
114 changes: 71 additions & 43 deletions custom_components/mypyllant/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
ClimateEntityFeature,
HVACMode,
HVACAction,
PRESET_COMFORT,
)
from homeassistant.components.climate.const import (
FAN_AUTO,
Expand Down Expand Up @@ -97,6 +98,13 @@
PRESET_SLEEP: ZoneCurrentSpecialFunction.SYSTEM_OFF,
}

ZONE_PRESET_MAP_VRC700 = {
ZoneHeatingOperatingModeVRC700.OFF: PRESET_NONE,
ZoneHeatingOperatingModeVRC700.DAY: PRESET_COMFORT,
ZoneHeatingOperatingModeVRC700.AUTO: PRESET_NONE,
ZoneHeatingOperatingModeVRC700.SET_BACK: PRESET_ECO,
}

ZONE_HVAC_ACTION_MAP = {
CircuitState.STANDBY: HVACAction.IDLE,
CircuitState.HEATING: HVACAction.HEATING,
Expand Down Expand Up @@ -285,7 +293,6 @@ class ZoneClimate(CoordinatorEntity, ClimateEntity):

coordinator: SystemCoordinator
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_preset_modes = [str(k) for k in ZONE_PRESET_MAP.keys()]

def __init__(
self,
Expand All @@ -308,8 +315,8 @@ def hvac_mode_map(self):
if self.zone.control_identifier.is_vrc700:
return {
ZoneHeatingOperatingModeVRC700.OFF: HVACMode.OFF,
ZoneHeatingOperatingModeVRC700.DAY: HVACMode.HEAT_COOL,
ZoneHeatingOperatingModeVRC700.AUTO: HVACMode.AUTO,
ZoneHeatingOperatingModeVRC700.DAY: HVACMode.AUTO,
ZoneHeatingOperatingModeVRC700.SET_BACK: HVACMode.AUTO,
}
else:
Expand Down Expand Up @@ -547,15 +554,25 @@ async def async_set_temperature(self, **kwargs: Any) -> None:
await self.set_quick_veto(temperature=temperature)
await self.coordinator.async_request_refresh_delayed()

@property
def preset_modes(self) -> list[str]:
if self.zone.control_identifier.is_vrc700:
return [k for k in ZONE_PRESET_MAP_VRC700.values()]
else:
return [k for k in ZONE_PRESET_MAP.keys()]

@property
def preset_mode(self) -> str:
if self.zone.is_eco_mode:
return PRESET_ECO
return [
k
for k, v in ZONE_PRESET_MAP.items()
if v == self.zone.current_special_function
][0]
if self.zone.control_identifier.is_vrc700:
return ZONE_PRESET_MAP_VRC700[self.zone.heating.operation_mode_heating] # type: ignore
else:
if self.zone.is_eco_mode:
return PRESET_ECO
return [
k
for k, v in ZONE_PRESET_MAP.items()
if v == self.zone.current_special_function
][0]

async def async_set_preset_mode(self, preset_mode):
"""
Expand All @@ -564,43 +581,54 @@ async def async_set_preset_mode(self, preset_mode):
Parameters:
preset_mode (str): The new preset mode to set
"""
if preset_mode not in ZONE_PRESET_MAP:
raise ValueError(
f'Invalid preset mode, use one of {", ".join(ZONE_PRESET_MAP.keys())}'
)
requested_mode = ZONE_PRESET_MAP[preset_mode]
if requested_mode != self.zone.current_special_function:
if requested_mode == ZoneCurrentSpecialFunction.NONE:
if (
self.zone.current_special_function
== ZoneCurrentSpecialFunction.QUICK_VETO
):
# If quick veto is set, we cancel that
await self.coordinator.api.cancel_quick_veto_zone_temperature(
self.zone
)
elif (
self.zone.current_special_function
== ZoneCurrentSpecialFunction.HOLIDAY
):
# If holiday mode is set, we cancel that instead
await self.cancel_holiday()
if requested_mode == ZoneCurrentSpecialFunction.QUICK_VETO:
await self.coordinator.api.quick_veto_zone_temperature(
self.zone,
self.zone.heating.manual_mode_setpoint_heating,
default_duration=self.default_quick_veto_duration,
if self.zone.control_identifier.is_vrc700:
try:
requested_mode = [
k for k, v in ZONE_PRESET_MAP_VRC700.items() if v == preset_mode
][0]
await self.set_zone_operating_mode(requested_mode)
except IndexError:
raise ValueError(
f'Invalid preset mode, use one of {", ".join(set(ZONE_PRESET_MAP_VRC700.values()))}'
)
else:
if preset_mode not in ZONE_PRESET_MAP:
raise ValueError(
f'Invalid preset mode, use one of {", ".join(ZONE_PRESET_MAP.keys())}'
)
if requested_mode == ZoneCurrentSpecialFunction.HOLIDAY:
await self.set_holiday()
requested_mode = ZONE_PRESET_MAP[preset_mode]
if requested_mode != self.zone.current_special_function:
if requested_mode == ZoneCurrentSpecialFunction.NONE:
if (
self.zone.current_special_function
== ZoneCurrentSpecialFunction.QUICK_VETO
):
# If quick veto is set, we cancel that
await self.coordinator.api.cancel_quick_veto_zone_temperature(
self.zone
)
elif (
self.zone.current_special_function
== ZoneCurrentSpecialFunction.HOLIDAY
):
# If holiday mode is set, we cancel that instead
await self.cancel_holiday()
if requested_mode == ZoneCurrentSpecialFunction.QUICK_VETO:
await self.coordinator.api.quick_veto_zone_temperature(
self.zone,
self.zone.heating.manual_mode_setpoint_heating,
default_duration=self.default_quick_veto_duration,
)
if requested_mode == ZoneCurrentSpecialFunction.HOLIDAY:
await self.set_holiday()

if requested_mode == ZoneCurrentSpecialFunction.SYSTEM_OFF:
# SYSTEM_OFF is a valid special function, but since there's no API endpoint we
# just turn off the system though the zone heating mode API.
# See https://github.com/signalkraft/mypyllant-component/issues/27#issuecomment-1746568372
await self.async_set_hvac_mode(HVACMode.OFF)
if requested_mode == ZoneCurrentSpecialFunction.SYSTEM_OFF:
# SYSTEM_OFF is a valid special function, but since there's no API endpoint we
# just turn off the system though the zone heating mode API.
# See https://github.com/signalkraft/mypyllant-component/issues/27#issuecomment-1746568372
await self.async_set_hvac_mode(HVACMode.OFF)

await self.coordinator.async_request_refresh_delayed()
await self.coordinator.async_request_refresh_delayed()


class VentilationClimate(CoordinatorEntity, ClimateEntity):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest as pytest
from homeassistant.components.climate import HVACMode
from homeassistant.components.climate.const import FAN_OFF, PRESET_AWAY
from homeassistant.components.climate.const import FAN_OFF, PRESET_ECO
from homeassistant.const import ATTR_TEMPERATURE
from homeassistant.helpers.entity_registry import DATA_REGISTRY, EntityRegistry
from homeassistant.loader import DATA_COMPONENTS, DATA_INTEGRATIONS
Expand Down Expand Up @@ -85,7 +85,7 @@ async def test_zone_climate(
await climate.async_set_hvac_mode(HVACMode.AUTO)
await climate.async_set_temperature(**{ATTR_TEMPERATURE: 20})
# TODO: Test logic of different calls depending on current new preset mode
await climate.async_set_preset_mode(preset_mode=PRESET_AWAY)
await climate.async_set_preset_mode(preset_mode=PRESET_ECO)
system_coordinator_mock._debounced_refresh.async_cancel()

print(system_coordinator_mock.data[0].state["zones"])
Expand Down

0 comments on commit f3ae76b

Please sign in to comment.