mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add unit_of_measurement to template numbers (#122862)
This commit is contained in:
parent
8e0b2b752c
commit
56dfb2c734
@ -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(),
|
||||
}
|
||||
|
||||
|
@ -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."""
|
||||
|
@ -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%]"
|
||||
|
@ -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"},
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user