From aa58d49903bfe214f5696b4ae2195c2c00614588 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:46:36 +0000 Subject: [PATCH] Move Tuya get_dptype method out of base entity --- homeassistant/components/tuya/entity.py | 32 ------------------------- homeassistant/components/tuya/light.py | 8 +++---- homeassistant/components/tuya/sensor.py | 3 ++- homeassistant/components/tuya/util.py | 30 ++++++++++++++++++++++- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/homeassistant/components/tuya/entity.py b/homeassistant/components/tuya/entity.py index 0ae0f793afd..f4f5c48fafa 100644 --- a/homeassistant/components/tuya/entity.py +++ b/homeassistant/components/tuya/entity.py @@ -13,16 +13,6 @@ from homeassistant.helpers.entity import Entity from .const import DOMAIN, LOGGER, TUYA_HA_SIGNAL_UPDATE_ENTITY, DPCode, DPType from .models import EnumTypeData, IntegerTypeData -_DPTYPE_MAPPING: dict[str, DPType] = { - "bitmap": DPType.BITMAP, - "bool": DPType.BOOLEAN, - "enum": DPType.ENUM, - "json": DPType.JSON, - "raw": DPType.RAW, - "string": DPType.STRING, - "value": DPType.INTEGER, -} - class TuyaEntity(Entity): """Tuya base device.""" @@ -125,28 +115,6 @@ class TuyaEntity(Entity): return None - def get_dptype( - self, dpcode: DPCode | None, prefer_function: bool = False - ) -> DPType | None: - """Find a matching DPCode data type available on for this device.""" - if dpcode is None: - return None - - order = ["status_range", "function"] - if prefer_function: - order = ["function", "status_range"] - for key in order: - if dpcode in getattr(self.device, key): - current_type = getattr(self.device, key)[dpcode].type - try: - return DPType(current_type) - except ValueError: - # Sometimes, we get ill-formed DPTypes from the cloud, - # this fixes them and maps them to the correct DPType. - return _DPTYPE_MAPPING.get(current_type) - - return None - async def async_added_to_hass(self) -> None: """Call when entity is added to hass.""" self.async_on_remove( diff --git a/homeassistant/components/tuya/light.py b/homeassistant/components/tuya/light.py index 9848351047c..d0e5c6013b1 100644 --- a/homeassistant/components/tuya/light.py +++ b/homeassistant/components/tuya/light.py @@ -29,7 +29,7 @@ from . import TuyaConfigEntry from .const import TUYA_DISCOVERY_NEW, DPCode, DPType, WorkMode from .entity import TuyaEntity from .models import IntegerTypeData -from .util import get_dpcode, remap_value +from .util import get_dpcode, get_dptype, remap_value @dataclass @@ -529,9 +529,9 @@ class TuyaLightEntity(TuyaEntity, LightEntity): description.brightness_min, dptype=DPType.INTEGER ) - if ( - dpcode := get_dpcode(self.device, description.color_data) - ) and self.get_dptype(dpcode) == DPType.JSON: + if (dpcode := get_dpcode(self.device, description.color_data)) and get_dptype( + self.device, dpcode + ) == DPType.JSON: self._color_data_dpcode = dpcode color_modes.add(ColorMode.HS) if dpcode in self.device.function: diff --git a/homeassistant/components/tuya/sensor.py b/homeassistant/components/tuya/sensor.py index 5ca6e1d77a0..58005a0063f 100644 --- a/homeassistant/components/tuya/sensor.py +++ b/homeassistant/components/tuya/sensor.py @@ -41,6 +41,7 @@ from .const import ( ) from .entity import TuyaEntity from .models import ComplexTypeData, ElectricityTypeData, EnumTypeData, IntegerTypeData +from .util import get_dptype @dataclass(frozen=True) @@ -1531,7 +1532,7 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity): self._type_data = enum_type self._type = DPType.ENUM else: - self._type = self.get_dptype(DPCode(description.key)) + self._type = get_dptype(self.device, DPCode(description.key)) # Logic to ensure the set device class and API received Unit Of Measurement # match Home Assistants requirements. diff --git a/homeassistant/components/tuya/util.py b/homeassistant/components/tuya/util.py index af6a78c1476..8afe66fb4c0 100644 --- a/homeassistant/components/tuya/util.py +++ b/homeassistant/components/tuya/util.py @@ -6,7 +6,17 @@ from tuya_sharing import CustomerDevice from homeassistant.exceptions import ServiceValidationError -from .const import DOMAIN, DPCode +from .const import DOMAIN, DPCode, DPType + +_DPTYPE_MAPPING: dict[str, DPType] = { + "bitmap": DPType.BITMAP, + "bool": DPType.BOOLEAN, + "enum": DPType.ENUM, + "json": DPType.JSON, + "raw": DPType.RAW, + "string": DPType.STRING, + "value": DPType.INTEGER, +} def get_dpcode( @@ -32,6 +42,24 @@ def get_dpcode( return None +def get_dptype(device: CustomerDevice, dpcode: DPCode | None) -> DPType | None: + """Find a matching DPType type information for this device DPCode.""" + if dpcode is None: + return None + + for device_specs in (device.status_range, device.function): + if current_definition := device_specs.get(dpcode): + current_type = current_definition.type + try: + return DPType(current_type) + except ValueError: + # Sometimes, we get ill-formed DPTypes from the cloud, + # this fixes them and maps them to the correct DPType. + return _DPTYPE_MAPPING.get(current_type) + + return None + + def remap_value( value: float, from_min: float = 0,