Skip to content

Commit

Permalink
Added support for ventilation climate entities on VRC700 controllers
Browse files Browse the repository at this point in the history
  • Loading branch information
signalkraft committed Mar 25, 2024
1 parent 344c75e commit ae2bec5
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 37 deletions.
2 changes: 1 addition & 1 deletion custom_components/mypyllant/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/signalkraft/mypyllant-component/issues",
"requirements": [
"myPyllant==0.8.10"
"myPyllant==0.8.11"
],
"version": "v0.7.3"
}
45 changes: 31 additions & 14 deletions custom_components/mypyllant/ventilation_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,17 @@

from custom_components.mypyllant.const import DOMAIN
from custom_components.mypyllant.coordinator import SystemCoordinator
from myPyllant.enums import VentilationOperationMode, VentilationFanStageType
from myPyllant.enums import (
VentilationOperationMode,
VentilationFanStageType,
VentilationOperationModeVRC700,
)
from myPyllant.models import System, Ventilation

VENTILATION_HVAC_MODE_MAP = {
HVACMode.FAN_ONLY: VentilationOperationMode.NORMAL,
HVACMode.AUTO: VentilationOperationMode.TIME_CONTROLLED,
}
VENTILATION_FAN_MODE_MAP = {
FAN_OFF: VentilationOperationMode.OFF,
FAN_ON: VentilationOperationMode.NORMAL,
FAN_LOW: VentilationOperationMode.REDUCED,
FAN_AUTO: VentilationOperationMode.TIME_CONTROLLED,
}
_FAN_STAGE_TYPE_OPTIONS = [
selector.SelectOptionDict(value=v.value, label=v.value.title())
for v in VentilationFanStageType
Expand All @@ -43,7 +41,6 @@ class VentilationClimate(CoordinatorEntity, ClimateEntity):
"""

coordinator: SystemCoordinator
_attr_fan_modes = [str(k) for k in VENTILATION_FAN_MODE_MAP.keys()]
_attr_hvac_modes = [str(k) for k in VENTILATION_HVAC_MODE_MAP.keys()]
_attr_temperature_unit = UnitOfTemperature.CELSIUS

Expand Down Expand Up @@ -104,6 +101,25 @@ def supported_features(self) -> ClimateEntityFeature:
"""Return the list of supported features."""
return ClimateEntityFeature.FAN_MODE

@property
def fan_mode_map(self):
if self.ventilation.control_identifier.is_vrc700:
return {
VentilationOperationModeVRC700.OFF: FAN_OFF,
VentilationOperationModeVRC700.NORMAL: FAN_ON,
VentilationOperationModeVRC700.REDUCED: FAN_LOW,
VentilationOperationModeVRC700.AUTO: FAN_AUTO,
VentilationOperationModeVRC700.DAY: FAN_ON,
VentilationOperationModeVRC700.SET_BACK: FAN_LOW,
}
else:
return {
VentilationOperationMode.OFF: FAN_OFF,
VentilationOperationMode.NORMAL: FAN_ON,
VentilationOperationMode.REDUCED: FAN_LOW,
VentilationOperationMode.TIME_CONTROLLED: FAN_AUTO,
}

@property
def hvac_mode(self) -> HVACMode:
if (
Expand All @@ -118,6 +134,10 @@ def hvac_mode(self) -> HVACMode:
else:
return HVACMode.FAN_ONLY

@property
def fan_modes(self) -> list[str]:
return [str(k) for k in self.fan_mode_map.values()]

async def async_set_hvac_mode(self, hvac_mode):
await self.coordinator.api.set_ventilation_operation_mode(
self.ventilation,
Expand All @@ -127,16 +147,13 @@ async def async_set_hvac_mode(self, hvac_mode):

@property
def fan_mode(self) -> HVACMode:
return [
k
for k, v in VENTILATION_FAN_MODE_MAP.items()
if v == self.ventilation.operation_mode_ventilation
][0]
return self.fan_mode_map[self.ventilation.operation_mode_ventilation]

async def async_set_fan_mode(self, fan_mode: str) -> None:
mode = [k for k, v in self.fan_mode_map.items() if v == fan_mode][0]
await self.coordinator.api.set_ventilation_operation_mode(
self.ventilation,
VENTILATION_FAN_MODE_MAP[fan_mode],
mode,
)
await self.coordinator.async_request_refresh_delayed()

Expand Down
2 changes: 1 addition & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ types-PyYAML~=6.0.12.12

# Need specific versions
pytest-homeassistant-custom-component==0.13.101
myPyllant==0.8.10
myPyllant==0.8.11

# Versions handled by pytest-homeassistant-custom-component
freezegun
Expand Down
4 changes: 2 additions & 2 deletions tests/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ async def test_system_binary_sensors(
assert isinstance(circuit.device_info, dict)
assert isinstance(circuit.system, System)

assert ControlError(0, system_coordinator_mock).is_on is False
assert isinstance(ControlError(0, system_coordinator_mock).is_on, bool)
assert isinstance(ControlError(0, system_coordinator_mock).name, str)
assert ControlOnline(0, system_coordinator_mock).is_on is True
assert isinstance(ControlOnline(0, system_coordinator_mock).name, str)
Expand All @@ -88,7 +88,7 @@ async def test_control_error(
mocked_api: MyPyllantAPI,
system_coordinator_mock: SystemCoordinator,
):
test_data = load_test_data(DATA_DIR / "ambisense2.yml")
test_data = load_test_data(DATA_DIR / "ambisense2.yaml")
with mypyllant_aioresponses(test_data) as _:
system_coordinator_mock.data = (
await system_coordinator_mock._async_update_data()
Expand Down
38 changes: 20 additions & 18 deletions tests/test_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,32 +111,34 @@ async def test_ventilation_climate(
mocked_api: MyPyllantAPI,
system_coordinator_mock: SystemCoordinator,
):
test_data = load_test_data(DATA_DIR / "ventilation")
with mypyllant_aioresponses(test_data) as _:
system_coordinator_mock.data = (
await system_coordinator_mock._async_update_data()
)
ventilation = VentilationClimate(
0,
0,
system_coordinator_mock,
)
assert isinstance(ventilation.device_info, dict)
assert isinstance(ventilation.extra_state_attributes, dict)
assert isinstance(ventilation.hvac_mode, HVACMode)
assert isinstance(ventilation.fan_mode, str)
test_data_files = ["ventilation", "vrc700_ventilation.yaml"]
for f in test_data_files:
test_data = load_test_data(DATA_DIR / f)
with mypyllant_aioresponses(test_data) as _:
system_coordinator_mock.data = (
await system_coordinator_mock._async_update_data()
)
ventilation = VentilationClimate(
0,
0,
system_coordinator_mock,
)
assert isinstance(ventilation.device_info, dict)
assert isinstance(ventilation.extra_state_attributes, dict)
assert isinstance(ventilation.hvac_mode, HVACMode)
assert isinstance(ventilation.fan_mode, str)

await ventilation.async_set_fan_mode(FAN_OFF)
system_coordinator_mock._debounced_refresh.async_cancel()
await mocked_api.aiohttp_session.close()
await ventilation.async_set_fan_mode(FAN_OFF)
system_coordinator_mock._debounced_refresh.async_cancel()
await mocked_api.aiohttp_session.close()


async def test_ambisense_climate(
mypyllant_aioresponses,
mocked_api: MyPyllantAPI,
system_coordinator_mock: SystemCoordinator,
):
test_data_files = ["ambisense", "ambisense2.yml"]
test_data_files = ["ambisense", "ambisense2.yaml"]
for f in test_data_files:
test_data = load_test_data(DATA_DIR / f)
with mypyllant_aioresponses(test_data) as _:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ async def test_ambisense_time_program(
mocked_api: MyPyllantAPI,
system_coordinator_mock: SystemCoordinator,
) -> None:
test_data_files = ["ambisense", "ambisense2.yml"]
test_data_files = ["ambisense", "ambisense2.yaml"]
for f in test_data_files:
test_data = load_test_data(DATA_DIR / f)
with mypyllant_aioresponses(test_data) as aio:
Expand Down

0 comments on commit ae2bec5

Please sign in to comment.