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:
parent
d5db55354e
commit
0088995b98
12 changed files with 202 additions and 276 deletions
|
@ -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
|
||||
|
|
|
@ -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,41 +77,14 @@ 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.",
|
||||
device,
|
||||
", ".join(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)
|
||||
initialise_templates(hass, templates, attribute_templates)
|
||||
entity_ids = extract_entities(
|
||||
device,
|
||||
"binary sensor",
|
||||
device_config.get(ATTR_ENTITY_ID),
|
||||
templates,
|
||||
attribute_templates,
|
||||
)
|
||||
|
||||
sensors.append(
|
||||
BinarySensorTemplate(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,36 +80,14 @@ 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.",
|
||||
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, attribute_templates)
|
||||
entity_ids = extract_entities(
|
||||
device,
|
||||
"sensor",
|
||||
device_config.get(ATTR_ENTITY_ID),
|
||||
templates,
|
||||
attribute_templates,
|
||||
)
|
||||
|
||||
sensors.append(
|
||||
SensorTemplate(
|
||||
|
@ -131,7 +105,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||
attribute_templates,
|
||||
)
|
||||
)
|
||||
|
||||
async_add_entities(sensors)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
else:
|
||||
if manual_entity_ids is None:
|
||||
entity_ids = list(entity_ids)
|
||||
else:
|
||||
entity_ids = manual_entity_ids
|
||||
initialise_templates(hass, templates)
|
||||
entity_ids = extract_entities(
|
||||
device, "switch", device_config.get(ATTR_ENTITY_ID), templates
|
||||
)
|
||||
|
||||
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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue