diff --git a/homeassistant/components/tuya/binary_sensor.py b/homeassistant/components/tuya/binary_sensor.py index 00479ac69c1..72b44a71036 100644 --- a/homeassistant/components/tuya/binary_sensor.py +++ b/homeassistant/components/tuya/binary_sensor.py @@ -372,7 +372,7 @@ class _CustomDPCodeWrapper(DPCodeWrapper): _valid_values: set[bool | float | int | str] def __init__( - self, dpcode: DPCode, valid_values: set[bool | float | int | str] + self, dpcode: str, valid_values: set[bool | float | int | str] ) -> None: """Init CustomDPCodeBooleanWrapper.""" super().__init__(dpcode) @@ -390,7 +390,7 @@ def _get_dpcode_wrapper( description: TuyaBinarySensorEntityDescription, ) -> DPCodeWrapper | None: """Get DPCode wrapper for an entity description.""" - dpcode = description.dpcode or DPCode(description.key) + dpcode = description.dpcode or description.key if description.bitmap_key is not None: return DPCodeBitmapBitWrapper.find_dpcode( device, dpcode, bitmap_key=description.bitmap_key diff --git a/homeassistant/components/tuya/humidifier.py b/homeassistant/components/tuya/humidifier.py index d7fa459368d..af1613fe330 100644 --- a/homeassistant/components/tuya/humidifier.py +++ b/homeassistant/components/tuya/humidifier.py @@ -49,9 +49,9 @@ def _has_a_valid_dpcode( device: CustomerDevice, description: TuyaHumidifierEntityDescription ) -> bool: """Check if the device has at least one valid DP code.""" - properties_to_check: list[DPCode | tuple[DPCode, ...] | None] = [ + properties_to_check: list[str | tuple[str, ...] | None] = [ # Main control switch - description.dpcode or DPCode(description.key), + description.dpcode or description.key, # Other humidity properties description.current_humidity, description.humidity, @@ -107,7 +107,7 @@ async def async_setup_entry( ), switch_wrapper=DPCodeBooleanWrapper.find_dpcode( device, - description.dpcode or DPCode(description.key), + description.dpcode or description.key, prefer_function=True, ), target_humidity_wrapper=_RoundedIntegerWrapper.find_dpcode( diff --git a/homeassistant/components/tuya/models.py b/homeassistant/components/tuya/models.py index 9fd88cf0218..3ca36c6d4f5 100644 --- a/homeassistant/components/tuya/models.py +++ b/homeassistant/components/tuya/models.py @@ -10,7 +10,7 @@ from tuya_sharing import CustomerDevice from homeassistant.util.json import json_loads, json_loads_object -from .const import LOGGER, DPCode, DPType +from .const import LOGGER, DPType from .util import parse_dptype, remap_value # Dictionary to track logged warnings to avoid spamming logs @@ -39,11 +39,11 @@ class TypeInformation: As provided by the SDK, from `device.function` / `device.status_range`. """ - dpcode: DPCode + dpcode: str type_data: str | None = None @classmethod - def from_json(cls, dpcode: DPCode, type_data: str) -> Self | None: + def from_json(cls, dpcode: str, type_data: str) -> Self | None: """Load JSON string and return a TypeInformation object.""" return cls(dpcode=dpcode, type_data=type_data) @@ -102,7 +102,7 @@ class IntegerTypeData(TypeInformation): return remap_value(value, from_min, from_max, self.min, self.max, reverse) @classmethod - def from_json(cls, dpcode: DPCode, type_data: str) -> Self | None: + def from_json(cls, dpcode: str, type_data: str) -> Self | None: """Load JSON string and return a IntegerTypeData object.""" if not (parsed := cast(dict[str, Any] | None, json_loads_object(type_data))): return None @@ -125,7 +125,7 @@ class BitmapTypeInformation(TypeInformation): label: list[str] @classmethod - def from_json(cls, dpcode: DPCode, type_data: str) -> Self | None: + def from_json(cls, dpcode: str, type_data: str) -> Self | None: """Load JSON string and return a BitmapTypeInformation object.""" if not (parsed := json_loads_object(type_data)): return None @@ -143,7 +143,7 @@ class EnumTypeData(TypeInformation): range: list[str] @classmethod - def from_json(cls, dpcode: DPCode, type_data: str) -> Self | None: + def from_json(cls, dpcode: str, type_data: str) -> Self | None: """Load JSON string and return a EnumTypeData object.""" if not (parsed := json_loads_object(type_data)): return None @@ -175,7 +175,7 @@ class DPCodeWrapper: native_unit: str | None = None suggested_unit: str | None = None - def __init__(self, dpcode: DPCode) -> None: + def __init__(self, dpcode: str) -> None: """Init DPCodeWrapper.""" self.dpcode = dpcode @@ -222,7 +222,7 @@ class DPCodeTypeInformationWrapper[T: TypeInformation](DPCodeWrapper): DPTYPE: DPType type_information: T - def __init__(self, dpcode: DPCode, type_information: T) -> None: + def __init__(self, dpcode: str, type_information: T) -> None: """Init DPCodeWrapper.""" super().__init__(dpcode) self.type_information = type_information @@ -231,7 +231,7 @@ class DPCodeTypeInformationWrapper[T: TypeInformation](DPCodeWrapper): def find_dpcode( cls, device: CustomerDevice, - dpcodes: str | DPCode | tuple[DPCode, ...] | None, + dpcodes: str | tuple[str, ...] | None, *, prefer_function: bool = False, ) -> Self | None: @@ -340,7 +340,7 @@ class DPCodeIntegerWrapper(DPCodeTypeInformationWrapper[IntegerTypeData]): DPTYPE = DPType.INTEGER - def __init__(self, dpcode: DPCode, type_information: IntegerTypeData) -> None: + def __init__(self, dpcode: str, type_information: IntegerTypeData) -> None: """Init DPCodeIntegerWrapper.""" super().__init__(dpcode, type_information) self.native_unit = type_information.unit @@ -380,7 +380,7 @@ class DPCodeStringWrapper(DPCodeTypeInformationWrapper[TypeInformation]): class DPCodeBitmapBitWrapper(DPCodeWrapper): """Simple wrapper for a specific bit in bitmap values.""" - def __init__(self, dpcode: DPCode, mask: int) -> None: + def __init__(self, dpcode: str, mask: int) -> None: """Init DPCodeBitmapWrapper.""" super().__init__(dpcode) self._mask = mask @@ -395,7 +395,7 @@ class DPCodeBitmapBitWrapper(DPCodeWrapper): def find_dpcode( cls, device: CustomerDevice, - dpcodes: str | DPCode | tuple[DPCode, ...], + dpcodes: str | tuple[str, ...], *, bitmap_key: str, ) -> Self | None: @@ -412,7 +412,7 @@ class DPCodeBitmapBitWrapper(DPCodeWrapper): @overload def find_dpcode( device: CustomerDevice, - dpcodes: str | DPCode | tuple[DPCode, ...] | None, + dpcodes: str | tuple[str, ...] | None, *, prefer_function: bool = False, dptype: Literal[DPType.BITMAP], @@ -422,7 +422,7 @@ def find_dpcode( @overload def find_dpcode( device: CustomerDevice, - dpcodes: str | DPCode | tuple[DPCode, ...] | None, + dpcodes: str | tuple[str, ...] | None, *, prefer_function: bool = False, dptype: Literal[DPType.ENUM], @@ -432,7 +432,7 @@ def find_dpcode( @overload def find_dpcode( device: CustomerDevice, - dpcodes: str | DPCode | tuple[DPCode, ...] | None, + dpcodes: str | tuple[str, ...] | None, *, prefer_function: bool = False, dptype: Literal[DPType.INTEGER], @@ -442,7 +442,7 @@ def find_dpcode( @overload def find_dpcode( device: CustomerDevice, - dpcodes: str | DPCode | tuple[DPCode, ...] | None, + dpcodes: str | tuple[str, ...] | None, *, prefer_function: bool = False, dptype: Literal[DPType.BOOLEAN, DPType.JSON, DPType.RAW], @@ -451,7 +451,7 @@ def find_dpcode( def find_dpcode( device: CustomerDevice, - dpcodes: str | DPCode | tuple[DPCode, ...] | None, + dpcodes: str | tuple[str, ...] | None, *, prefer_function: bool = False, dptype: DPType, @@ -463,9 +463,7 @@ def find_dpcode( if dpcodes is None: return None - if isinstance(dpcodes, str): - dpcodes = (DPCode(dpcodes),) - elif not isinstance(dpcodes, tuple): + if not isinstance(dpcodes, tuple): dpcodes = (dpcodes,) lookup_tuple = ( diff --git a/homeassistant/components/tuya/util.py b/homeassistant/components/tuya/util.py index 43f2b1b7841..aa554b6e1cd 100644 --- a/homeassistant/components/tuya/util.py +++ b/homeassistant/components/tuya/util.py @@ -20,16 +20,14 @@ _DPTYPE_MAPPING: dict[str, DPType] = { def get_dpcode( - device: CustomerDevice, dpcodes: str | DPCode | tuple[DPCode, ...] | None -) -> DPCode | None: + device: CustomerDevice, dpcodes: str | tuple[str, ...] | None +) -> str | None: """Get the first matching DPCode from the device or return None.""" if dpcodes is None: return None - if isinstance(dpcodes, DPCode): + if not isinstance(dpcodes, tuple): dpcodes = (dpcodes,) - elif isinstance(dpcodes, str): - dpcodes = (DPCode(dpcodes),) for dpcode in dpcodes: if ( @@ -70,19 +68,23 @@ class ActionDPCodeNotFoundError(ServiceValidationError): """Custom exception for action DP code not found errors.""" def __init__( - self, device: CustomerDevice, expected: str | DPCode | tuple[DPCode, ...] | None + self, device: CustomerDevice, expected: str | tuple[str, ...] | None ) -> None: """Initialize the error with device and expected DP codes.""" if expected is None: expected = () # empty tuple for no expected codes - elif isinstance(expected, str): - expected = (DPCode(expected),) + elif not isinstance(expected, tuple): + expected = (expected,) super().__init__( translation_domain=DOMAIN, translation_key="action_dpcode_not_found", translation_placeholders={ - "expected": str(sorted([dp.value for dp in expected])), + "expected": str( + sorted( + [dp.value if isinstance(dp, DPCode) else dp for dp in expected] + ) + ), "available": str(sorted(device.function.keys())), }, )