1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-17 23:53:49 +01:00

Adjust light triggers (#166263)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Erik Montnemery
2026-03-23 16:48:33 +01:00
committed by GitHub
parent 31c7553e68
commit a45da11ec1
4 changed files with 134 additions and 6 deletions

View File

@@ -30,10 +30,10 @@ BRIGHTNESS_DOMAIN_SPECS = {
TRIGGERS: dict[str, type[Trigger]] = {
"brightness_changed": make_entity_numerical_state_changed_trigger(
BRIGHTNESS_DOMAIN_SPECS
BRIGHTNESS_DOMAIN_SPECS, valid_unit="%"
),
"brightness_crossed_threshold": make_entity_numerical_state_crossed_threshold_trigger(
BRIGHTNESS_DOMAIN_SPECS
BRIGHTNESS_DOMAIN_SPECS, valid_unit="%"
),
"turned_off": make_entity_target_state_trigger(DOMAIN, STATE_OFF),
"turned_on": make_entity_target_state_trigger(DOMAIN, STATE_ON),

View File

@@ -30,10 +30,12 @@
selector:
entity:
filter:
domain:
- input_number
- number
- sensor
- domain: input_number
unit_of_measurement: "%"
- domain: number
unit_of_measurement: "%"
- domain: sensor
unit_of_measurement: "%"
translation_key: number_or_entity
turned_on: *trigger_common

View File

@@ -12,6 +12,7 @@ from homeassistant.const import (
ATTR_DEVICE_ID,
ATTR_FLOOR_ID,
ATTR_LABEL_ID,
ATTR_UNIT_OF_MEASUREMENT,
CONF_ABOVE,
CONF_BELOW,
CONF_CONDITION,
@@ -1160,3 +1161,78 @@ async def assert_trigger_behavior_last(
set_or_remove_state(hass, excluded_entity_id, excluded_state)
await hass.async_block_till_done()
assert len(service_calls) == 0
async def assert_trigger_ignores_limit_entities_with_wrong_unit(
hass: HomeAssistant,
*,
service_calls: list[ServiceCall],
trigger: str,
trigger_options: dict[str, Any],
entity_id: str,
entity_state: str,
reset_attributes: dict[str, Any],
trigger_attributes: dict[str, Any],
limit_entities: list[tuple[str, str]],
correct_unit: str,
wrong_unit: str,
) -> None:
"""Test that a trigger does not fire when limit entities have the wrong unit.
Verifies that ALL limit entities must have the correct unit_of_measurement
for the trigger to fire. Limit entities are fixed one at a time; the trigger
should only fire once all of them have the correct unit.
Args:
trigger: The trigger key (e.g. "light.brightness_crossed_threshold").
trigger_options: Trigger options dict (must already contain the limit
entity IDs as values).
entity_id: The entity being observed by the trigger.
entity_state: The state string for the observed entity (e.g. STATE_ON).
reset_attributes: Attributes to set on the entity before re-triggering.
trigger_attributes: Attributes that should cause the trigger to fire.
limit_entities: List of (entity_id, value) tuples for the limit entities.
correct_unit: The unit that the trigger expects (e.g. "%").
wrong_unit: A unit that the trigger should reject (e.g. "lx").
"""
# Set up entity in triggering state
hass.states.async_set(entity_id, entity_state, trigger_attributes)
# Set up all limit entities with the wrong unit
for limit_entity_id, limit_value in limit_entities:
hass.states.async_set(
limit_entity_id,
limit_value,
{ATTR_UNIT_OF_MEASUREMENT: wrong_unit},
)
await hass.async_block_till_done()
await arm_trigger(hass, trigger, trigger_options, {CONF_ENTITY_ID: [entity_id]})
# Cycle entity state - should NOT fire (all limit entities have wrong unit)
hass.states.async_set(entity_id, entity_state, reset_attributes)
await hass.async_block_till_done()
hass.states.async_set(entity_id, entity_state, trigger_attributes)
await hass.async_block_till_done()
assert len(service_calls) == 0
# Fix limit entities one at a time; trigger should not fire until all are fixed
for i, (limit_entity_id, limit_value) in enumerate(limit_entities):
hass.states.async_set(
limit_entity_id,
limit_value,
{ATTR_UNIT_OF_MEASUREMENT: correct_unit},
)
await hass.async_block_till_done()
hass.states.async_set(entity_id, entity_state, reset_attributes)
await hass.async_block_till_done()
hass.states.async_set(entity_id, entity_state, trigger_attributes)
await hass.async_block_till_done()
if i < len(limit_entities) - 1:
# Not all limits fixed yet - should not fire
assert len(service_calls) == 0
else:
# All limits fixed - should fire
assert len(service_calls) == 1

View File

@@ -20,6 +20,7 @@ from tests.components.common import (
assert_trigger_behavior_first,
assert_trigger_behavior_last,
assert_trigger_gated_by_labs_flag,
assert_trigger_ignores_limit_entities_with_wrong_unit,
parametrize_target_entities,
parametrize_trigger_states,
target_entities,
@@ -423,3 +424,52 @@ async def test_light_state_attribute_trigger_behavior_last(
trigger_options=trigger_options,
states=states,
)
@pytest.mark.usefixtures("enable_labs_preview_features")
@pytest.mark.parametrize(
("trigger", "trigger_options", "limit_entities"),
[
(
"light.brightness_changed",
{
CONF_ABOVE: "sensor.brightness_above",
CONF_BELOW: "sensor.brightness_below",
},
["sensor.brightness_above", "sensor.brightness_below"],
),
(
"light.brightness_crossed_threshold",
{
CONF_THRESHOLD_TYPE: ThresholdType.BETWEEN,
CONF_LOWER_LIMIT: "sensor.brightness_lower",
CONF_UPPER_LIMIT: "sensor.brightness_upper",
},
["sensor.brightness_lower", "sensor.brightness_upper"],
),
],
)
async def test_light_trigger_ignores_limit_entity_with_wrong_unit(
hass: HomeAssistant,
service_calls: list[ServiceCall],
trigger: str,
trigger_options: dict[str, Any],
limit_entities: list[str],
) -> None:
"""Test numerical triggers do not fire if limit entities have the wrong unit."""
await assert_trigger_ignores_limit_entities_with_wrong_unit(
hass,
service_calls=service_calls,
trigger=trigger,
trigger_options=trigger_options,
entity_id="light.test_light",
entity_state=STATE_ON,
reset_attributes={ATTR_BRIGHTNESS: 0},
trigger_attributes={ATTR_BRIGHTNESS: 128},
limit_entities=[
(limit_entities[0], "10"),
(limit_entities[1], "90"),
],
correct_unit="%",
wrong_unit="lx",
)