diff --git a/homeassistant/components/template/__init__.py b/homeassistant/components/template/__init__.py index 04808970af2..de9d60feceb 100644 --- a/homeassistant/components/template/__init__.py +++ b/homeassistant/components/template/__init__.py @@ -40,8 +40,11 @@ def extract_entities( else: invalid_templates.append(template_name.replace("_template", "")) + entity_ids = list(entity_ids) + if invalid_templates: - entity_ids = MATCH_ALL + if not entity_ids: + entity_ids = MATCH_ALL _LOGGER.warning( "Template %s '%s' has no entity ids configured to track nor" " were we able to extract the entities to track from the %s " @@ -51,8 +54,6 @@ def extract_entities( device_name, ", ".join(invalid_templates), ) - else: - entity_ids = list(entity_ids) else: entity_ids = manual_entity_ids diff --git a/homeassistant/components/template/alarm_control_panel.py b/homeassistant/components/template/alarm_control_panel.py index 3d6ac1dbe0e..b7ad219eff7 100644 --- a/homeassistant/components/template/alarm_control_panel.py +++ b/homeassistant/components/template/alarm_control_panel.py @@ -32,7 +32,7 @@ from homeassistant.core import callback from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import async_generate_entity_id -from homeassistant.helpers.event import async_track_state_change +from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.script import Script _LOGGER = logging.getLogger(__name__) @@ -204,15 +204,16 @@ class AlarmControlPanelTemplate(AlarmControlPanelEntity): """Register callbacks.""" @callback - def template_alarm_state_listener(entity, old_state, new_state): + def template_alarm_state_listener(event): """Handle target device state changes.""" self.async_schedule_update_ha_state(True) @callback def template_alarm_control_panel_startup(event): """Update template on startup.""" - if self._template is not None: - async_track_state_change( + if self._template is not None and self._entities != MATCH_ALL: + # Track state change only for valid templates + async_track_state_change_event( self.hass, self._entities, template_alarm_state_listener ) diff --git a/homeassistant/components/template/binary_sensor.py b/homeassistant/components/template/binary_sensor.py index 91ffba6dd25..101651fabd5 100644 --- a/homeassistant/components/template/binary_sensor.py +++ b/homeassistant/components/template/binary_sensor.py @@ -24,7 +24,10 @@ from homeassistant.core import callback from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import async_generate_entity_id -from homeassistant.helpers.event import async_track_same_state, async_track_state_change +from homeassistant.helpers.event import ( + async_track_same_state, + async_track_state_change_event, +) from . import extract_entities, initialise_templates from .const import CONF_AVAILABILITY_TEMPLATE @@ -148,7 +151,7 @@ class BinarySensorTemplate(BinarySensorEntity): """Register callbacks.""" @callback - def template_bsensor_state_listener(entity, old_state, new_state): + def template_bsensor_state_listener(event): """Handle the target device state changes.""" self.async_check_state() @@ -157,7 +160,7 @@ class BinarySensorTemplate(BinarySensorEntity): """Update template on startup.""" if self._entities != MATCH_ALL: # Track state change only for valid templates - async_track_state_change( + async_track_state_change_event( self.hass, self._entities, template_bsensor_state_listener ) diff --git a/homeassistant/components/template/cover.py b/homeassistant/components/template/cover.py index 16140de67d8..e2f67acf2bd 100644 --- a/homeassistant/components/template/cover.py +++ b/homeassistant/components/template/cover.py @@ -28,6 +28,7 @@ from homeassistant.const import ( CONF_OPTIMISTIC, CONF_VALUE_TEMPLATE, EVENT_HOMEASSISTANT_START, + MATCH_ALL, STATE_CLOSED, STATE_OPEN, ) @@ -35,7 +36,7 @@ from homeassistant.core import callback from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import async_generate_entity_id -from homeassistant.helpers.event import async_track_state_change +from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.script import Script from . import extract_entities, initialise_templates @@ -226,16 +227,18 @@ class CoverTemplate(CoverEntity): """Register callbacks.""" @callback - def template_cover_state_listener(entity, old_state, new_state): + def template_cover_state_listener(event): """Handle target device state changes.""" self.async_schedule_update_ha_state(True) @callback def template_cover_startup(event): """Update template on startup.""" - async_track_state_change( - self.hass, self._entities, template_cover_state_listener - ) + if self._entities != MATCH_ALL: + # Track state change only for valid templates + async_track_state_change_event( + self.hass, self._entities, template_cover_state_listener + ) self.async_schedule_update_ha_state(True) diff --git a/homeassistant/components/template/fan.py b/homeassistant/components/template/fan.py index ecdb4ec7eec..037cc6c40e1 100644 --- a/homeassistant/components/template/fan.py +++ b/homeassistant/components/template/fan.py @@ -23,6 +23,7 @@ from homeassistant.const import ( CONF_FRIENDLY_NAME, CONF_VALUE_TEMPLATE, EVENT_HOMEASSISTANT_START, + MATCH_ALL, STATE_OFF, STATE_ON, STATE_UNKNOWN, @@ -313,16 +314,18 @@ class TemplateFan(FanEntity): """Register callbacks.""" @callback - def template_fan_state_listener(entity, old_state, new_state): + def template_fan_state_listener(event): """Handle target device state changes.""" self.async_schedule_update_ha_state(True) @callback def template_fan_startup(event): """Update template on startup.""" - self.hass.helpers.event.async_track_state_change( - self._entities, template_fan_state_listener - ) + if self._entities != MATCH_ALL: + # Track state change only for valid templates + self.hass.helpers.event.async_track_state_change_event( + self._entities, template_fan_state_listener + ) self.async_schedule_update_ha_state(True) diff --git a/homeassistant/components/template/light.py b/homeassistant/components/template/light.py index d96c6f62dce..6832ca04017 100644 --- a/homeassistant/components/template/light.py +++ b/homeassistant/components/template/light.py @@ -23,6 +23,7 @@ from homeassistant.const import ( CONF_LIGHTS, CONF_VALUE_TEMPLATE, EVENT_HOMEASSISTANT_START, + MATCH_ALL, STATE_OFF, STATE_ON, ) @@ -31,7 +32,7 @@ from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv from homeassistant.helpers.config_validation import PLATFORM_SCHEMA from homeassistant.helpers.entity import async_generate_entity_id -from homeassistant.helpers.event import async_track_state_change +from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.script import Script from . import extract_entities, initialise_templates @@ -277,7 +278,7 @@ class LightTemplate(LightEntity): """Register callbacks.""" @callback - def template_light_state_listener(entity, old_state, new_state): + def template_light_state_listener(event): """Handle target device state changes.""" self.async_schedule_update_ha_state(True) @@ -292,9 +293,11 @@ class LightTemplate(LightEntity): or self._white_value_template is not None or self._availability_template is not None ): - async_track_state_change( - self.hass, self._entities, template_light_state_listener - ) + if self._entities != MATCH_ALL: + # Track state change only for valid templates + async_track_state_change_event( + self.hass, self._entities, template_light_state_listener + ) self.async_schedule_update_ha_state(True) diff --git a/homeassistant/components/template/lock.py b/homeassistant/components/template/lock.py index 7a50e34f8cb..0d8cdd7d290 100644 --- a/homeassistant/components/template/lock.py +++ b/homeassistant/components/template/lock.py @@ -16,7 +16,7 @@ from homeassistant.const import ( from homeassistant.core import callback from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.event import async_track_state_change +from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.script import Script from . import extract_entities, initialise_templates @@ -102,7 +102,7 @@ class TemplateLock(LockEntity): """Register callbacks.""" @callback - def template_lock_state_listener(entity, old_state, new_state): + def template_lock_state_listener(event): """Handle target device state changes.""" self.async_schedule_update_ha_state(True) @@ -111,7 +111,7 @@ class TemplateLock(LockEntity): """Update template on startup.""" if self._state_entities != MATCH_ALL: # Track state change only for valid templates - async_track_state_change( + async_track_state_change_event( self._hass, self._state_entities, template_lock_state_listener ) self.async_schedule_update_ha_state(True) diff --git a/homeassistant/components/template/sensor.py b/homeassistant/components/template/sensor.py index 44f83699097..d4977d626ca 100644 --- a/homeassistant/components/template/sensor.py +++ b/homeassistant/components/template/sensor.py @@ -26,7 +26,7 @@ from homeassistant.core import callback from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity, async_generate_entity_id -from homeassistant.helpers.event import async_track_state_change +from homeassistant.helpers.event import async_track_state_change_event from . import extract_entities, initialise_templates from .const import CONF_AVAILABILITY_TEMPLATE @@ -154,7 +154,7 @@ class SensorTemplate(Entity): """Register callbacks.""" @callback - def template_sensor_state_listener(entity, old_state, new_state): + def template_sensor_state_listener(event): """Handle device state changes.""" self.async_schedule_update_ha_state(True) @@ -163,7 +163,7 @@ class SensorTemplate(Entity): """Update template on startup.""" if self._entities != MATCH_ALL: # Track state change only for valid templates - async_track_state_change( + async_track_state_change_event( self.hass, self._entities, template_sensor_state_listener ) diff --git a/homeassistant/components/template/switch.py b/homeassistant/components/template/switch.py index abc9a432529..124d12d194f 100644 --- a/homeassistant/components/template/switch.py +++ b/homeassistant/components/template/switch.py @@ -16,6 +16,7 @@ from homeassistant.const import ( CONF_SWITCHES, CONF_VALUE_TEMPLATE, EVENT_HOMEASSISTANT_START, + MATCH_ALL, STATE_OFF, STATE_ON, ) @@ -23,7 +24,7 @@ from homeassistant.core import callback from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import async_generate_entity_id -from homeassistant.helpers.event import async_track_state_change +from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.script import Script @@ -147,16 +148,18 @@ class SwitchTemplate(SwitchEntity, RestoreEntity): # set up event listening @callback - def template_switch_state_listener(entity, old_state, new_state): + def template_switch_state_listener(event): """Handle target device state changes.""" self.async_schedule_update_ha_state(True) @callback def template_switch_startup(event): """Update template on startup.""" - async_track_state_change( - self.hass, self._entities, template_switch_state_listener - ) + if self._entities != MATCH_ALL: + # Track state change only for valid templates + async_track_state_change_event( + self.hass, self._entities, template_switch_state_listener + ) self.async_schedule_update_ha_state(True) diff --git a/homeassistant/components/template/vacuum.py b/homeassistant/components/template/vacuum.py index 040b4324b05..1209e617a7e 100644 --- a/homeassistant/components/template/vacuum.py +++ b/homeassistant/components/template/vacuum.py @@ -341,7 +341,7 @@ class TemplateVacuum(StateVacuumEntity): """Register callbacks.""" @callback - def template_vacuum_state_listener(entity, old_state, new_state): + def template_vacuum_state_listener(event): """Handle target device state changes.""" self.async_schedule_update_ha_state(True) @@ -350,7 +350,7 @@ class TemplateVacuum(StateVacuumEntity): """Update template on startup.""" if self._entities != MATCH_ALL: # Track state changes only for valid templates - self.hass.helpers.event.async_track_state_change( + self.hass.helpers.event.async_track_state_change_event( self._entities, template_vacuum_state_listener ) diff --git a/tests/components/template/test_binary_sensor.py b/tests/components/template/test_binary_sensor.py index 698d1c2ca80..482a72082cd 100644 --- a/tests/components/template/test_binary_sensor.py +++ b/tests/components/template/test_binary_sensor.py @@ -622,9 +622,10 @@ async def test_no_update_template_match_all(hass, caplog): await hass.async_block_till_done() assert hass.states.get("binary_sensor.all_state").state == "on" - assert hass.states.get("binary_sensor.all_icon").state == "on" - assert hass.states.get("binary_sensor.all_entity_picture").state == "on" - assert hass.states.get("binary_sensor.all_attribute").state == "on" + # Will now process because we have one valid template + assert hass.states.get("binary_sensor.all_icon").state == "off" + assert hass.states.get("binary_sensor.all_entity_picture").state == "off" + assert hass.states.get("binary_sensor.all_attribute").state == "off" await hass.helpers.entity_component.async_update_entity("binary_sensor.all_state") await hass.helpers.entity_component.async_update_entity("binary_sensor.all_icon") diff --git a/tests/components/template/test_sensor.py b/tests/components/template/test_sensor.py index 0fbce50f2a3..d61b1be4a7f 100644 --- a/tests/components/template/test_sensor.py +++ b/tests/components/template/test_sensor.py @@ -618,10 +618,11 @@ async def test_no_template_match_all(hass, caplog): await hass.async_block_till_done() assert hass.states.get("sensor.invalid_state").state == "2" - assert hass.states.get("sensor.invalid_icon").state == "startup" - assert hass.states.get("sensor.invalid_entity_picture").state == "startup" - assert hass.states.get("sensor.invalid_friendly_name").state == "startup" - assert hass.states.get("sensor.invalid_attribute").state == "startup" + # Will now process because we have at least one valid template + assert hass.states.get("sensor.invalid_icon").state == "hello" + assert hass.states.get("sensor.invalid_entity_picture").state == "hello" + assert hass.states.get("sensor.invalid_friendly_name").state == "hello" + assert hass.states.get("sensor.invalid_attribute").state == "hello" await hass.helpers.entity_component.async_update_entity("sensor.invalid_state") await hass.helpers.entity_component.async_update_entity("sensor.invalid_icon")