diff --git a/homeassistant/components/homeassistant/triggers/numeric_state.py b/homeassistant/components/homeassistant/triggers/numeric_state.py index 55e875c90de..4f406de23ca 100644 --- a/homeassistant/components/homeassistant/triggers/numeric_state.py +++ b/homeassistant/components/homeassistant/triggers/numeric_state.py @@ -78,12 +78,16 @@ async def async_attach_trigger( attribute = config.get(CONF_ATTRIBUTE) job = HassJob(action) + _variables = {} + if automation_info: + _variables = automation_info.get("variables") or {} + if value_template is not None: value_template.hass = hass def variables(entity_id): """Return a dict with trigger variables.""" - return { + trigger_info = { "trigger": { "platform": "numeric_state", "entity_id": entity_id, @@ -92,6 +96,7 @@ async def async_attach_trigger( "attribute": attribute, } } + return {**_variables, **trigger_info} @callback def check_numeric_state(entity_id, from_s, to_s): diff --git a/tests/components/homeassistant/triggers/test_numeric_state.py b/tests/components/homeassistant/triggers/test_numeric_state.py index 979c5bad5d7..e58bccb0bcc 100644 --- a/tests/components/homeassistant/triggers/test_numeric_state.py +++ b/tests/components/homeassistant/triggers/test_numeric_state.py @@ -1647,3 +1647,93 @@ async def test_attribute_if_not_fires_on_entities_change_with_for_after_stop( async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) await hass.async_block_till_done() assert len(calls) == 1 + + +@pytest.mark.parametrize( + "above, below", + ((8, 12),), +) +async def test_variables_priority(hass, calls, above, below): + """Test an externally defined trigger variable is overridden.""" + hass.states.async_set("test.entity_1", 0) + hass.states.async_set("test.entity_2", 0) + await hass.async_block_till_done() + + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: { + "trigger_variables": {"trigger": "illegal"}, + "trigger": { + "platform": "numeric_state", + "entity_id": ["test.entity_1", "test.entity_2"], + "above": above, + "below": below, + "for": '{{ 5 if trigger.entity_id == "test.entity_1"' + " else 10 }}", + }, + "action": { + "service": "test.automation", + "data_template": { + "some": "{{ trigger.entity_id }} - {{ trigger.for }}" + }, + }, + } + }, + ) + await hass.async_block_till_done() + + utcnow = dt_util.utcnow() + with patch("homeassistant.util.dt.utcnow") as mock_utcnow: + mock_utcnow.return_value = utcnow + hass.states.async_set("test.entity_1", 9) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=1) + async_fire_time_changed(hass, mock_utcnow.return_value) + hass.states.async_set("test.entity_2", 9) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=1) + async_fire_time_changed(hass, mock_utcnow.return_value) + hass.states.async_set("test.entity_2", 15) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=1) + async_fire_time_changed(hass, mock_utcnow.return_value) + hass.states.async_set("test.entity_2", 9) + await hass.async_block_till_done() + assert len(calls) == 0 + mock_utcnow.return_value += timedelta(seconds=3) + async_fire_time_changed(hass, mock_utcnow.return_value) + await hass.async_block_till_done() + assert len(calls) == 1 + assert calls[0].data["some"] == "test.entity_1 - 0:00:05" + + +@pytest.mark.parametrize("multiplier", (1, 5)) +async def test_template_variable(hass, calls, multiplier): + """Test template variable.""" + hass.states.async_set("test.entity", "entity", {"test_attribute": [11, 15, 11]}) + await hass.async_block_till_done() + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: { + "trigger_variables": {"multiplier": multiplier}, + "trigger": { + "platform": "numeric_state", + "entity_id": "test.entity", + "value_template": "{{ state.attributes.test_attribute[2] * multiplier}}", + "below": 10, + }, + "action": {"service": "test.automation"}, + } + }, + ) + # 3 is below 10 + hass.states.async_set("test.entity", "entity", {"test_attribute": [11, 15, 3]}) + await hass.async_block_till_done() + if multiplier * 3 < 10: + assert len(calls) == 1 + else: + assert len(calls) == 0