Add unit_of_measurement to template numbers (#122862)

This commit is contained in:
chammp 2024-09-11 08:47:17 +02:00 committed by GitHub
parent 8e0b2b752c
commit 56dfb2c734
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 43 additions and 11 deletions

View File

@ -116,6 +116,11 @@ def generate_schema(domain: str, flow_type: str) -> vol.Schema:
vol.Required(CONF_STEP, default=DEFAULT_STEP): selector.NumberSelector(
selector.NumberSelectorConfig(mode=selector.NumberSelectorMode.BOX),
),
vol.Optional(CONF_UNIT_OF_MEASUREMENT): selector.TextSelector(
selector.TextSelectorConfig(
type=selector.TextSelectorType.TEXT, multiline=False
)
),
vol.Optional(CONF_SET_VALUE): selector.ActionSelector(),
}

View File

@ -22,6 +22,7 @@ from homeassistant.const import (
CONF_OPTIMISTIC,
CONF_STATE,
CONF_UNIQUE_ID,
CONF_UNIT_OF_MEASUREMENT,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, selector
@ -55,6 +56,7 @@ NUMBER_SCHEMA = (
vol.Required(CONF_STEP): cv.template,
vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): cv.template,
vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): cv.template,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_UNIQUE_ID): cv.string,
}
@ -70,6 +72,7 @@ NUMBER_CONFIG_SCHEMA = vol.Schema(
vol.Required(CONF_SET_VALUE): cv.SCRIPT_SCHEMA,
vol.Optional(CONF_MIN): cv.template,
vol.Optional(CONF_MAX): cv.template,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_DEVICE_ID): selector.DeviceSelector(),
}
)
@ -159,6 +162,7 @@ class TemplateNumber(TemplateEntity, NumberEntity):
self._min_value_template = config[CONF_MIN]
self._max_value_template = config[CONF_MAX]
self._attr_assumed_state = self._optimistic = config.get(CONF_OPTIMISTIC)
self._attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
self._attr_native_step = DEFAULT_STEP
self._attr_native_min_value = DEFAULT_MIN_VALUE
self._attr_native_max_value = DEFAULT_MAX_VALUE
@ -230,6 +234,7 @@ class TriggerNumberEntity(TriggerEntity, NumberEntity):
) -> None:
"""Initialize the entity."""
super().__init__(hass, coordinator, config)
self._command_set_value = Script(
hass,
config[CONF_SET_VALUE],
@ -237,6 +242,8 @@ class TriggerNumberEntity(TriggerEntity, NumberEntity):
DOMAIN,
)
self._attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
@property
def native_value(self) -> float | None:
"""Return the currently selected option."""

View File

