Refactor template components to extract common routines (#27064)

* Added availability_template to Template Cover platform

* Added availability_template to Template Binary Sensor platform

* Added availability_template to Template Fan platform

* Added availability_template to Template Light platform

* Added availability_template to Template Sensor platform

* Added availability_template to Template Switch platform

* Added availability_template to Template Vacuum platform

* Added availability_template to Template Lock platform

* Added to test for invalid values in availability_template

* Black and Lint fix

* black formatting

* Added to test for invalid values in availability_template

* black

* Added to test for invalid values in availability_template

* Added to test for invalid values in availability_template

* simplified exception handler

* Fixed Entity discovery big and coverage

* Added to test for invalid values in availability_template

* flake8

* fixed component ID in test

* Added to test for invalid values in availability_template

* Added to test for invalid values in availability_template

* Made availability_template redering erorr more concise

* Cleaned template setup

* I'll remember to run black every time one of these days...

* Refactored Template initialisation

* Refactored Template initialisation

* Updated AVAILABILITY_TEMPLATE Rendering error

* Updated AVAILABILITY_TEMPLATE Rendering error

* Updated AVAILABILITY_TEMPLATE Rendering error

* Updated AVAILABILITY_TEMPLATE Rendering error

* Updated AVAILABILITY_TEMPLATE Rendering error

* Updated AVAILABILITY_TEMPLATE Rendering error

* Updated AVAILABILITY_TEMPLATE Rendering error

* Updated AVAILABILITY_TEMPLATE Rendering error

* Moved const to package Const.py

* Moved const to package Const.py

* Moved const to package Const.py

* Moved const to package Const.py

* Moved const to package Const.py

* Moved const to package Const.py

* Moved const to package Const.py

* Moved const to package Const.py

* Fix import order (pylint)

* Fix import order (pylint)

* Fix import order (pylint)

* Fix import order (pylint)

* Fix import order (pylint)

* Fix import order (pylint)

* Fix import order (pylint)

* Fixed linting issues

* Moved availability_template rendering to common loop

* Moved availability_template rendering to common loop

* Moved availability_template rendering to common loop

* Moved availability_template rendering to common loop

* Removed 'Magic' string

* Removed 'Magic' string and removed duplicate code

* Removed 'Magic' string

* Removed 'Magic' string

* Brought contant into line

* Refactored availability_tempalte rendering to common loop

* Removed 'Magic' string

* Cleaned up const and compare lowercase result to 'true'

* Cleaned up const and compare lowercase result to 'true'

* Cleaned up const and compare lowercase result to 'true'

* Cleaned up const and compare lowercase result to 'true'

* Cleaned up const and compare lowercase result to 'true'

* Cleaned up const and compare lowercase result to 'true'

* Cleaned up const and compare lowercase result to 'true'

* reverted _available back to boolean

* reverted _available back to boolean

* reverted _available back to boolean

* reverted _available back to boolean

* reverted _available back to boolean

* reverted _available back to boolean

* reverted _available back to boolean

* Fixed tests (magic values and state checks)

* Fixed tests (magic values and state checks)

* Fixed tests (async, magic values and state checks)

* Fixed tests (async, magic values and state checks)

* Fixed tests (async, magic values and state checks)

* Fixed tests (async, magic values and state checks)

* Fixed tests (async, magic values and state checks)

* Removed duplicate

* Clean up and remove debug

* Reverted Dev Container Change
This commit is contained in:
Gil Peeters 2019-11-26 11:30:49 +11:00 committed by Paulus Schoutsen
parent d5db55354e
commit 0088995b98
12 changed files with 202 additions and 276 deletions

View file

@ -1 +1,60 @@
"""The template component."""
import logging
from itertools import chain
from homeassistant.const import MATCH_ALL
_LOGGER = logging.getLogger(__name__)
def initialise_templates(hass, templates, attribute_templates=None):
"""Initialise templates and attribute templates."""
if attribute_templates is None:
attribute_templates = dict()
for template in chain(templates.values(), attribute_templates.values()):
if template is None:
continue
template.hass = hass
def extract_entities(
device_name, device_type, manual_entity_ids, templates, attribute_templates=None
):
"""Extract entity ids from templates and attribute templates."""
if attribute_templates is None:
attribute_templates = dict()
entity_ids = set()
if manual_entity_ids is None:
invalid_templates = []
for template_name, template in chain(
templates.items(), attribute_templates.items()
):
if template is None:
continue
template_entity_ids = template.extract_entities()
if template_entity_ids != MATCH_ALL:
entity_ids |= set(template_entity_ids)
else:
invalid_templates.append(template_name.replace("_template", ""))
if invalid_templates:
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 "
"template(s). This entity will only be able to be updated "
"manually.",
device_type,
device_name,
", ".join(invalid_templates),
)
else:
entity_ids = list(entity_ids)
else:
entity_ids = manual_entity_ids
return entity_ids

