Extend climate tests for nibe heatpump (#103522)

This commit is contained in:
Joakim Plate 2023-11-08 12:40:28 +01:00 committed by GitHub
parent 3697567f18
commit 0a2a699133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 745 additions and 30 deletions

View File

@ -819,7 +819,6 @@ omit =
homeassistant/components/nfandroidtv/__init__.py homeassistant/components/nfandroidtv/__init__.py
homeassistant/components/nfandroidtv/notify.py homeassistant/components/nfandroidtv/notify.py
homeassistant/components/nibe_heatpump/__init__.py homeassistant/components/nibe_heatpump/__init__.py
homeassistant/components/nibe_heatpump/climate.py
homeassistant/components/nibe_heatpump/binary_sensor.py homeassistant/components/nibe_heatpump/binary_sensor.py
homeassistant/components/nibe_heatpump/select.py homeassistant/components/nibe_heatpump/select.py
homeassistant/components/nibe_heatpump/sensor.py homeassistant/components/nibe_heatpump/sensor.py

View File

@ -24,7 +24,6 @@ from homeassistant.components.climate import (
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
@ -48,10 +47,7 @@ async def async_setup_entry(
coordinator: Coordinator = hass.data[DOMAIN][config_entry.entry_id] coordinator: Coordinator = hass.data[DOMAIN][config_entry.entry_id]
main_unit = UNIT_COILGROUPS.get(coordinator.series, {}).get("main") main_unit = UNIT_COILGROUPS[coordinator.series]["main"]
if not main_unit:
LOGGER.debug("Skipping climates - no main unit found")
return
def climate_systems(): def climate_systems():
for key, group in CLIMATE_COILGROUPS.get(coordinator.series, ()).items(): for key, group in CLIMATE_COILGROUPS.get(coordinator.series, ()).items():
@ -128,9 +124,6 @@ class NibeClimateEntity(CoordinatorEntity[Coordinator], ClimateEntity):
@callback @callback
def _handle_coordinator_update(self) -> None: def _handle_coordinator_update(self) -> None:
if not self.coordinator.data:
return
def _get_value(coil: Coil) -> int | str | float | None: def _get_value(coil: Coil) -> int | str | float | None:
return self.coordinator.get_coil_value(coil) return self.coordinator.get_coil_value(coil)
@ -179,7 +172,7 @@ class NibeClimateEntity(CoordinatorEntity[Coordinator], ClimateEntity):
else: else:
self._attr_hvac_action = HVACAction.IDLE self._attr_hvac_action = HVACAction.IDLE
else: else:
self._attr_hvac_action = None self._attr_hvac_action = HVACAction.OFF
self.async_write_ha_state() self.async_write_ha_state()
@ -247,4 +240,4 @@ class NibeClimateEntity(CoordinatorEntity[Coordinator], ClimateEntity):
) )
await coordinator.async_write_coil(self._coil_use_room_sensor, "OFF") await coordinator.async_write_coil(self._coil_use_room_sensor, "OFF")
else: else:
raise HomeAssistantError(f"{hvac_mode} mode not supported for {self.name}") raise ValueError(f"{hvac_mode} mode not supported for {self.name}")

View File

@ -1,5 +1,391 @@
# serializer version: 1 # serializer version: 1
# name: test_basic[Model.S320-s1-climate.climate_system_s1][1. initial] # name: test_active_accessory[Model.F1155-s2-climate.climate_system_s2][initial]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_active_accessory[Model.F1155-s2-climate.climate_system_s2][unavailable (not supported)]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Climate System S2',
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_step': 0.5,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_active_accessory[Model.F1155-s3-climate.climate_system_s3][initial]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S3',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s3',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_active_accessory[Model.F1155-s3-climate.climate_system_s3][unavailable (not supported)]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Climate System S3',
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_step': 0.5,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s3',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_active_accessory[Model.S320-s2-climate.climate_system_21][initial]
None
# ---
# name: test_active_accessory[Model.S320-s2-climate.climate_system_s1][initial]
None
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][cooling]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.COOLING: 'cooling'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][heating (auto)]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.HEATING: 'heating'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][heating (only)]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.HEATING: 'heating'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': 21.0,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
})
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][heating]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.HEATING: 'heating'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][idle (mixing valve)]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][initial]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][off (auto)]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.OFF: 'off'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---
# name: test_basic[Model.F1155-s2-climate.climate_system_s2][unavailable]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S2',
'hvac_action': <HVACAction.OFF: 'off'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][cooling]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S1',
'hvac_action': <HVACAction.COOLING: 'cooling'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][heating (auto)]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S1',
'hvac_action': <HVACAction.HEATING: 'heating'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][heating (only)]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S1',
'hvac_action': <HVACAction.HEATING: 'heating'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': 21.0,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
})
# ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][heating]
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'current_temperature': 20.5, 'current_temperature': 20.5,
@ -25,7 +411,7 @@
'state': 'heat_cool', 'state': 'heat_cool',
}) })
# --- # ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][2. idle] # name: test_basic[Model.S320-s1-climate.climate_system_s1][idle (mixing valve)]
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'current_temperature': 20.5, 'current_temperature': 20.5,
@ -51,3 +437,81 @@
'state': 'heat_cool', 'state': 'heat_cool',
}) })
# --- # ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][initial]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S1',
'hvac_action': <HVACAction.IDLE: 'idle'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'heat_cool',
})
# ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][off (auto)]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S1',
'hvac_action': <HVACAction.OFF: 'off'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---
# name: test_basic[Model.S320-s1-climate.climate_system_s1][unavailable]
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.5,
'friendly_name': 'Climate System S1',
'hvac_action': <HVACAction.OFF: 'off'>,
'hvac_modes': list([
<HVACMode.AUTO: 'auto'>,
<HVACMode.HEAT: 'heat'>,
<HVACMode.HEAT_COOL: 'heat_cool'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'climate.climate_system_s1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---

View File

@ -1,13 +1,29 @@
"""Test the Nibe Heat Pump config flow.""" """Test the Nibe Heat Pump config flow."""
from typing import Any from typing import Any
from unittest.mock import patch from unittest.mock import call, patch
from nibe.coil_groups import CLIMATE_COILGROUPS, UNIT_COILGROUPS from nibe.coil import CoilData
from nibe.coil_groups import (
CLIMATE_COILGROUPS,
UNIT_COILGROUPS,
ClimateCoilGroup,
UnitCoilGroup,
)
from nibe.heatpump import Model from nibe.heatpump import Model
import pytest import pytest
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.const import Platform from homeassistant.components.climate import (
ATTR_HVAC_MODE,
ATTR_TARGET_TEMP_HIGH,
ATTR_TARGET_TEMP_LOW,
ATTR_TEMPERATURE,
DOMAIN as PLATFORM_DOMAIN,
SERVICE_SET_HVAC_MODE,
SERVICE_SET_TEMPERATURE,
HVACMode,
)
from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from . import MockConnection, async_add_model from . import MockConnection, async_add_model
@ -20,10 +36,31 @@ async def fixture_single_platform():
yield yield
def _setup_climate_group(
coils: dict[int, Any], model: Model, climate_id: str
) -> tuple[ClimateCoilGroup, UnitCoilGroup]:
"""Initialize coils for a climate group, with some default values."""
climate = CLIMATE_COILGROUPS[model.series][climate_id]
unit = UNIT_COILGROUPS[model.series]["main"]
if climate.active_accessory is not None:
coils[climate.active_accessory] = "ON"
coils[climate.current] = 20.5
coils[climate.setpoint_heat] = 21.0
coils[climate.setpoint_cool] = 30.0
coils[climate.mixing_valve_state] = 20
coils[climate.use_room_sensor] = "ON"
coils[unit.prio] = "OFF"
coils[unit.cooling_with_room_sensor] = "ON"
return climate, unit
@pytest.mark.parametrize( @pytest.mark.parametrize(
("model", "climate_id", "entity_id"), ("model", "climate_id", "entity_id"),
[ [
(Model.S320, "s1", "climate.climate_system_s1"), (Model.S320, "s1", "climate.climate_system_s1"),
(Model.F1155, "s2", "climate.climate_system_s2"),
], ],
) )
async def test_basic( async def test_basic(
@ -37,22 +74,244 @@ async def test_basic(
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test setting of value.""" """Test setting of value."""
climate = CLIMATE_COILGROUPS[model.series][climate_id] climate, unit = _setup_climate_group(coils, model, climate_id)
unit = UNIT_COILGROUPS[model.series]["main"]
if climate.active_accessory is not None:
coils[climate.active_accessory] = "ON"
coils[climate.current] = 20.5
coils[climate.setpoint_heat] = 21.0
coils[climate.setpoint_cool] = 30.0
coils[climate.mixing_valve_state] = "ON"
coils[climate.use_room_sensor] = "ON"
coils[unit.prio] = "HEAT"
coils[unit.cooling_with_room_sensor] = "ON"
await async_add_model(hass, model) await async_add_model(hass, model)
assert hass.states.get(entity_id) == snapshot(name="1. initial") assert hass.states.get(entity_id) == snapshot(name="initial")
mock_connection.mock_coil_update(unit.prio, "OFF") mock_connection.mock_coil_update(unit.prio, "COOLING")
assert hass.states.get(entity_id) == snapshot(name="cooling")
assert hass.states.get(entity_id) == snapshot(name="2. idle") mock_connection.mock_coil_update(unit.prio, "HEAT")
assert hass.states.get(entity_id) == snapshot(name="heating")
mock_connection.mock_coil_update(climate.mixing_valve_state, 30)
assert hass.states.get(entity_id) == snapshot(name="idle (mixing valve)")
mock_connection.mock_coil_update(climate.mixing_valve_state, 20)
mock_connection.mock_coil_update(unit.cooling_with_room_sensor, "OFF")
assert hass.states.get(entity_id) == snapshot(name="heating (only)")
mock_connection.mock_coil_update(climate.use_room_sensor, "OFF")
assert hass.states.get(entity_id) == snapshot(name="heating (auto)")
mock_connection.mock_coil_update(unit.prio, None)
assert hass.states.get(entity_id) == snapshot(name="off (auto)")
coils.clear()
assert hass.states.get(entity_id) == snapshot(name="unavailable")
@pytest.mark.parametrize(
("model", "climate_id", "entity_id"),
[
(Model.F1155, "s2", "climate.climate_system_s2"),
(Model.F1155, "s3", "climate.climate_system_s3"),
],
)
async def test_active_accessory(
hass: HomeAssistant,
mock_connection: MockConnection,
model: Model,
climate_id: str,
entity_id: str,
coils: dict[int, Any],
entity_registry_enabled_by_default: None,
snapshot: SnapshotAssertion,
) -> None:
"""Test climate groups that can be deactivated by configuration."""
climate, unit = _setup_climate_group(coils, model, climate_id)
await async_add_model(hass, model)
assert hass.states.get(entity_id) == snapshot(name="initial")
mock_connection.mock_coil_update(climate.active_accessory, "OFF")
assert hass.states.get(entity_id) == snapshot(name="unavailable (not supported)")
@pytest.mark.parametrize(
("model", "climate_id", "entity_id"),
[
(Model.S320, "s1", "climate.climate_system_s1"),
(Model.F1155, "s2", "climate.climate_system_s2"),
],
)
async def test_set_temperature(
hass: HomeAssistant,
mock_connection: MockConnection,
model: Model,
climate_id: str,
entity_id: str,
coils: dict[int, Any],
entity_registry_enabled_by_default: None,
snapshot: SnapshotAssertion,
) -> None:
"""Test setting temperature."""
climate, _ = _setup_climate_group(coils, model, climate_id)
await async_add_model(hass, model)
coil_setpoint_heat = mock_connection.heatpump.get_coil_by_address(
climate.setpoint_heat
)
coil_setpoint_cool = mock_connection.heatpump.get_coil_by_address(
climate.setpoint_cool
)
await hass.services.async_call(
PLATFORM_DOMAIN,
SERVICE_SET_TEMPERATURE,
{
ATTR_ENTITY_ID: entity_id,
ATTR_TEMPERATURE: 22,
ATTR_HVAC_MODE: HVACMode.HEAT,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_connection.write_coil.mock_calls == [
call(CoilData(coil_setpoint_heat, 22))
]
mock_connection.write_coil.reset_mock()
await hass.services.async_call(
PLATFORM_DOMAIN,
SERVICE_SET_TEMPERATURE,
{
ATTR_ENTITY_ID: entity_id,
ATTR_TEMPERATURE: 22,
ATTR_HVAC_MODE: HVACMode.COOL,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_connection.write_coil.mock_calls == [
call(CoilData(coil_setpoint_cool, 22))
]
mock_connection.write_coil.reset_mock()
with pytest.raises(ValueError):
await hass.services.async_call(
PLATFORM_DOMAIN,
SERVICE_SET_TEMPERATURE,
{
ATTR_ENTITY_ID: entity_id,
ATTR_TEMPERATURE: 22,
},
blocking=True,
)
await hass.services.async_call(
PLATFORM_DOMAIN,
SERVICE_SET_TEMPERATURE,
{
ATTR_ENTITY_ID: entity_id,
ATTR_TARGET_TEMP_HIGH: 30,
ATTR_TARGET_TEMP_LOW: 22,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_connection.write_coil.mock_calls == [
call(CoilData(coil_setpoint_heat, 22)),
call(CoilData(coil_setpoint_cool, 30)),
]
mock_connection.write_coil.reset_mock()
@pytest.mark.parametrize(
("hvac_mode", "cooling_with_room_sensor", "use_room_sensor"),
[
(HVACMode.HEAT_COOL, "ON", "ON"),
(HVACMode.HEAT, "OFF", "ON"),
(HVACMode.AUTO, "OFF", "OFF"),
],
)
@pytest.mark.parametrize(
("model", "climate_id", "entity_id"),
[
(Model.S320, "s1", "climate.climate_system_s1"),
(Model.F1155, "s2", "climate.climate_system_s2"),
],
)
async def test_set_hvac_mode(
hass: HomeAssistant,
mock_connection: MockConnection,
model: Model,
climate_id: str,
entity_id: str,
cooling_with_room_sensor: str,
use_room_sensor: str,
hvac_mode: HVACMode,
coils: dict[int, Any],
entity_registry_enabled_by_default: None,
) -> None:
"""Test setting a hvac mode."""
climate, unit = _setup_climate_group(coils, model, climate_id)
await async_add_model(hass, model)
coil_use_room_sensor = mock_connection.heatpump.get_coil_by_address(
climate.use_room_sensor
)
coil_cooling_with_room_sensor = mock_connection.heatpump.get_coil_by_address(
unit.cooling_with_room_sensor
)
await hass.services.async_call(
PLATFORM_DOMAIN,
SERVICE_SET_HVAC_MODE,
{
ATTR_ENTITY_ID: entity_id,
ATTR_HVAC_MODE: hvac_mode,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_connection.write_coil.mock_calls == [
call(CoilData(coil_cooling_with_room_sensor, cooling_with_room_sensor)),
call(CoilData(coil_use_room_sensor, use_room_sensor)),
]
@pytest.mark.parametrize(
("model", "climate_id", "entity_id"),
[
(Model.S320, "s1", "climate.climate_system_s1"),
(Model.F1155, "s2", "climate.climate_system_s2"),
],
)
async def test_set_invalid_hvac_mode(
hass: HomeAssistant,
mock_connection: MockConnection,
model: Model,
climate_id: str,
entity_id: str,
coils: dict[int, Any],
entity_registry_enabled_by_default: None,
) -> None:
"""Test setting an invalid hvac mode."""
_setup_climate_group(coils, model, climate_id)
await async_add_model(hass, model)
with pytest.raises(ValueError):
await hass.services.async_call(
PLATFORM_DOMAIN,
SERVICE_SET_HVAC_MODE,
{
ATTR_ENTITY_ID: entity_id,
ATTR_HVAC_MODE: HVACMode.DRY,
},
blocking=True,
)
await hass.async_block_till_done()
assert mock_connection.write_coil.mock_calls == []