Add hvac_modes property to Plugwise (#102636)

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
Bouwe Westerdijk 2023-10-24 17:53:55 +02:00 committed by GitHub
parent 9600c7fac1
commit 8c3ae1b30c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 62 deletions

View File

@ -66,13 +66,6 @@ class PlugwiseClimateEntity(PlugwiseEntity, ClimateEntity):
self._attr_supported_features |= ClimateEntityFeature.PRESET_MODE self._attr_supported_features |= ClimateEntityFeature.PRESET_MODE
self._attr_preset_modes = presets self._attr_preset_modes = presets
# Determine hvac modes and current hvac mode
self._attr_hvac_modes = [HVACMode.HEAT]
if self.coordinator.data.gateway["cooling_present"]:
self._attr_hvac_modes = [HVACMode.HEAT_COOL]
if self.device["available_schedules"] != ["None"]:
self._attr_hvac_modes.append(HVACMode.AUTO)
self._attr_min_temp = self.device["thermostat"]["lower_bound"] self._attr_min_temp = self.device["thermostat"]["lower_bound"]
self._attr_max_temp = self.device["thermostat"]["upper_bound"] self._attr_max_temp = self.device["thermostat"]["upper_bound"]
# Ensure we don't drop below 0.1 # Ensure we don't drop below 0.1
@ -117,6 +110,18 @@ class PlugwiseClimateEntity(PlugwiseEntity, ClimateEntity):
return HVACMode.HEAT return HVACMode.HEAT
return HVACMode(mode) return HVACMode(mode)
@property
def hvac_modes(self) -> list[HVACMode]:
"""Return the list of available HVACModes."""
hvac_modes = [HVACMode.HEAT]
if self.coordinator.data.gateway["cooling_present"]:
hvac_modes = [HVACMode.HEAT_COOL]
if self.device["available_schedules"] != ["None"]:
hvac_modes.append(HVACMode.AUTO)
return hvac_modes
@property @property
def hvac_action(self) -> HVACAction | None: def hvac_action(self) -> HVACAction | None:
"""Return the current running hvac operation if supported.""" """Return the current running hvac operation if supported."""

View File

@ -1,14 +1,17 @@
"""Tests for the Plugwise Climate integration.""" """Tests for the Plugwise Climate integration."""
from unittest.mock import MagicMock
from datetime import timedelta
from unittest.mock import MagicMock, patch
from plugwise.exceptions import PlugwiseError from plugwise.exceptions import PlugwiseError
import pytest import pytest
from homeassistant.components.climate import HVACMode from homeassistant.components.climate.const import HVACMode
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.util.dt import utcnow
from tests.common import MockConfigEntry from tests.common import MockConfigEntry, async_fire_time_changed
async def test_adam_climate_entity_attributes( async def test_adam_climate_entity_attributes(
@ -87,8 +90,6 @@ async def test_adam_climate_adjust_negative_testing(
hass: HomeAssistant, mock_smile_adam: MagicMock, init_integration: MockConfigEntry hass: HomeAssistant, mock_smile_adam: MagicMock, init_integration: MockConfigEntry
) -> None: ) -> None:
"""Test exceptions of climate entities.""" """Test exceptions of climate entities."""
mock_smile_adam.set_preset.side_effect = PlugwiseError
mock_smile_adam.set_schedule_state.side_effect = PlugwiseError
mock_smile_adam.set_temperature.side_effect = PlugwiseError mock_smile_adam.set_temperature.side_effect = PlugwiseError
with pytest.raises(HomeAssistantError): with pytest.raises(HomeAssistantError):
@ -99,25 +100,6 @@ async def test_adam_climate_adjust_negative_testing(
blocking=True, blocking=True,
) )
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
"climate",
"set_preset_mode",
{"entity_id": "climate.zone_thermostat_jessie", "preset_mode": "home"},
blocking=True,
)
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
"climate",
"set_hvac_mode",
{
"entity_id": "climate.zone_thermostat_jessie",
"hvac_mode": HVACMode.AUTO,
},
blocking=True,
)
async def test_adam_climate_entity_climate_changes( async def test_adam_climate_entity_climate_changes(
hass: HomeAssistant, mock_smile_adam: MagicMock, init_integration: MockConfigEntry hass: HomeAssistant, mock_smile_adam: MagicMock, init_integration: MockConfigEntry
@ -129,7 +111,6 @@ async def test_adam_climate_entity_climate_changes(
{"entity_id": "climate.zone_lisa_wk", "temperature": 25}, {"entity_id": "climate.zone_lisa_wk", "temperature": 25},
blocking=True, blocking=True,
) )
assert mock_smile_adam.set_temperature.call_count == 1 assert mock_smile_adam.set_temperature.call_count == 1
mock_smile_adam.set_temperature.assert_called_with( mock_smile_adam.set_temperature.assert_called_with(
"c50f167537524366a5af7aa3942feb1e", {"setpoint": 25.0} "c50f167537524366a5af7aa3942feb1e", {"setpoint": 25.0}
@ -145,7 +126,6 @@ async def test_adam_climate_entity_climate_changes(
}, },
blocking=True, blocking=True,
) )
assert mock_smile_adam.set_temperature.call_count == 2 assert mock_smile_adam.set_temperature.call_count == 2
mock_smile_adam.set_temperature.assert_called_with( mock_smile_adam.set_temperature.assert_called_with(
"c50f167537524366a5af7aa3942feb1e", {"setpoint": 25.0} "c50f167537524366a5af7aa3942feb1e", {"setpoint": 25.0}
@ -165,7 +145,6 @@ async def test_adam_climate_entity_climate_changes(
{"entity_id": "climate.zone_lisa_wk", "preset_mode": "away"}, {"entity_id": "climate.zone_lisa_wk", "preset_mode": "away"},
blocking=True, blocking=True,
) )
assert mock_smile_adam.set_preset.call_count == 1 assert mock_smile_adam.set_preset.call_count == 1
mock_smile_adam.set_preset.assert_called_with( mock_smile_adam.set_preset.assert_called_with(
"c50f167537524366a5af7aa3942feb1e", "away" "c50f167537524366a5af7aa3942feb1e", "away"
@ -173,26 +152,13 @@ async def test_adam_climate_entity_climate_changes(
await hass.services.async_call( await hass.services.async_call(
"climate", "climate",
"set_temperature", "set_hvac_mode",
{"entity_id": "climate.zone_thermostat_jessie", "temperature": 25}, {"entity_id": "climate.zone_lisa_wk", "hvac_mode": "heat"},
blocking=True, blocking=True,
) )
assert mock_smile_adam.set_schedule_state.call_count == 2
assert mock_smile_adam.set_temperature.call_count == 3 mock_smile_adam.set_schedule_state.assert_called_with(
mock_smile_adam.set_temperature.assert_called_with( "c50f167537524366a5af7aa3942feb1e", "GF7 Woonkamer", "off"
"82fa13f017d240daa0d0ea1775420f24", {"setpoint": 25.0}
)
await hass.services.async_call(
"climate",
"set_preset_mode",
{"entity_id": "climate.zone_thermostat_jessie", "preset_mode": "home"},
blocking=True,
)
assert mock_smile_adam.set_preset.call_count == 2
mock_smile_adam.set_preset.assert_called_with(
"82fa13f017d240daa0d0ea1775420f24", "home"
) )
with pytest.raises(HomeAssistantError): with pytest.raises(HomeAssistantError):
@ -270,7 +236,9 @@ async def test_anna_3_climate_entity_attributes(
async def test_anna_climate_entity_climate_changes( async def test_anna_climate_entity_climate_changes(
hass: HomeAssistant, mock_smile_anna: MagicMock, init_integration: MockConfigEntry hass: HomeAssistant,
mock_smile_anna: MagicMock,
init_integration: MockConfigEntry,
) -> None: ) -> None:
"""Test handling of user requests in anna climate device environment.""" """Test handling of user requests in anna climate device environment."""
await hass.services.async_call( await hass.services.async_call(
@ -279,7 +247,6 @@ async def test_anna_climate_entity_climate_changes(
{"entity_id": "climate.anna", "target_temp_high": 25, "target_temp_low": 20}, {"entity_id": "climate.anna", "target_temp_high": 25, "target_temp_low": 20},
blocking=True, blocking=True,
) )
assert mock_smile_anna.set_temperature.call_count == 1 assert mock_smile_anna.set_temperature.call_count == 1
mock_smile_anna.set_temperature.assert_called_with( mock_smile_anna.set_temperature.assert_called_with(
"c784ee9fdab44e1395b8dee7d7a497d5", "c784ee9fdab44e1395b8dee7d7a497d5",
@ -292,7 +259,6 @@ async def test_anna_climate_entity_climate_changes(
{"entity_id": "climate.anna", "preset_mode": "away"}, {"entity_id": "climate.anna", "preset_mode": "away"},
blocking=True, blocking=True,
) )
assert mock_smile_anna.set_preset.call_count == 1 assert mock_smile_anna.set_preset.call_count == 1
mock_smile_anna.set_preset.assert_called_with( mock_smile_anna.set_preset.assert_called_with(
"c784ee9fdab44e1395b8dee7d7a497d5", "away" "c784ee9fdab44e1395b8dee7d7a497d5", "away"
@ -301,24 +267,32 @@ async def test_anna_climate_entity_climate_changes(
await hass.services.async_call( await hass.services.async_call(
"climate", "climate",
"set_hvac_mode", "set_hvac_mode",
{"entity_id": "climate.anna", "hvac_mode": "heat"}, {"entity_id": "climate.anna", "hvac_mode": "auto"},
blocking=True, blocking=True,
) )
assert mock_smile_anna.set_temperature.call_count == 1
assert mock_smile_anna.set_schedule_state.call_count == 1 assert mock_smile_anna.set_schedule_state.call_count == 1
mock_smile_anna.set_schedule_state.assert_called_with( mock_smile_anna.set_schedule_state.assert_called_with(
"c784ee9fdab44e1395b8dee7d7a497d5", "standaard", "off" "c784ee9fdab44e1395b8dee7d7a497d5", "standaard", "on"
) )
await hass.services.async_call( await hass.services.async_call(
"climate", "climate",
"set_hvac_mode", "set_hvac_mode",
{"entity_id": "climate.anna", "hvac_mode": "auto"}, {"entity_id": "climate.anna", "hvac_mode": "heat"},
blocking=True, blocking=True,
) )
assert mock_smile_anna.set_schedule_state.call_count == 2 assert mock_smile_anna.set_schedule_state.call_count == 2
mock_smile_anna.set_schedule_state.assert_called_with( mock_smile_anna.set_schedule_state.assert_called_with(
"c784ee9fdab44e1395b8dee7d7a497d5", "standaard", "on" "c784ee9fdab44e1395b8dee7d7a497d5", "standaard", "off"
) )
data = mock_smile_anna.async_update.return_value
data.devices["3cb70739631c4d17a86b8b12e8a5161b"]["available_schedules"] = ["None"]
with patch(
"homeassistant.components.plugwise.coordinator.Smile.async_update",
return_value=data,
):
async_fire_time_changed(hass, utcnow() + timedelta(minutes=1))
await hass.async_block_till_done()
state = hass.states.get("climate.anna")
assert state.state == HVACMode.HEAT
assert state.attributes["hvac_modes"] == [HVACMode.HEAT]