Subscribe to state change events only if the template has entities (#39188)

pull/39250/head
J. Nick Koston 2020-08-25 17:20:04 -05:00 committed by GitHub
parent 68c0f770fe
commit 20398cc0a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 18 deletions

View File

@ -484,12 +484,6 @@ class _TrackTemplateResultInfo:
if self._info.exception:
return True
# There are no entities in the template
# to track so this template will
# re-render on EVERY state change
if not self._info.domains and not self._info.entities:
return True
return False
@callback

View File

@ -10,8 +10,10 @@ from homeassistant.const import (
STATE_ON,
STATE_UNAVAILABLE,
)
from homeassistant.core import CoreState
from homeassistant.core import CoreState, callback
from homeassistant.helpers.template import Template
from homeassistant.setup import ATTR_COMPONENT, async_setup_component, setup_component
import homeassistant.util.dt as dt_util
from tests.common import assert_setup_component, get_test_home_assistant
@ -694,3 +696,64 @@ async def test_unique_id(hass):
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
async def test_sun_renders_once_per_sensor(hass):
"""Test sun change renders the template only once per sensor."""
now = dt_util.utcnow()
hass.states.async_set(
"sun.sun", "above_horizon", {"elevation": 45.3, "next_rising": now}
)
await async_setup_component(
hass,
"sensor",
{
"sensor": {
"platform": "template",
"sensors": {
"solar_angle": {
"friendly_name": "Sun angle",
"unit_of_measurement": "degrees",
"value_template": "{{ state_attr('sun.sun', 'elevation') }}",
},
"sunrise": {
"value_template": "{{ state_attr('sun.sun', 'next_rising') }}"
},
},
}
},
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 3
assert hass.states.get("sensor.solar_angle").state == "45.3"
assert hass.states.get("sensor.sunrise").state == str(now)
async_render_calls = []
@callback
def _record_async_render(self, *args, **kwargs):
"""Catch async_render."""
async_render_calls.append(self.template)
return "mocked"
later = dt_util.utcnow()
with patch.object(Template, "async_render", _record_async_render):
hass.states.async_set("sun.sun", {"elevation": 50, "next_rising": later})
await hass.async_block_till_done()
assert hass.states.get("sensor.solar_angle").state == "mocked"
assert hass.states.get("sensor.sunrise").state == "mocked"
assert len(async_render_calls) == 2
assert set(async_render_calls) == {
"{{ state_attr('sun.sun', 'elevation') }}",
"{{ state_attr('sun.sun', 'next_rising') }}",
}

View File

@ -39,7 +39,10 @@ async def test_if_fires_on_change_bool(hass, calls):
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ true }}"},
"trigger": {
"platform": "template",
"value_template": "{{ states.test.entity.state and true }}",
},
"action": {"service": "test.automation"},
}
},
@ -64,7 +67,10 @@ async def test_if_fires_on_change_str(hass, calls):
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": '{{ "true" }}'},
"trigger": {
"platform": "template",
"value_template": '{{ states.test.entity.state and "true" }}',
},
"action": {"service": "test.automation"},
}
},
@ -82,7 +88,10 @@ async def test_if_fires_on_change_str_crazy(hass, calls):
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": '{{ "TrUE" }}'},
"trigger": {
"platform": "template",
"value_template": '{{ states.test.entity.state and "TrUE" }}',
},
"action": {"service": "test.automation"},
}
},
@ -100,7 +109,10 @@ async def test_if_not_fires_on_change_bool(hass, calls):
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ false }}"},
"trigger": {
"platform": "template",
"value_template": "{{ states.test.entity.state and false }}",
},
"action": {"service": "test.automation"},
}
},
@ -178,7 +190,10 @@ async def test_if_fires_on_two_change(hass, calls):
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "template", "value_template": "{{ true }}"},
"trigger": {
"platform": "template",
"value_template": "{{ states.test.entity.state and true }}",
},
"action": {"service": "test.automation"},
}
},

View File

@ -542,12 +542,6 @@ async def test_track_template_error(hass, caplog):
assert "lunch" not in caplog.text
assert "TemplateAssertionError" not in caplog.text
hass.states.async_set("switch.not_exist", "on")
await hass.async_block_till_done()
assert "lunch" in caplog.text
assert "TemplateAssertionError" in caplog.text
async def test_track_template_result(hass):
"""Test tracking template."""