mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Extend climate tests for nibe heatpump (#103522)
This commit is contained in:
parent
3697567f18
commit
0a2a699133
@ -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
|
||||||
|
@ -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}")
|
||||||
|
@ -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',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
@ -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 == []
|
||||||
|
Loading…
x
Reference in New Issue
Block a user