diff --git a/homeassistant/components/mqtt/sensor.py b/homeassistant/components/mqtt/sensor.py index 783a0b30b14..b48a3c37a81 100644 --- a/homeassistant/components/mqtt/sensor.py +++ b/homeassistant/components/mqtt/sensor.py @@ -21,6 +21,7 @@ from homeassistant.components.sensor import ( SensorExtraStoredData, SensorStateClass, ) +from homeassistant.components.sensor.recorder import EQUIVALENT_UNITS from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( CONF_DEVICE_CLASS, @@ -132,6 +133,10 @@ def validate_sensor_state_and_device_class_config(config: ConfigType) -> ConfigT ) is None: return config + if unit_of_measurement in EQUIVALENT_UNITS: + unit_of_measurement = config[CONF_UNIT_OF_MEASUREMENT] = EQUIVALENT_UNITS[ + unit_of_measurement + ] if ( device_class in DEVICE_CLASS_UNITS and unit_of_measurement not in DEVICE_CLASS_UNITS[device_class] diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index 997c014cd13..ffe93851e48 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -906,6 +906,100 @@ async def test_invalid_unit_of_measurement( assert state is None +@pytest.mark.parametrize( + "hass_config", + [ + { + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "device_class": "voltage", + "unit_of_measurement": "\u00b5V", + } + } + } + ], +) +async def test_device_class_with_equivalent_unit_of_measurement_received( + 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("sensor.test") + assert state is not None + assert state.state == "100" + + caplog.clear() + + discovery_payload = { + "name": "bla", + "state_topic": "test-topic2", + "device_class": "voltage", + "unit_of_measurement": "\u00b5V", + } + # Now discover an invalid sensor + async_fire_mqtt_message( + hass, "homeassistant/sensor/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("sensor.bla") + assert state is not None + assert state.state == "21" + + +@pytest.mark.parametrize( + "hass_config", + [ + { + mqtt.DOMAIN: { + sensor.DOMAIN: { + "name": "test", + "state_topic": "test-topic", + "unit_of_measurement": "\u00b5V", + } + } + } + ], +) +async def test_equivalent_unit_of_measurement_received_without_device_class( + 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("sensor.test") + assert state is not None + assert state.state == "100" + + caplog.clear() + + discovery_payload = { + "name": "bla", + "state_topic": "test-topic2", + "unit_of_measurement": "\u00b5V", + } + # Now discover an invalid sensor + async_fire_mqtt_message( + hass, "homeassistant/sensor/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("sensor.bla") + assert state is not None + assert state.state == "21" + + @pytest.mark.parametrize( "hass_config", [