mirror of
https://github.com/home-assistant/core.git
synced 2025-08-04 11:08:17 +00:00
Include MQTT number and assert on sensor and number unit
This commit is contained in:
parent
8bc70354ca
commit
af643c05ab
@ -16,6 +16,7 @@ from homeassistant.components.number import (
|
|||||||
NumberMode,
|
NumberMode,
|
||||||
RestoreNumber,
|
RestoreNumber,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.sensor.recorder import EQUIVALENT_UNITS
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DEVICE_CLASS,
|
CONF_DEVICE_CLASS,
|
||||||
@ -70,6 +71,13 @@ MQTT_NUMBER_ATTRIBUTES_BLOCKED = frozenset(
|
|||||||
|
|
||||||
def validate_config(config: ConfigType) -> ConfigType:
|
def validate_config(config: ConfigType) -> ConfigType:
|
||||||
"""Validate that the configuration is valid, throws if it isn't."""
|
"""Validate that the configuration is valid, throws if it isn't."""
|
||||||
|
if (
|
||||||
|
CONF_UNIT_OF_MEASUREMENT in config
|
||||||
|
and (unit_of_measurement := config[CONF_UNIT_OF_MEASUREMENT])
|
||||||
|
in EQUIVALENT_UNITS
|
||||||
|
):
|
||||||
|
config[CONF_UNIT_OF_MEASUREMENT] = EQUIVALENT_UNITS[unit_of_measurement]
|
||||||
|
|
||||||
if config[CONF_MIN] > config[CONF_MAX]:
|
if config[CONF_MIN] > config[CONF_MAX]:
|
||||||
raise vol.Invalid(f"{CONF_MAX} must be >= {CONF_MIN}")
|
raise vol.Invalid(f"{CONF_MAX} must be >= {CONF_MIN}")
|
||||||
|
|
||||||
|
@ -130,13 +130,15 @@ def validate_sensor_state_and_device_class_config(config: ConfigType) -> ConfigT
|
|||||||
|
|
||||||
if (device_class := config.get(CONF_DEVICE_CLASS)) is None or (
|
if (device_class := config.get(CONF_DEVICE_CLASS)) is None or (
|
||||||
unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)
|
unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)
|
||||||
) is None:
|
) in EQUIVALENT_UNITS:
|
||||||
|
unit_of_measurement = EQUIVALENT_UNITS[unit_of_measurement]
|
||||||
|
config[CONF_UNIT_OF_MEASUREMENT] = unit_of_measurement
|
||||||
|
|
||||||
|
if (
|
||||||
|
device_class := config.get(CONF_DEVICE_CLASS)
|
||||||
|
) is None or unit_of_measurement is None:
|
||||||
return config
|
return config
|
||||||
|
|
||||||
if unit_of_measurement in EQUIVALENT_UNITS:
|
|
||||||
unit_of_measurement = config[CONF_UNIT_OF_MEASUREMENT] = EQUIVALENT_UNITS[
|
|
||||||
unit_of_measurement
|
|
||||||
]
|
|
||||||
if (
|
if (
|
||||||
device_class in DEVICE_CLASS_UNITS
|
device_class in DEVICE_CLASS_UNITS
|
||||||
and unit_of_measurement not in DEVICE_CLASS_UNITS[device_class]
|
and unit_of_measurement not in DEVICE_CLASS_UNITS[device_class]
|
||||||
|
@ -91,7 +91,7 @@ EQUIVALENT_UNITS = {
|
|||||||
"\u00b5g/ft³": CONCENTRATION_MICROGRAMS_PER_CUBIC_FOOT,
|
"\u00b5g/ft³": CONCENTRATION_MICROGRAMS_PER_CUBIC_FOOT,
|
||||||
"\u00b5g/m³": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
"\u00b5g/m³": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
"\u00b5mol/s⋅m²": "μmol/s⋅m²", # fyta: light
|
"\u00b5mol/s⋅m²": "μmol/s⋅m²", # fyta: light
|
||||||
"\u0065g": UnitOfMass.MICROGRAMS,
|
"\u00b5g": UnitOfMass.MICROGRAMS,
|
||||||
"\u00b5s": UnitOfTime.MICROSECONDS,
|
"\u00b5s": UnitOfTime.MICROSECONDS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ from homeassistant.const import (
|
|||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
ATTR_MODE,
|
ATTR_MODE,
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
|
UnitOfElectricPotential,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, State
|
from homeassistant.core import HomeAssistant, State
|
||||||
@ -253,6 +254,62 @@ async def test_native_value_validation(
|
|||||||
mqtt_mock.async_publish.reset_mock()
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"hass_config",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
number.DOMAIN: {
|
||||||
|
"name": "test",
|
||||||
|
"command_topic": "test-topic-cmd",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unit_of_measurement": "\u00b5V",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_equivalent_unit_of_measurement(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test device_class with equivalent unit of measurement."""
|
||||||
|
assert await mqtt_mock_entry()
|
||||||
|
async_fire_mqtt_message(hass, "test-topic", "100")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("number.test")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == "100"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
is UnitOfElectricPotential.MICROVOLT
|
||||||
|
)
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
discovery_payload = {
|
||||||
|
"name": "bla",
|
||||||
|
"command_topic": "test-topic2-cmd",
|
||||||
|
"state_topic": "test-topic2",
|
||||||
|
"unit_of_measurement": "\u00b5V",
|
||||||
|
}
|
||||||
|
# Now discover an invalid sensor
|
||||||
|
async_fire_mqtt_message(
|
||||||
|
hass, "homeassistant/number/bla/config", json.dumps(discovery_payload)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
async_fire_mqtt_message(hass, "test-topic2", "21")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("number.bla")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == "21"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
is UnitOfElectricPotential.MICROVOLT
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"hass_config",
|
"hass_config",
|
||||||
[
|
[
|
||||||
|
@ -15,9 +15,11 @@ import pytest
|
|||||||
from homeassistant.components import mqtt, sensor
|
from homeassistant.components import mqtt, sensor
|
||||||
from homeassistant.components.mqtt.sensor import MQTT_SENSOR_ATTRIBUTES_BLOCKED
|
from homeassistant.components.mqtt.sensor import MQTT_SENSOR_ATTRIBUTES_BLOCKED
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
EVENT_STATE_CHANGED,
|
EVENT_STATE_CHANGED,
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
|
UnitOfElectricPotential,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import Event, HomeAssistant, State, callback
|
from homeassistant.core import Event, HomeAssistant, State, callback
|
||||||
@ -933,6 +935,10 @@ async def test_device_class_with_equivalent_unit_of_measurement_received(
|
|||||||
state = hass.states.get("sensor.test")
|
state = hass.states.get("sensor.test")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == "100"
|
assert state.state == "100"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
is UnitOfElectricPotential.MICROVOLT
|
||||||
|
)
|
||||||
|
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
|
|
||||||
@ -952,6 +958,10 @@ async def test_device_class_with_equivalent_unit_of_measurement_received(
|
|||||||
state = hass.states.get("sensor.bla")
|
state = hass.states.get("sensor.bla")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == "21"
|
assert state.state == "21"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
is UnitOfElectricPotential.MICROVOLT
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@ -980,6 +990,10 @@ async def test_equivalent_unit_of_measurement_received_without_device_class(
|
|||||||
state = hass.states.get("sensor.test")
|
state = hass.states.get("sensor.test")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == "100"
|
assert state.state == "100"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
is UnitOfElectricPotential.MICROVOLT
|
||||||
|
)
|
||||||
|
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
|
|
||||||
@ -998,6 +1012,10 @@ async def test_equivalent_unit_of_measurement_received_without_device_class(
|
|||||||
state = hass.states.get("sensor.bla")
|
state = hass.states.get("sensor.bla")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == "21"
|
assert state.state == "21"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
is UnitOfElectricPotential.MICROVOLT
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user