View file

@ -1,6 +1,5 @@
"""Support for exposing a templated binary sensor."""
import logging
from itertools import chain
import voluptuous as vol
@ -26,6 +25,7 @@ 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, async_track_same_state
from . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
_LOGGER = logging.getLogger(__name__)
@ -63,11 +63,12 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
icon_template = device_config.get(CONF_ICON_TEMPLATE)
entity_picture_template = device_config.get(CONF_ENTITY_PICTURE_TEMPLATE)
availability_template = device_config.get(CONF_AVAILABILITY_TEMPLATE)
entity_ids = set()
manual_entity_ids = device_config.get(ATTR_ENTITY_ID)
attribute_templates = device_config.get(CONF_ATTRIBUTE_TEMPLATES, {})
invalid_templates = []
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
device_class = device_config.get(CONF_DEVICE_CLASS)
delay_on = device_config.get(CONF_DELAY_ON)
delay_off = device_config.get(CONF_DELAY_OFF)
templates = {
CONF_VALUE_TEMPLATE: value_template,
@ -76,42 +77,15 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
CONF_AVAILABILITY_TEMPLATE: availability_template,
}
for tpl_name, template in chain(templates.items(), attribute_templates.items()):
if template is None:
continue
template.hass = hass
if manual_entity_ids is not None:
continue
template_entity_ids = template.extract_entities()
if template_entity_ids == MATCH_ALL:
entity_ids = MATCH_ALL
# Cut off _template from name
invalid_templates.append(tpl_name.replace("_template", ""))
elif entity_ids != MATCH_ALL:
entity_ids |= set(template_entity_ids)
if manual_entity_ids is not None:
entity_ids = manual_entity_ids
elif entity_ids != MATCH_ALL:
entity_ids = list(entity_ids)
if invalid_templates:
_LOGGER.warning(
"Template binary sensor %s has no entity ids configured to"
" track nor were we able to extract the entities to track"
" from the %s template(s). This entity will only be able"
" to be updated manually.",
initialise_templates(hass, templates, attribute_templates)
entity_ids = extract_entities(
device,
", ".join(invalid_templates),
"binary sensor",
device_config.get(ATTR_ENTITY_ID),
templates,
attribute_templates,
)
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
device_class = device_config.get(CONF_DEVICE_CLASS)
delay_on = device_config.get(CONF_DELAY_ON)
delay_off = device_config.get(CONF_DELAY_OFF)
sensors.append(
BinarySensorTemplate(
hass,

View file

@ -24,7 +24,6 @@ from homeassistant.const import (
CONF_FRIENDLY_NAME,
CONF_ENTITY_ID,
EVENT_HOMEASSISTANT_START,
MATCH_ALL,
CONF_VALUE_TEMPLATE,
CONF_ICON_TEMPLATE,
CONF_DEVICE_CLASS,
@ -38,6 +37,7 @@ 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.script import Script
from . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
_LOGGER = logging.getLogger(__name__)
@ -100,13 +100,14 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
covers = []
for device, device_config in config[CONF_COVERS].items():
friendly_name = device_config.get(CONF_FRIENDLY_NAME, device)
state_template = device_config.get(CONF_VALUE_TEMPLATE)
position_template = device_config.get(CONF_POSITION_TEMPLATE)
tilt_template = device_config.get(CONF_TILT_TEMPLATE)
icon_template = device_config.get(CONF_ICON_TEMPLATE)
availability_template = device_config.get(CONF_AVAILABILITY_TEMPLATE)
entity_picture_template = device_config.get(CONF_ENTITY_PICTURE_TEMPLATE)
friendly_name = device_config.get(CONF_FRIENDLY_NAME, device)
device_class = device_config.get(CONF_DEVICE_CLASS)
open_action = device_config.get(OPEN_ACTION)
close_action = device_config.get(CLOSE_ACTION)
@ -121,41 +122,18 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
"Must specify at least one of %s" or "%s", OPEN_ACTION, POSITION_ACTION
)
continue
template_entity_ids = set()
if state_template is not None:
temp_ids = state_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if position_template is not None:
temp_ids = position_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
templates = {
CONF_VALUE_TEMPLATE: state_template,
CONF_POSITION_TEMPLATE: position_template,
CONF_TILT_TEMPLATE: tilt_template,
CONF_ICON_TEMPLATE: icon_template,
CONF_AVAILABILITY_TEMPLATE: availability_template,
CONF_ENTITY_PICTURE_TEMPLATE: entity_picture_template,
}
if tilt_template is not None:
temp_ids = tilt_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if icon_template is not None:
temp_ids = icon_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if entity_picture_template is not None:
temp_ids = entity_picture_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if availability_template is not None:
temp_ids = availability_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if not template_entity_ids:
template_entity_ids = MATCH_ALL
entity_ids = device_config.get(CONF_ENTITY_ID, template_entity_ids)
initialise_templates(hass, templates)
entity_ids = extract_entities(device, "cover", None, templates)
covers.append(
CoverTemplate(

View file

@ -25,7 +25,6 @@ from homeassistant.const import (
CONF_ENTITY_ID,
STATE_ON,
STATE_OFF,
MATCH_ALL,
EVENT_HOMEASSISTANT_START,
STATE_UNKNOWN,
)
@ -33,6 +32,7 @@ from homeassistant.core import callback
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.entity import async_generate_entity_id
from homeassistant.helpers.script import Script
from . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
_LOGGER = logging.getLogger(__name__)
@ -98,33 +98,16 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
speed_list = device_config[CONF_SPEED_LIST]
entity_ids = set()
manual_entity_ids = device_config.get(CONF_ENTITY_ID)
templates = {
CONF_VALUE_TEMPLATE: state_template,
CONF_SPEED_TEMPLATE: speed_template,
CONF_OSCILLATING_TEMPLATE: oscillating_template,
CONF_DIRECTION_TEMPLATE: direction_template,
CONF_AVAILABILITY_TEMPLATE: availability_template,
}
for template in (
state_template,
speed_template,
oscillating_template,
direction_template,
availability_template,
):
if template is None:
continue
template.hass = hass
if entity_ids == MATCH_ALL or manual_entity_ids is not None:
continue
template_entity_ids = template.extract_entities()
if template_entity_ids == MATCH_ALL:
entity_ids = MATCH_ALL
else:
entity_ids |= set(template_entity_ids)
if manual_entity_ids is not None:
entity_ids = manual_entity_ids
elif entity_ids != MATCH_ALL:
entity_ids = list(entity_ids)
initialise_templates(hass, templates)
entity_ids = extract_entities(device, "fan", None, templates)
fans.append(
TemplateFan(

View file

@ -19,7 +19,6 @@ from homeassistant.const import (
STATE_ON,
STATE_OFF,
EVENT_HOMEASSISTANT_START,
MATCH_ALL,
CONF_LIGHTS,
)
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
@ -28,6 +27,7 @@ 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.script import Script
from . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
_LOGGER = logging.getLogger(__name__)
@ -64,46 +64,27 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
for device, device_config in config[CONF_LIGHTS].items():
friendly_name = device_config.get(CONF_FRIENDLY_NAME, device)
state_template = device_config.get(CONF_VALUE_TEMPLATE)
icon_template = device_config.get(CONF_ICON_TEMPLATE)
entity_picture_template = device_config.get(CONF_ENTITY_PICTURE_TEMPLATE)
availability_template = device_config.get(CONF_AVAILABILITY_TEMPLATE)
level_template = device_config.get(CONF_LEVEL_TEMPLATE)
on_action = device_config[CONF_ON_ACTION]
off_action = device_config[CONF_OFF_ACTION]
level_action = device_config.get(CONF_LEVEL_ACTION)
level_template = device_config.get(CONF_LEVEL_TEMPLATE)
template_entity_ids = set()
templates = {
CONF_VALUE_TEMPLATE: state_template,
CONF_ICON_TEMPLATE: icon_template,
CONF_ENTITY_PICTURE_TEMPLATE: entity_picture_template,
CONF_AVAILABILITY_TEMPLATE: availability_template,
CONF_LEVEL_TEMPLATE: level_template,
}
if state_template is not None:
temp_ids = state_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if level_template is not None:
temp_ids = level_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if icon_template is not None:
temp_ids = icon_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if entity_picture_template is not None:
temp_ids = entity_picture_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if availability_template is not None:
temp_ids = availability_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
if not template_entity_ids:
template_entity_ids = MATCH_ALL
entity_ids = device_config.get(CONF_ENTITY_ID, template_entity_ids)
initialise_templates(hass, templates)
entity_ids = extract_entities(device, "light", None, templates)
lights.append(
LightTemplate(

View file

@ -19,6 +19,7 @@ from homeassistant.const import (
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.event import async_track_state_change
from homeassistant.helpers.script import Script
from . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
_LOGGER = logging.getLogger(__name__)
@ -43,39 +44,26 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
async def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Template lock."""
name = config.get(CONF_NAME)
device = config.get(CONF_NAME)
value_template = config.get(CONF_VALUE_TEMPLATE)
value_template.hass = hass
value_template_entity_ids = value_template.extract_entities()
if value_template_entity_ids == MATCH_ALL:
_LOGGER.warning(
"Template lock '%s' has no entity ids configured to track nor "
"were we able to extract the entities to track from the '%s' "
"template. This entity will only be able to be updated "
"manually.",
name,
CONF_VALUE_TEMPLATE,
)
template_entity_ids = set()
template_entity_ids |= set(value_template_entity_ids)
availability_template = config.get(CONF_AVAILABILITY_TEMPLATE)
if availability_template is not None:
availability_template.hass = hass
temp_ids = availability_template.extract_entities()
if str(temp_ids) != MATCH_ALL:
template_entity_ids |= set(temp_ids)
templates = {
CONF_VALUE_TEMPLATE: value_template,
CONF_AVAILABILITY_TEMPLATE: availability_template,
}
initialise_templates(hass, templates)
entity_ids = extract_entities(device, "lock", None, templates)
async_add_devices(
[
TemplateLock(
hass,
name,
device,
value_template,
availability_template,
template_entity_ids,
entity_ids,
config.get(CONF_LOCK),
config.get(CONF_UNLOCK),
config.get(CONF_OPTIMISTIC),

View file

@ -1,7 +1,6 @@
"""Allows the creation of a sensor that breaks out state_attributes."""
import logging
from typing import Optional
from itertools import chain
import voluptuous as vol
@ -29,6 +28,7 @@ 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 . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
CONF_ATTRIBUTE_TEMPLATES = "attribute_templates"
@ -72,10 +72,6 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
device_class = device_config.get(CONF_DEVICE_CLASS)
attribute_templates = device_config[CONF_ATTRIBUTE_TEMPLATES]
entity_ids = set()
manual_entity_ids = device_config.get(ATTR_ENTITY_ID)
invalid_templates = []
templates = {
CONF_VALUE_TEMPLATE: state_template,
CONF_ICON_TEMPLATE: icon_template,
@ -84,37 +80,15 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
CONF_AVAILABILITY_TEMPLATE: availability_template,
}
for tpl_name, template in chain(templates.items(), attribute_templates.items()):
if template is None:
continue
template.hass = hass
if manual_entity_ids is not None:
continue
template_entity_ids = template.extract_entities()
if template_entity_ids == MATCH_ALL:
entity_ids = MATCH_ALL
# Cut off _template from name
invalid_templates.append(tpl_name.replace("_template", ""))
elif entity_ids != MATCH_ALL:
entity_ids |= set(template_entity_ids)
if invalid_templates:
_LOGGER.warning(
"Template sensor %s has no entity ids configured to track nor"
" were we able to extract the entities to track from the %s "
"template(s). This entity will only be able to be updated "
"manually.",
initialise_templates(hass, templates, attribute_templates)
entity_ids = extract_entities(
device,
", ".join(invalid_templates),
"sensor",
device_config.get(ATTR_ENTITY_ID),
templates,
attribute_templates,
)
if manual_entity_ids is not None:
entity_ids = manual_entity_ids
elif entity_ids != MATCH_ALL:
entity_ids = list(entity_ids)
sensors.append(
SensorTemplate(
hass,
@ -131,7 +105,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
attribute_templates,
)
)
async_add_entities(sensors)
return True

View file

@ -19,13 +19,13 @@ from homeassistant.const import (
ATTR_ENTITY_ID,
CONF_SWITCHES,
EVENT_HOMEASSISTANT_START,
MATCH_ALL,
)
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.script import Script
from . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
_LOGGER = logging.getLogger(__name__)
@ -64,8 +64,6 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
availability_template = device_config.get(CONF_AVAILABILITY_TEMPLATE)
on_action = device_config[ON_ACTION]
off_action = device_config[OFF_ACTION]
manual_entity_ids = device_config.get(ATTR_ENTITY_ID)
entity_ids = set()
templates = {
CONF_VALUE_TEMPLATE: state_template,
@ -73,35 +71,11 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
CONF_ENTITY_PICTURE_TEMPLATE: entity_picture_template,
CONF_AVAILABILITY_TEMPLATE: availability_template,
}
invalid_templates = []
for template_name, template in templates.items():
if template is not None:
template.hass = hass
if manual_entity_ids is not None:
continue
template_entity_ids = template.extract_entities()
if template_entity_ids == MATCH_ALL:
invalid_templates.append(template_name.replace("_template", ""))
entity_ids = MATCH_ALL
elif entity_ids != MATCH_ALL:
entity_ids |= set(template_entity_ids)
if invalid_templates:
_LOGGER.warning(
"Template sensor %s has no entity ids configured to track nor"
" were we able to extract the entities to track from the %s "
"template(s). This entity will only be able to be updated "
"manually.",
device,
", ".join(invalid_templates),
initialise_templates(hass, templates)
entity_ids = extract_entities(
device, "switch", device_config.get(ATTR_ENTITY_ID), templates
)
else:
if manual_entity_ids is None:
entity_ids = list(entity_ids)
else:
entity_ids = manual_entity_ids
switches.append(
SwitchTemplate(
@ -117,6 +91,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
entity_ids,
)
)
if not switches:
_LOGGER.error("No switches added")
return False

View file

@ -43,7 +43,7 @@ from homeassistant.core import callback
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.entity import async_generate_entity_id
from homeassistant.helpers.script import Script
from . import extract_entities, initialise_templates
from .const import CONF_AVAILABILITY_TEMPLATE
_LOGGER = logging.getLogger(__name__)
@ -109,45 +109,15 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
fan_speed_list = device_config[CONF_FAN_SPEED_LIST]
entity_ids = set()
manual_entity_ids = device_config.get(CONF_ENTITY_ID)
invalid_templates = []
templates = {
CONF_VALUE_TEMPLATE: state_template,
CONF_BATTERY_LEVEL_TEMPLATE: battery_level_template,
CONF_FAN_SPEED_TEMPLATE: fan_speed_template,
CONF_AVAILABILITY_TEMPLATE: availability_template,
}
for tpl_name, template in (
(CONF_VALUE_TEMPLATE, state_template),
(CONF_BATTERY_LEVEL_TEMPLATE, battery_level_template),
(CONF_FAN_SPEED_TEMPLATE, fan_speed_template),
(CONF_AVAILABILITY_TEMPLATE, availability_template),
):
if template is None:
continue
template.hass = hass
if manual_entity_ids is not None:
continue
template_entity_ids = template.extract_entities()
if template_entity_ids == MATCH_ALL:
entity_ids = MATCH_ALL
# Cut off _template from name
invalid_templates.append(tpl_name[:-9])
elif entity_ids != MATCH_ALL:
entity_ids |= set(template_entity_ids)
if invalid_templates:
_LOGGER.warning(
"Template vacuum %s has no entity ids configured to track nor"
" were we able to extract the entities to track from the %s "
"template(s). This entity will only be able to be updated "
"manually.",
device,
", ".join(invalid_templates),
)
if manual_entity_ids is not None:
entity_ids = manual_entity_ids
elif entity_ids != MATCH_ALL:
entity_ids = list(entity_ids)
initialise_templates(hass, templates)
entity_ids = extract_entities(device, "vacuum", None, templates)
vacuums.append(
TemplateVacuum(

View file

@ -576,22 +576,22 @@ async def test_no_update_template_match_all(hass, caplog):
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 5
assert (
"Template binary sensor all_state has no entity ids "
"Template binary sensor 'all_state' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the value template"
) in caplog.text
assert (
"Template binary sensor all_icon has no entity ids "
"Template binary sensor 'all_icon' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the icon template"
) in caplog.text
assert (
"Template binary sensor all_entity_picture has no entity ids "
"Template binary sensor 'all_entity_picture' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the entity_picture template"
) in caplog.text
assert (
"Template binary sensor all_attribute has no entity ids "
"Template binary sensor 'all_attribute' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the test_attribute template"
) in caplog.text

View file

@ -254,10 +254,9 @@ class TestTemplateLock:
assert state.state == lock.STATE_UNLOCKED
assert (
"Template lock 'Template Lock' has no entity ids configured "
"to track nor were we able to extract the entities to track "
"from the 'value_template' template. This entity will only "
"be able to be updated manually."
"Template lock 'Template Lock' has no entity ids configured to track "
"nor were we able to extract the entities to track from the value "
"template(s). This entity will only be able to be updated manually"
) in caplog.text
self.hass.states.set("lock.template_lock", lock.STATE_LOCKED)
@ -343,7 +342,7 @@ async def test_available_template_with_entities(hass):
{
"lock": {
"platform": "template",
"value_template": "{{ 'on' }}",
"value_template": "{{ states('switch.test_state') }}",
"lock": {"service": "switch.turn_on", "entity_id": "switch.test_state"},
"unlock": {
"service": "switch.turn_off",

View file

@ -377,6 +377,49 @@ class TestTemplateSensor:
state = self.hass.states.get("sensor.test2")
assert "device_class" not in state.attributes
def test_available_template_with_entities(self):
"""Test availability tempalates with values from other entities."""
with assert_setup_component(1):
assert setup_component(
self.hass,
"sensor",
{
"sensor": {
"platform": "template",
"sensors": {
"test_template_sensor": {
"value_template": "{{ states.sensor.test_state.state }}",
"availability_template": "{{ is_state('availability_boolean.state', 'on') }}",
}
},
}
},
)
self.hass.start()
self.hass.block_till_done()
# When template returns true..
self.hass.states.set("availability_boolean.state", STATE_ON)
self.hass.block_till_done()
# Device State should not be unavailable
assert (
self.hass.states.get("sensor.test_template_sensor").state
!= STATE_UNAVAILABLE
)
# When Availability template returns false
self.hass.states.set("availability_boolean.state", STATE_OFF)
self.hass.block_till_done()
# device state should be unavailable
assert (
self.hass.states.get("sensor.test_template_sensor").state
== STATE_UNAVAILABLE
)
async def test_available_template_with_entities(hass):
"""Test availability tempalates with values from other entities."""
@ -511,27 +554,27 @@ async def test_no_template_match_all(hass, caplog):
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 6
assert (
"Template sensor invalid_state has no entity ids "
"Template sensor 'invalid_state' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the value template"
) in caplog.text
assert (
"Template sensor invalid_icon has no entity ids "
"Template sensor 'invalid_icon' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the icon template"
) in caplog.text
assert (
"Template sensor invalid_entity_picture has no entity ids "
"Template sensor 'invalid_entity_picture' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the entity_picture template"
) in caplog.text
assert (
"Template sensor invalid_friendly_name has no entity ids "
"Template sensor 'invalid_friendly_name' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the friendly_name template"
) in caplog.text
assert (
"Template sensor invalid_attribute has no entity ids "
"Template sensor 'invalid_attribute' has no entity ids "
"configured to track nor were we able to extract the entities to "
"track from the test_attribute template"
) in caplog.text