mirror of
https://github.com/home-assistant/core.git
synced 2026-04-02 08:26:41 +01:00
KNX: add config for device_class and unit_of_measurement for yaml number entities (#165083)
This commit is contained in:
@@ -120,6 +120,19 @@ class KnxYamlNumber(_KnxNumber, KnxYamlEntity):
|
||||
value_type=config[CONF_TYPE],
|
||||
),
|
||||
)
|
||||
dpt_string = self._device.sensor_value.dpt_class.dpt_number_str()
|
||||
dpt_info = get_supported_dpts()[dpt_string]
|
||||
|
||||
self._attr_device_class = config.get(
|
||||
CONF_DEVICE_CLASS,
|
||||
try_parse_enum(
|
||||
# sensor device classes should, with some exceptions ("enum" etc.), align with number device classes
|
||||
NumberDeviceClass,
|
||||
dpt_info["sensor_device_class"],
|
||||
),
|
||||
)
|
||||
self._attr_entity_category = config.get(CONF_ENTITY_CATEGORY)
|
||||
self._attr_mode = config[CONF_MODE]
|
||||
self._attr_native_max_value = config.get(
|
||||
NumberConf.MAX,
|
||||
self._device.sensor_value.dpt_class.value_max,
|
||||
@@ -128,14 +141,16 @@ class KnxYamlNumber(_KnxNumber, KnxYamlEntity):
|
||||
NumberConf.MIN,
|
||||
self._device.sensor_value.dpt_class.value_min,
|
||||
)
|
||||
self._attr_mode = config[CONF_MODE]
|
||||
self._attr_native_step = config.get(
|
||||
NumberConf.STEP,
|
||||
self._device.sensor_value.dpt_class.resolution,
|
||||
)
|
||||
self._attr_entity_category = config.get(CONF_ENTITY_CATEGORY)
|
||||
self._attr_native_unit_of_measurement = config.get(
|
||||
CONF_UNIT_OF_MEASUREMENT,
|
||||
dpt_info["unit"],
|
||||
)
|
||||
self._attr_unique_id = str(self._device.sensor_value.group_address)
|
||||
self._attr_native_unit_of_measurement = self._device.unit_of_measurement()
|
||||
|
||||
self._device.sensor_value.value = max(0, self._attr_native_min_value)
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ from homeassistant.components.climate import FAN_OFF, HVACMode
|
||||
from homeassistant.components.cover import (
|
||||
DEVICE_CLASSES_SCHEMA as COVER_DEVICE_CLASSES_SCHEMA,
|
||||
)
|
||||
from homeassistant.components.number import NumberMode
|
||||
from homeassistant.components.number import (
|
||||
DEVICE_CLASSES_SCHEMA as NUMBER_DEVICE_CLASSES_SCHEMA,
|
||||
NumberMode,
|
||||
)
|
||||
from homeassistant.components.sensor import (
|
||||
CONF_STATE_CLASS as CONF_SENSOR_STATE_CLASS,
|
||||
DEVICE_CLASSES_SCHEMA as SENSOR_DEVICE_CLASSES_SCHEMA,
|
||||
@@ -39,6 +42,7 @@ from homeassistant.const import (
|
||||
CONF_NAME,
|
||||
CONF_PAYLOAD,
|
||||
CONF_TYPE,
|
||||
CONF_UNIT_OF_MEASUREMENT,
|
||||
CONF_VALUE_TEMPLATE,
|
||||
Platform,
|
||||
)
|
||||
@@ -787,6 +791,8 @@ class NumberSchema(KNXPlatformSchema):
|
||||
vol.Optional(NumberConf.MAX): vol.Coerce(float),
|
||||
vol.Optional(NumberConf.MIN): vol.Coerce(float),
|
||||
vol.Optional(NumberConf.STEP): cv.positive_float,
|
||||
vol.Optional(CONF_DEVICE_CLASS): NUMBER_DEVICE_CLASSES_SCHEMA,
|
||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||
vol.Optional(CONF_ENTITY_CATEGORY): ENTITY_CATEGORIES_SCHEMA,
|
||||
}
|
||||
),
|
||||
|
||||
@@ -7,7 +7,10 @@ from homeassistant.components.knx.dpt import (
|
||||
_sensor_state_class_overrides,
|
||||
_sensor_unit_overrides,
|
||||
)
|
||||
from homeassistant.components.knx.schema import _sensor_attribute_sub_validator
|
||||
from homeassistant.components.knx.schema import (
|
||||
_number_limit_sub_validator,
|
||||
_sensor_attribute_sub_validator,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -31,3 +34,9 @@ def test_dpt_default_device_classes(dpt: str) -> None:
|
||||
# UI validation works the same way, but uses different schema for config
|
||||
{"type": dpt}
|
||||
)
|
||||
number_config = {"type": dpt}
|
||||
if dpt.startswith("14"):
|
||||
# DPT 14 has infinite range which isn't supported by HA
|
||||
# this test shall still check for correct device_class and unit_of_measurement
|
||||
number_config |= {"min": -500000, "max": 500000}
|
||||
assert _number_limit_sub_validator(number_config)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Test KNX number."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
@@ -111,6 +112,44 @@ async def test_number_restore_and_respond(hass: HomeAssistant, knx: KNXTestKit)
|
||||
assert state.state == "9000.96"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"attribute_config",
|
||||
[
|
||||
{"device_class": "energy"}, # invalid with uom of temperature DPT
|
||||
{"device_class": "energy", "unit_of_measurement": "invalid"},
|
||||
{"device_class": "invalid"},
|
||||
],
|
||||
)
|
||||
async def test_number_yaml_attribute_validation(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
knx: KNXTestKit,
|
||||
attribute_config: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test creating a number with invalid unit or device_class."""
|
||||
with caplog.at_level(logging.ERROR):
|
||||
await knx.setup_integration(
|
||||
{
|
||||
NumberSchema.PLATFORM: {
|
||||
CONF_NAME: "test",
|
||||
KNX_ADDRESS: "1/1/1",
|
||||
CONF_TYPE: "9.001", # temperature 2 byte float
|
||||
**attribute_config,
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(caplog.messages) == 2
|
||||
record = caplog.records[0]
|
||||
assert record.levelname == "ERROR"
|
||||
assert "Invalid config for 'knx': " in record.message
|
||||
|
||||
record = caplog.records[1]
|
||||
assert record.levelname == "ERROR"
|
||||
assert "Setup failed for 'knx': Invalid config." in record.message
|
||||
|
||||
assert hass.states.get("number.test") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("knx_config", "set_value", "expected_telegram", "expected_state"),
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user