mirror of
https://github.com/home-assistant/core.git
synced 2026-05-08 17:49:37 +01:00
Exclude incompatible entities from temperature automations (#169901)
This commit is contained in:
@@ -46,6 +46,21 @@ class TemperatureCondition(EntityNumericalConditionWithUnitBase):
|
||||
_domain_specs = TEMPERATURE_DOMAIN_SPECS
|
||||
_unit_converter = TemperatureConverter
|
||||
|
||||
def _should_include(self, state: State) -> bool:
|
||||
"""Skip attribute-source entities that lack the temperature attribute.
|
||||
|
||||
Mirrors the temperature trigger: for climate / water_heater /
|
||||
weather (attribute-based), the entity is filtered when the source
|
||||
attribute is absent; sensor entities (state-value-based) fall
|
||||
through to the base impl.
|
||||
"""
|
||||
if not super()._should_include(state):
|
||||
return False
|
||||
domain_spec = self._domain_specs[state.domain]
|
||||
if domain_spec.value_source is None:
|
||||
return True
|
||||
return state.attributes.get(domain_spec.value_source) is not None
|
||||
|
||||
def _get_entity_unit(self, entity_state: State) -> str | None:
|
||||
"""Get the temperature unit of an entity from its state."""
|
||||
if entity_state.domain == SENSOR_DOMAIN:
|
||||
|
||||
@@ -46,6 +46,23 @@ class _TemperatureTriggerMixin(EntityNumericalStateTriggerWithUnitBase):
|
||||
_domain_specs = TEMPERATURE_DOMAIN_SPECS
|
||||
_unit_converter = TemperatureConverter
|
||||
|
||||
def _should_include(self, state: State) -> bool:
|
||||
"""Skip attribute-source entities that lack the temperature attribute.
|
||||
|
||||
For domains whose tracked value comes from an attribute
|
||||
(climate / water_heater / weather), require the attribute to be
|
||||
present; otherwise the all/count check would treat an entity that
|
||||
cannot report a temperature as a non-match and block behavior=last.
|
||||
Sensor entities source their value from `state.state`, so they
|
||||
fall through to the base impl.
|
||||
"""
|
||||
if not super()._should_include(state):
|
||||
return False
|
||||
domain_spec = self._domain_specs[state.domain]
|
||||
if domain_spec.value_source is None:
|
||||
return True
|
||||
return state.attributes.get(domain_spec.value_source) is not None
|
||||
|
||||
def _get_entity_unit(self, state: State) -> str | None:
|
||||
"""Get the temperature unit of an entity from its state."""
|
||||
if state.domain == SENSOR_DOMAIN:
|
||||
|
||||
@@ -180,6 +180,7 @@ async def test_temperature_sensor_condition_behavior_all(
|
||||
HVACMode.AUTO,
|
||||
"current_temperature",
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
)
|
||||
async def test_temperature_climate_condition_behavior_any(
|
||||
@@ -217,6 +218,7 @@ async def test_temperature_climate_condition_behavior_any(
|
||||
HVACMode.AUTO,
|
||||
"current_temperature",
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
)
|
||||
async def test_temperature_climate_condition_behavior_all(
|
||||
@@ -254,6 +256,7 @@ async def test_temperature_climate_condition_behavior_all(
|
||||
"eco",
|
||||
"current_temperature",
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
)
|
||||
async def test_temperature_water_heater_condition_behavior_any(
|
||||
@@ -291,6 +294,7 @@ async def test_temperature_water_heater_condition_behavior_any(
|
||||
"eco",
|
||||
"current_temperature",
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
)
|
||||
async def test_temperature_water_heater_condition_behavior_all(
|
||||
@@ -329,6 +333,7 @@ async def test_temperature_water_heater_condition_behavior_all(
|
||||
"temperature",
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
unit_attributes=_WEATHER_UNIT_ATTRIBUTES,
|
||||
attribute_required=True,
|
||||
),
|
||||
)
|
||||
async def test_temperature_weather_condition_behavior_any(
|
||||
@@ -367,6 +372,7 @@ async def test_temperature_weather_condition_behavior_any(
|
||||
"temperature",
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
unit_attributes=_WEATHER_UNIT_ATTRIBUTES,
|
||||
attribute_required=True,
|
||||
),
|
||||
)
|
||||
async def test_temperature_weather_condition_behavior_all(
|
||||
|
||||
@@ -263,12 +263,14 @@ async def test_temperature_trigger_sensor_crossed_threshold_behavior_last(
|
||||
HVACMode.AUTO,
|
||||
CLIMATE_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
*parametrize_numerical_attribute_crossed_threshold_trigger_states(
|
||||
"temperature.crossed_threshold",
|
||||
HVACMode.AUTO,
|
||||
CLIMATE_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -308,6 +310,7 @@ async def test_temperature_trigger_climate_behavior_any(
|
||||
HVACMode.AUTO,
|
||||
CLIMATE_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -347,6 +350,7 @@ async def test_temperature_trigger_climate_crossed_threshold_behavior_first(
|
||||
HVACMode.AUTO,
|
||||
CLIMATE_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -389,12 +393,14 @@ async def test_temperature_trigger_climate_crossed_threshold_behavior_last(
|
||||
"eco",
|
||||
WATER_HEATER_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
*parametrize_numerical_attribute_crossed_threshold_trigger_states(
|
||||
"temperature.crossed_threshold",
|
||||
"eco",
|
||||
WATER_HEATER_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -434,6 +440,7 @@ async def test_temperature_trigger_water_heater_behavior_any(
|
||||
"eco",
|
||||
WATER_HEATER_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -473,6 +480,7 @@ async def test_temperature_trigger_water_heater_crossed_threshold_behavior_first
|
||||
"eco",
|
||||
WATER_HEATER_ATTR_CURRENT_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -516,6 +524,7 @@ async def test_temperature_trigger_water_heater_crossed_threshold_behavior_last(
|
||||
ATTR_WEATHER_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
unit_attributes=_WEATHER_UNIT_ATTRIBUTES,
|
||||
attribute_required=True,
|
||||
),
|
||||
*parametrize_numerical_attribute_crossed_threshold_trigger_states(
|
||||
"temperature.crossed_threshold",
|
||||
@@ -523,6 +532,7 @@ async def test_temperature_trigger_water_heater_crossed_threshold_behavior_last(
|
||||
ATTR_WEATHER_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
unit_attributes=_WEATHER_UNIT_ATTRIBUTES,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -563,6 +573,7 @@ async def test_temperature_trigger_weather_behavior_any(
|
||||
ATTR_WEATHER_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
unit_attributes=_WEATHER_UNIT_ATTRIBUTES,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -603,6 +614,7 @@ async def test_temperature_trigger_weather_crossed_threshold_behavior_first(
|
||||
ATTR_WEATHER_TEMPERATURE,
|
||||
threshold_unit=UnitOfTemperature.CELSIUS,
|
||||
unit_attributes=_WEATHER_UNIT_ATTRIBUTES,
|
||||
attribute_required=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user