mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 14:57:09 +00:00
Allow a climate entity to have an independent on / off state attribute
This commit is contained in:
parent
a0fb6df5ba
commit
e2d9ca9cd9
@ -240,6 +240,7 @@ CACHED_PROPERTIES_WITH_ATTR_ = {
|
|||||||
"preset_mode",
|
"preset_mode",
|
||||||
"preset_modes",
|
"preset_modes",
|
||||||
"is_aux_heat",
|
"is_aux_heat",
|
||||||
|
"is_on",
|
||||||
"fan_mode",
|
"fan_mode",
|
||||||
"fan_modes",
|
"fan_modes",
|
||||||
"swing_mode",
|
"swing_mode",
|
||||||
@ -280,6 +281,7 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
_attr_hvac_mode: HVACMode | None
|
_attr_hvac_mode: HVACMode | None
|
||||||
_attr_hvac_modes: list[HVACMode]
|
_attr_hvac_modes: list[HVACMode]
|
||||||
_attr_is_aux_heat: bool | None
|
_attr_is_aux_heat: bool | None
|
||||||
|
_attr_is_on: bool | None
|
||||||
_attr_max_humidity: float = DEFAULT_MAX_HUMIDITY
|
_attr_max_humidity: float = DEFAULT_MAX_HUMIDITY
|
||||||
_attr_max_temp: float
|
_attr_max_temp: float
|
||||||
_attr_min_humidity: float = DEFAULT_MIN_HUMIDITY
|
_attr_min_humidity: float = DEFAULT_MIN_HUMIDITY
|
||||||
@ -357,6 +359,26 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
return HVACMode(hvac_mode).value # type: ignore[unreachable]
|
return HVACMode(hvac_mode).value # type: ignore[unreachable]
|
||||||
return hvac_mode.value
|
return hvac_mode.value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self) -> bool | None:
|
||||||
|
"""Return True if the climate is turned on.
|
||||||
|
|
||||||
|
The climate's on/off state can be be controlled independently
|
||||||
|
from the hvac_action and hvac_mode if the _attr_is_on attribute is set.
|
||||||
|
|
||||||
|
If the _attr_is_on attrubiute is set, then return that value.
|
||||||
|
Otherwise, return True if hvac_action is not None and not HVACAction.OFF.
|
||||||
|
Return None if hvac_action is None,
|
||||||
|
otherwise return True if hvac_mode is not HVACMode.OFF.
|
||||||
|
"""
|
||||||
|
if hasattr(self, "_attr_is_on"):
|
||||||
|
return self._attr_is_on
|
||||||
|
if self.hvac_action is not None:
|
||||||
|
return self.hvac_action != HVACAction.OFF
|
||||||
|
if self.hvac_mode is None:
|
||||||
|
return None
|
||||||
|
return self.hvac_mode != HVACMode.OFF
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def precision(self) -> float:
|
def precision(self) -> float:
|
||||||
"""Return the precision of the system."""
|
"""Return the precision of the system."""
|
||||||
|
@ -36,6 +36,7 @@ from homeassistant.components.climate.const import (
|
|||||||
SWING_HORIZONTAL_OFF,
|
SWING_HORIZONTAL_OFF,
|
||||||
SWING_HORIZONTAL_ON,
|
SWING_HORIZONTAL_ON,
|
||||||
ClimateEntityFeature,
|
ClimateEntityFeature,
|
||||||
|
HVACAction,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
|
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
|
||||||
@ -425,7 +426,7 @@ async def test_mode_validation(
|
|||||||
|
|
||||||
|
|
||||||
async def test_turn_on_off_toggle(hass: HomeAssistant) -> None:
|
async def test_turn_on_off_toggle(hass: HomeAssistant) -> None:
|
||||||
"""Test turn_on/turn_off/toggle methods."""
|
"""Test turn_on/turn_off/toggle methods and the is_on property."""
|
||||||
|
|
||||||
class MockClimateEntityTest(MockClimateEntity):
|
class MockClimateEntityTest(MockClimateEntity):
|
||||||
"""Mock Climate device."""
|
"""Mock Climate device."""
|
||||||
@ -440,20 +441,54 @@ async def test_turn_on_off_toggle(hass: HomeAssistant) -> None:
|
|||||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||||
"""Set new target hvac mode."""
|
"""Set new target hvac mode."""
|
||||||
self._attr_hvac_mode = hvac_mode
|
self._attr_hvac_mode = hvac_mode
|
||||||
|
self._attr_is_on = hvac_mode != HVACMode.OFF
|
||||||
|
|
||||||
climate = MockClimateEntityTest()
|
climate = MockClimateEntityTest()
|
||||||
climate.hass = hass
|
climate.hass = hass
|
||||||
|
|
||||||
|
assert climate.is_on is False
|
||||||
|
|
||||||
await climate.async_turn_on()
|
await climate.async_turn_on()
|
||||||
assert climate.hvac_mode == HVACMode.HEAT
|
assert climate.hvac_mode == HVACMode.HEAT
|
||||||
|
assert climate.is_on is True
|
||||||
|
|
||||||
await climate.async_turn_off()
|
await climate.async_turn_off()
|
||||||
assert climate.hvac_mode == HVACMode.OFF
|
assert climate.hvac_mode == HVACMode.OFF
|
||||||
|
assert climate.is_on is False
|
||||||
|
|
||||||
await climate.async_toggle()
|
await climate.async_toggle()
|
||||||
assert climate.hvac_mode == HVACMode.HEAT
|
assert climate.hvac_mode == HVACMode.HEAT
|
||||||
|
assert climate.is_on is True
|
||||||
await climate.async_toggle()
|
await climate.async_toggle()
|
||||||
assert climate.hvac_mode == HVACMode.OFF
|
assert climate.hvac_mode == HVACMode.OFF
|
||||||
|
assert climate.is_on is False
|
||||||
|
|
||||||
|
# Test is_on property in case _attr_is_on is not set
|
||||||
|
delattr(climate, "_attr_is_on")
|
||||||
|
|
||||||
|
# When hvac_action is set, is_on should depend on it
|
||||||
|
climate._attr_hvac_mode = HVACMode.AUTO
|
||||||
|
climate._attr_hvac_action = HVACAction.HEATING
|
||||||
|
assert climate.hvac_mode == HVACMode.AUTO
|
||||||
|
assert climate.hvac_action == HVACAction.HEATING
|
||||||
|
assert climate.is_on is True
|
||||||
|
climate._attr_hvac_action = HVACAction.OFF
|
||||||
|
assert climate.hvac_action == HVACAction.OFF
|
||||||
|
assert climate.is_on is False
|
||||||
|
|
||||||
|
# When hvac_action is not used and hvac_mode is set, is_on should depend on it
|
||||||
|
climate._attr_hvac_action = None
|
||||||
|
assert climate.hvac_action is None
|
||||||
|
assert climate.hvac_mode == HVACMode.AUTO
|
||||||
|
assert climate.is_on is True
|
||||||
|
climate._attr_hvac_mode = HVACMode.OFF
|
||||||
|
assert climate.hvac_mode == HVACMode.OFF
|
||||||
|
assert climate.is_on is False
|
||||||
|
|
||||||
|
# If no mode or action is set and _attr_is_on is not set, is_on should be None
|
||||||
|
climate._attr_hvac_action = None
|
||||||
|
climate._attr_hvac_mode = None
|
||||||
|
assert climate.is_on is None
|
||||||
|
|
||||||
|
|
||||||
async def test_sync_toggle(hass: HomeAssistant) -> None:
|
async def test_sync_toggle(hass: HomeAssistant) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user