Make Tuya complex type handling explicit

This commit is contained in:
epenet 2025-07-30 15:30:56 +00:00
parent 749fc318ca
commit a878bec668
2 changed files with 47 additions and 7 deletions

View File

@ -99,8 +99,22 @@ class EnumTypeData:
return cls(dpcode, **parsed) return cls(dpcode, **parsed)
class ComplexTypeData:
"""Complex Type Data (for JSON/RAW parsing)."""
@classmethod
def from_json(cls, data: str) -> Self:
"""Load JSON string and return a BaseTypeData object."""
raise NotImplementedError("from_json is not implemented for this type")
@classmethod
def from_raw(cls, data: str) -> Self:
"""Decode base64 string and return a BaseTypeData object."""
raise NotImplementedError("from_raw is not implemented for this type")
@dataclass @dataclass
class ElectricityTypeData: class ElectricityTypeData(ComplexTypeData):
"""Electricity Type Data.""" """Electricity Type Data."""
electriccurrent: str | None = None electriccurrent: str | None = None

View File

@ -40,13 +40,14 @@ from .const import (
UnitOfMeasurement, UnitOfMeasurement,
) )
from .entity import TuyaEntity from .entity import TuyaEntity
from .models import ElectricityTypeData, EnumTypeData, IntegerTypeData from .models import ComplexTypeData, ElectricityTypeData, EnumTypeData, IntegerTypeData
@dataclass(frozen=True) @dataclass(frozen=True)
class TuyaSensorEntityDescription(SensorEntityDescription): class TuyaSensorEntityDescription(SensorEntityDescription):
"""Describes Tuya sensor entity.""" """Describes Tuya sensor entity."""
complex_type: type[ComplexTypeData] | None = None
subkey: str | None = None subkey: str | None = None
@ -368,6 +369,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
complex_type=ElectricityTypeData,
subkey="electriccurrent", subkey="electriccurrent",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -376,6 +378,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.KILO_WATT, native_unit_of_measurement=UnitOfPower.KILO_WATT,
complex_type=ElectricityTypeData,
subkey="power", subkey="power",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -384,6 +387,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.VOLTAGE, device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT, native_unit_of_measurement=UnitOfElectricPotential.VOLT,
complex_type=ElectricityTypeData,
subkey="voltage", subkey="voltage",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -392,6 +396,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
complex_type=ElectricityTypeData,
subkey="electriccurrent", subkey="electriccurrent",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -400,6 +405,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.KILO_WATT, native_unit_of_measurement=UnitOfPower.KILO_WATT,
complex_type=ElectricityTypeData,
subkey="power", subkey="power",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -408,6 +414,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.VOLTAGE, device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT, native_unit_of_measurement=UnitOfElectricPotential.VOLT,
complex_type=ElectricityTypeData,
subkey="voltage", subkey="voltage",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -416,6 +423,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
complex_type=ElectricityTypeData,
subkey="electriccurrent", subkey="electriccurrent",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -424,6 +432,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.KILO_WATT, native_unit_of_measurement=UnitOfPower.KILO_WATT,
complex_type=ElectricityTypeData,
subkey="power", subkey="power",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -432,6 +441,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.VOLTAGE, device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT, native_unit_of_measurement=UnitOfElectricPotential.VOLT,
complex_type=ElectricityTypeData,
subkey="voltage", subkey="voltage",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1247,6 +1257,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
translation_key="total_power", translation_key="total_power",
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
complex_type=ElectricityTypeData,
subkey="power", subkey="power",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1255,6 +1266,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
complex_type=ElectricityTypeData,
subkey="electriccurrent", subkey="electriccurrent",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1263,6 +1275,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.KILO_WATT, native_unit_of_measurement=UnitOfPower.KILO_WATT,
complex_type=ElectricityTypeData,
subkey="power", subkey="power",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1271,6 +1284,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.VOLTAGE, device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT, native_unit_of_measurement=UnitOfElectricPotential.VOLT,
complex_type=ElectricityTypeData,
subkey="voltage", subkey="voltage",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1279,6 +1293,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
complex_type=ElectricityTypeData,
subkey="electriccurrent", subkey="electriccurrent",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1287,6 +1302,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.KILO_WATT, native_unit_of_measurement=UnitOfPower.KILO_WATT,
complex_type=ElectricityTypeData,
subkey="power", subkey="power",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1295,6 +1311,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.VOLTAGE, device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT, native_unit_of_measurement=UnitOfElectricPotential.VOLT,
complex_type=ElectricityTypeData,
subkey="voltage", subkey="voltage",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1303,6 +1320,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
complex_type=ElectricityTypeData,
subkey="electriccurrent", subkey="electriccurrent",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1311,6 +1329,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.KILO_WATT, native_unit_of_measurement=UnitOfPower.KILO_WATT,
complex_type=ElectricityTypeData,
subkey="power", subkey="power",
), ),
TuyaSensorEntityDescription( TuyaSensorEntityDescription(
@ -1319,6 +1338,7 @@ SENSORS: dict[str, tuple[TuyaSensorEntityDescription, ...]] = {
device_class=SensorDeviceClass.VOLTAGE, device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT, native_unit_of_measurement=UnitOfElectricPotential.VOLT,
complex_type=ElectricityTypeData,
subkey="voltage", subkey="voltage",
), ),
), ),
@ -1417,7 +1437,7 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity):
_status_range: DeviceStatusRange | None = None _status_range: DeviceStatusRange | None = None
_type: DPType | None = None _type: DPType | None = None
_type_data: IntegerTypeData | EnumTypeData | None = None _type_data: IntegerTypeData | EnumTypeData | ComplexTypeData | None = None
_uom: UnitOfMeasurement | None = None _uom: UnitOfMeasurement | None = None
def __init__( def __init__(
@ -1516,15 +1536,21 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity):
# Get subkey value from Json string. # Get subkey value from Json string.
if self._type is DPType.JSON: if self._type is DPType.JSON:
if self.entity_description.subkey is None: if (
self.entity_description.complex_type is None
or self.entity_description.subkey is None
):
return None return None
values = ElectricityTypeData.from_json(value) values = self.entity_description.complex_type.from_json(value)
return getattr(values, self.entity_description.subkey) return getattr(values, self.entity_description.subkey)
if self._type is DPType.RAW: if self._type is DPType.RAW:
if self.entity_description.subkey is None: if (
self.entity_description.complex_type is None
or self.entity_description.subkey is None
):
return None return None
values = ElectricityTypeData.from_raw(value) values = self.entity_description.complex_type.from_raw(value)
return getattr(values, self.entity_description.subkey) return getattr(values, self.entity_description.subkey)
# Valid string or enum value # Valid string or enum value