@ -45,7 +45,8 @@
"step": "Step value",
"set_value": "Actions on set value",
"max": "Maximum value",
"min": "Minimum value"
"min": "Minimum value",
"unit_of_measurement": "[%key:component::template::config::step::sensor::data::unit_of_measurement%]"
},
"data_description": {
"device_id": "[%key:component::template::config::step::sensor::data_description::device_id%]"

View File

@ -101,6 +101,7 @@ from tests.typing import WebSocketGenerator
"min": "0",
"max": "100",
"step": "0.1",
"unit_of_measurement": "cm",
"set_value": {
"action": "input_number.set_value",
"target": {"entity_id": "input_number.test"},
@ -111,6 +112,7 @@ from tests.typing import WebSocketGenerator
"min": 0,
"max": 100,
"step": 0.1,
"unit_of_measurement": "cm",
"set_value": {
"action": "input_number.set_value",
"target": {"entity_id": "input_number.test"},
@ -454,6 +456,7 @@ def get_suggested(schema, key):
"min": 0,
"max": 100,
"step": 0.1,
"unit_of_measurement": "cm",
"set_value": {
"action": "input_number.set_value",
"target": {"entity_id": "input_number.test"},
@ -464,6 +467,7 @@ def get_suggested(schema, key):
"min": 0,
"max": 100,
"step": 0.1,
"unit_of_measurement": "cm",
"set_value": {
"action": "input_number.set_value",
"target": {"entity_id": "input_number.test"},

View File

@ -17,7 +17,12 @@ from homeassistant.components.number import (
SERVICE_SET_VALUE as NUMBER_SERVICE_SET_VALUE,
)
from homeassistant.components.template import DOMAIN
from homeassistant.const import ATTR_ICON, CONF_ENTITY_ID, STATE_UNKNOWN
from homeassistant.const import (
ATTR_ICON,
CONF_ENTITY_ID,
CONF_UNIT_OF_MEASUREMENT,
STATE_UNKNOWN,
)
from homeassistant.core import Context, HomeAssistant, ServiceCall
from homeassistant.helpers import device_registry as dr, entity_registry as er
@ -100,7 +105,7 @@ async def test_missing_optional_config(hass: HomeAssistant) -> None:
await hass.async_start()
await hass.async_block_till_done()
_verify(hass, 4, 1, 0.0, 100.0)
_verify(hass, 4, 1, 0.0, 100.0, None)
async def test_missing_required_keys(hass: HomeAssistant) -> None:
@ -152,6 +157,7 @@ async def test_all_optional_config(hass: HomeAssistant) -> None:
"min": "{{ 3 }}",
"max": "{{ 5 }}",
"step": "{{ 1 }}",
"unit_of_measurement": "beer",
}
}
},
@ -161,7 +167,7 @@ async def test_all_optional_config(hass: HomeAssistant) -> None:
await hass.async_start()
await hass.async_block_till_done()
_verify(hass, 4, 1, 3, 5)
_verify(hass, 4, 1, 3, 5, "beer")
async def test_templates_with_entities(
@ -249,7 +255,7 @@ async def test_templates_with_entities(
assert entry
assert entry.unique_id == "b-a"
_verify(hass, 4, 1, 3, 5)
_verify(hass, 4, 1, 3, 5, None)
await hass.services.async_call(
INPUT_NUMBER_DOMAIN,
@ -258,7 +264,7 @@ async def test_templates_with_entities(
blocking=True,
)
await hass.async_block_till_done()
_verify(hass, 5, 1, 3, 5)
_verify(hass, 5, 1, 3, 5, None)
await hass.services.async_call(
INPUT_NUMBER_DOMAIN,
@ -267,7 +273,7 @@ async def test_templates_with_entities(
blocking=True,
)
await hass.async_block_till_done()
_verify(hass, 5, 2, 3, 5)
_verify(hass, 5, 2, 3, 5, None)
await hass.services.async_call(
INPUT_NUMBER_DOMAIN,
@ -276,7 +282,7 @@ async def test_templates_with_entities(
blocking=True,
)
await hass.async_block_till_done()
_verify(hass, 5, 2, 2, 5)
_verify(hass, 5, 2, 2, 5, None)
await hass.services.async_call(
INPUT_NUMBER_DOMAIN,
@ -285,7 +291,7 @@ async def test_templates_with_entities(
blocking=True,
)
await hass.async_block_till_done()
_verify(hass, 5, 2, 2, 6)
_verify(hass, 5, 2, 2, 6, None)
await hass.services.async_call(
NUMBER_DOMAIN,
@ -293,7 +299,7 @@ async def test_templates_with_entities(
{CONF_ENTITY_ID: _TEST_NUMBER, NUMBER_ATTR_VALUE: 2},
blocking=True,
)
_verify(hass, 2, 2, 2, 6)
_verify(hass, 2, 2, 2, 6, None)
# Check this variable can be used in set_value script
assert len(calls) == 1
@ -323,6 +329,7 @@ async def test_trigger_number(hass: HomeAssistant) -> None:
"min": "{{ trigger.event.data.min_beers }}",
"max": "{{ trigger.event.data.max_beers }}",
"step": "{{ trigger.event.data.step }}",
"unit_of_measurement": "beer",
"set_value": {"event": "test_number_event"},
"optimistic": True,
},
@ -342,11 +349,17 @@ async def test_trigger_number(hass: HomeAssistant) -> None:
assert state.attributes["min"] == 0.0
assert state.attributes["max"] == 100.0
assert state.attributes["step"] == 1.0
assert state.attributes["unit_of_measurement"] == "beer"
context = Context()
hass.bus.async_fire(
"test_event",
{"beers_drank": 3, "min_beers": 1.0, "max_beers": 5.0, "step": 0.5},
{
"beers_drank": 3,
"min_beers": 1.0,
"max_beers": 5.0,
"step": 0.5,
},
context=context,
)
await hass.async_block_till_done()
@ -374,6 +387,7 @@ def _verify(
expected_step: int,
expected_minimum: int,
expected_maximum: int,
expected_unit_of_measurement: str | None,
) -> None:
"""Verify number's state."""
state = hass.states.get(_TEST_NUMBER)
@ -382,6 +396,7 @@ def _verify(
assert attributes.get(ATTR_STEP) == float(expected_step)
assert attributes.get(ATTR_MAX) == float(expected_maximum)
assert attributes.get(ATTR_MIN) == float(expected_minimum)
assert attributes.get(CONF_UNIT_OF_MEASUREMENT) == expected_unit_of_measurement
async def test_icon_template(hass: HomeAssistant) -> None: