Use suggested unit of measurement in Tuya (#148599)

This commit is contained in:
epenet 2025-07-15 10:34:16 +02:00 committed by GitHub
parent f6aa4aa788
commit 41e261096a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 25 deletions

View File

@ -2,7 +2,6 @@
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass, field
from enum import StrEnum
import logging
@ -417,8 +416,6 @@ class UnitOfMeasurement:
device_classes: set[str]
aliases: set[str] = field(default_factory=set)
conversion_unit: str | None = None
conversion_fn: Callable[[float], float] | None = None
# A tuple of available units of measurements we can work with.
@ -458,8 +455,6 @@ UNITS = (
SensorDeviceClass.CO,
SensorDeviceClass.CO2,
},
conversion_unit=CONCENTRATION_PARTS_PER_MILLION,
conversion_fn=lambda x: x / 1000,
),
UnitOfMeasurement(
unit=UnitOfElectricCurrent.AMPERE,
@ -470,8 +465,6 @@ UNITS = (
unit=UnitOfElectricCurrent.MILLIAMPERE,
aliases={"ma", "milliampere"},
device_classes={SensorDeviceClass.CURRENT},
conversion_unit=UnitOfElectricCurrent.AMPERE,
conversion_fn=lambda x: x / 1000,
),
UnitOfMeasurement(
unit=UnitOfEnergy.WATT_HOUR,
@ -527,8 +520,6 @@ UNITS = (
SensorDeviceClass.SULPHUR_DIOXIDE,
SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
},
conversion_unit=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
conversion_fn=lambda x: x * 1000,
),
UnitOfMeasurement(
unit=UnitOfPower.WATT,
@ -596,8 +587,6 @@ UNITS = (
unit=UnitOfElectricPotential.MILLIVOLT,
aliases={"mv", "millivolt"},
device_classes={SensorDeviceClass.VOLTAGE},
conversion_unit=UnitOfElectricPotential.VOLT,
conversion_fn=lambda x: x / 1000,
),
)

View File

@ -382,20 +382,18 @@ class TuyaNumberEntity(TuyaEntity, NumberEntity):
return
uoms = DEVICE_CLASS_UNITS[self.device_class]
self._uom = uoms.get(self.native_unit_of_measurement) or uoms.get(
uom = uoms.get(self.native_unit_of_measurement) or uoms.get(
self.native_unit_of_measurement.lower()
)
# Unknown unit of measurement, device class should not be used.
if self._uom is None:
if uom is None:
self._attr_device_class = None
return
# Found unit of measurement, use the standardized Unit
# Use the target conversion unit (if set)
self._attr_native_unit_of_measurement = (
self._uom.conversion_unit or self._uom.unit
)
self._attr_native_unit_of_measurement = uom.unit
@property
def native_value(self) -> float | None:

View File

@ -14,6 +14,8 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfElectricCurrent,
@ -98,6 +100,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="current",
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
entity_registry_enabled_default=False,
),
TuyaSensorEntityDescription(
@ -112,6 +115,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="voltage",
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
entity_registry_enabled_default=False,
),
),
@ -164,6 +168,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.CH2O_VALUE,
@ -181,6 +186,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="pm25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
*BATTERY_SENSORS,
),
@ -192,6 +198,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="carbon_monoxide",
device_class=SensorDeviceClass.CO,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
*BATTERY_SENSORS,
),
@ -278,18 +285,21 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="pm25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
TuyaSensorEntityDescription(
key=DPCode.CO_VALUE,
translation_key="carbon_monoxide",
device_class=SensorDeviceClass.CO,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.CO2_VALUE,
translation_key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.CH2O_VALUE,
@ -418,6 +428,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="current",
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
entity_registry_enabled_default=False,
),
TuyaSensorEntityDescription(
@ -432,6 +443,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="voltage",
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
entity_registry_enabled_default=False,
),
),
@ -472,6 +484,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.CH2O_VALUE,
@ -489,12 +502,14 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="pm25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
TuyaSensorEntityDescription(
key=DPCode.PM10,
translation_key="pm10",
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
*BATTERY_SENSORS,
),
@ -506,6 +521,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.VOC_VALUE,
@ -518,6 +534,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="pm25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
TuyaSensorEntityDescription(
key=DPCode.VA_HUMIDITY,
@ -583,6 +600,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="current",
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
entity_registry_enabled_default=False,
),
TuyaSensorEntityDescription(
@ -597,6 +615,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="voltage",
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
entity_registry_enabled_default=False,
),
),
@ -613,6 +632,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="pm25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
TuyaSensorEntityDescription(
key=DPCode.TEMP,
@ -637,6 +657,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="concentration_carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.TOTAL_TIME,
@ -685,6 +706,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
*BATTERY_SENSORS,
),
@ -724,6 +746,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="pm25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
TuyaSensorEntityDescription(
key=DPCode.CH2O_VALUE,
@ -747,6 +770,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.HUMIDITY_VALUE,
@ -759,12 +783,14 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="pm1",
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
TuyaSensorEntityDescription(
key=DPCode.PM10,
translation_key="pm10",
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
*BATTERY_SENSORS,
),
@ -945,6 +971,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="current",
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
entity_registry_enabled_default=False,
),
TuyaSensorEntityDescription(
@ -959,6 +986,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="voltage",
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
entity_registry_enabled_default=False,
),
TuyaSensorEntityDescription(
@ -1004,12 +1032,14 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
),
TuyaSensorEntityDescription(
key=DPCode.PM25_VALUE,
translation_key="pm25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
),
TuyaSensorEntityDescription(
key=DPCode.CH2O_VALUE,
@ -1057,6 +1087,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="current",
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
entity_registry_enabled_default=False,
),
TuyaSensorEntityDescription(
@ -1071,6 +1102,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="voltage",
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
entity_registry_enabled_default=False,
),
),
@ -1097,6 +1129,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="current",
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
@ -1113,6 +1146,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="voltage",
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
@ -1415,20 +1449,18 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity):
return
uoms = DEVICE_CLASS_UNITS[self.device_class]
self._uom = uoms.get(self.native_unit_of_measurement) or uoms.get(
uom = uoms.get(self.native_unit_of_measurement) or uoms.get(
self.native_unit_of_measurement.lower()
)
# Unknown unit of measurement, device class should not be used.
if self._uom is None:
if uom is None:
self._attr_device_class = None
return
# Found unit of measurement, use the standardized Unit
# Use the target conversion unit (if set)
self._attr_native_unit_of_measurement = (
self._uom.conversion_unit or self._uom.unit
)
self._attr_native_unit_of_measurement = uom.unit
@property
def native_value(self) -> StateType:
@ -1450,10 +1482,7 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity):
# Scale integer/float value
if isinstance(self._type_data, IntegerTypeData):
scaled_value = self._type_data.scale_value(value)
if self._uom and self._uom.conversion_fn is not None:
return self._uom.conversion_fn(scaled_value)
return scaled_value
return self._type_data.scale_value(value)
# Unexpected enum value
if (

View File

@ -387,6 +387,9 @@
'sensor': dict({
'suggested_display_precision': 2,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
}),
'original_device_class': <SensorDeviceClass.CURRENT: 'current'>,
'original_icon': None,
@ -499,6 +502,9 @@
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricPotential.VOLT: 'V'>,
}),
}),
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
'original_icon': None,
@ -555,6 +561,9 @@
'sensor': dict({
'suggested_display_precision': 2,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
}),
'original_device_class': <SensorDeviceClass.CURRENT: 'current'>,
'original_icon': None,
@ -667,6 +676,9 @@
'sensor': dict({
'suggested_display_precision': 0,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricPotential.VOLT: 'V'>,
}),
}),
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
'original_icon': None,