Enable template icons for template numbers (#56154)

This commit is contained in:
Jeff Irion 2021-10-01 09:35:44 -07:00 committed by GitHub
parent cc97502a0c
commit 15a8f6741b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 142 additions and 11 deletions

View File

@ -18,7 +18,13 @@ from homeassistant.components.number.const import (
DOMAIN as NUMBER_DOMAIN, DOMAIN as NUMBER_DOMAIN,
) )
from homeassistant.components.template import TriggerUpdateCoordinator from homeassistant.components.template import TriggerUpdateCoordinator
from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_STATE, CONF_UNIQUE_ID from homeassistant.const import (
CONF_ICON,
CONF_NAME,
CONF_OPTIMISTIC,
CONF_STATE,
CONF_UNIQUE_ID,
)
from homeassistant.core import Config, HomeAssistant from homeassistant.core import Config, HomeAssistant
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -47,6 +53,7 @@ NUMBER_SCHEMA = vol.Schema(
vol.Optional(CONF_AVAILABILITY): cv.template, vol.Optional(CONF_AVAILABILITY): cv.template,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean, vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_UNIQUE_ID): cv.string, vol.Optional(CONF_UNIQUE_ID): cv.string,
vol.Optional(CONF_ICON): cv.template,
} }
) )
@ -72,6 +79,7 @@ async def _async_create_entities(
definition[ATTR_MAX], definition[ATTR_MAX],
definition[CONF_OPTIMISTIC], definition[CONF_OPTIMISTIC],
unique_id, unique_id,
definition.get(CONF_ICON),
) )
) )
return entities return entities
@ -119,9 +127,12 @@ class TemplateNumber(TemplateEntity, NumberEntity):
maximum_template: Template | None, maximum_template: Template | None,
optimistic: bool, optimistic: bool,
unique_id: str | None, unique_id: str | None,
icon_template: Template | None,
) -> None: ) -> None:
"""Initialize the number.""" """Initialize the number."""
super().__init__(availability_template=availability_template) super().__init__(
availability_template=availability_template, icon_template=icon_template
)
self._attr_name = DEFAULT_NAME self._attr_name = DEFAULT_NAME
self._name_template = name_template self._name_template = name_template
name_template.hass = hass name_template.hass = hass

View File

@ -15,7 +15,7 @@ from homeassistant.components.number.const import (
DOMAIN as NUMBER_DOMAIN, DOMAIN as NUMBER_DOMAIN,
SERVICE_SET_VALUE as NUMBER_SERVICE_SET_VALUE, SERVICE_SET_VALUE as NUMBER_SERVICE_SET_VALUE,
) )
from homeassistant.const import CONF_ENTITY_ID, STATE_UNKNOWN from homeassistant.const import ATTR_ICON, CONF_ENTITY_ID, STATE_UNKNOWN
from homeassistant.core import Context from homeassistant.core import Context
from homeassistant.helpers.entity_registry import async_get from homeassistant.helpers.entity_registry import async_get
@ -35,6 +35,17 @@ _MAXIMUM_INPUT_NUMBER = "input_number.maximum"
# Represent for number's step # Represent for number's step
_STEP_INPUT_NUMBER = "input_number.step" _STEP_INPUT_NUMBER = "input_number.step"
# Config for `_VALUE_INPUT_NUMBER`
_VALUE_INPUT_NUMBER_CONFIG = {
"value": {
"min": 0.0,
"max": 100.0,
"name": "Value",
"step": 1.0,
"mode": "slider",
}
}
@pytest.fixture @pytest.fixture
def calls(hass): def calls(hass):
@ -128,20 +139,14 @@ async def test_all_optional_config(hass, calls):
async def test_templates_with_entities(hass, calls): async def test_templates_with_entities(hass, calls):
"""Test tempalates with values from other entities.""" """Test templates with values from other entities."""
with assert_setup_component(4, "input_number"): with assert_setup_component(4, "input_number"):
assert await setup.async_setup_component( assert await setup.async_setup_component(
hass, hass,
"input_number", "input_number",
{ {
"input_number": { "input_number": {
"value": { **_VALUE_INPUT_NUMBER_CONFIG,
"min": 0.0,
"max": 100.0,
"name": "Value",
"step": 1.0,
"mode": "slider",
},
"step": { "step": {
"min": 0.0, "min": 0.0,
"max": 100.0, "max": 100.0,
@ -334,3 +339,118 @@ def _verify(
assert attributes.get(ATTR_STEP) == float(expected_step) assert attributes.get(ATTR_STEP) == float(expected_step)
assert attributes.get(ATTR_MAX) == float(expected_maximum) assert attributes.get(ATTR_MAX) == float(expected_maximum)
assert attributes.get(ATTR_MIN) == float(expected_minimum) assert attributes.get(ATTR_MIN) == float(expected_minimum)
async def test_icon_template(hass):
"""Test template numbers with icon templates."""
with assert_setup_component(1, "input_number"):
assert await setup.async_setup_component(
hass,
"input_number",
{"input_number": _VALUE_INPUT_NUMBER_CONFIG},
)
with assert_setup_component(1, "template"):
assert await setup.async_setup_component(
hass,
"template",
{
"template": {
"unique_id": "b",
"number": {
"state": f"{{{{ states('{_VALUE_INPUT_NUMBER}') }}}}",
"step": 1,
"min": 0,
"max": 100,
"set_value": {
"service": "input_number.set_value",
"data_template": {
"entity_id": _VALUE_INPUT_NUMBER,
"value": "{{ value }}",
},
},
"icon": "{% if ((states.input_number.value.state or 0) | int) > 50 %}mdi:greater{% else %}mdi:less{% endif %}",
},
}
},
)
hass.states.async_set(_VALUE_INPUT_NUMBER, 49)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
state = hass.states.get(_TEST_NUMBER)
assert float(state.state) == 49
assert state.attributes[ATTR_ICON] == "mdi:less"
await hass.services.async_call(
INPUT_NUMBER_DOMAIN,
INPUT_NUMBER_SERVICE_SET_VALUE,
{CONF_ENTITY_ID: _VALUE_INPUT_NUMBER, INPUT_NUMBER_ATTR_VALUE: 51},
blocking=True,
)
await hass.async_block_till_done()
state = hass.states.get(_TEST_NUMBER)
assert float(state.state) == 51
assert state.attributes[ATTR_ICON] == "mdi:greater"
async def test_icon_template_with_trigger(hass):
"""Test template numbers with icon templates."""
with assert_setup_component(1, "input_number"):
assert await setup.async_setup_component(
hass,
"input_number",
{"input_number": _VALUE_INPUT_NUMBER_CONFIG},
)
with assert_setup_component(1, "template"):
assert await setup.async_setup_component(
hass,
"template",
{
"template": {
"trigger": {"platform": "state", "entity_id": _VALUE_INPUT_NUMBER},
"unique_id": "b",
"number": {
"state": "{{ trigger.to_state.state }}",
"step": 1,
"min": 0,
"max": 100,
"set_value": {
"service": "input_number.set_value",
"data_template": {
"entity_id": _VALUE_INPUT_NUMBER,
"value": "{{ value }}",
},
},
"icon": "{% if ((trigger.to_state.state or 0) | int) > 50 %}mdi:greater{% else %}mdi:less{% endif %}",
},
}
},
)
hass.states.async_set(_VALUE_INPUT_NUMBER, 49)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
state = hass.states.get(_TEST_NUMBER)
assert float(state.state) == 49
assert state.attributes[ATTR_ICON] == "mdi:less"
await hass.services.async_call(
INPUT_NUMBER_DOMAIN,
INPUT_NUMBER_SERVICE_SET_VALUE,
{CONF_ENTITY_ID: _VALUE_INPUT_NUMBER, INPUT_NUMBER_ATTR_VALUE: 51},
blocking=True,
)
await hass.async_block_till_done()
state = hass.states.get(_TEST_NUMBER)
assert float(state.state) == 51
assert state.attributes[ATTR_ICON] == "mdi:greater"