mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
Move tuya models to separate module (#148550)
This commit is contained in:
parent
12f913e737
commit
eb20292683
@ -20,7 +20,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DPCode, DPType
|
||||
from .entity import EnumTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import EnumTypeData
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -25,7 +25,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DPCode, DPType
|
||||
from .entity import IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import IntegerTypeData
|
||||
|
||||
TUYA_HVAC_TO_HA = {
|
||||
"auto": HVACMode.HEAT_COOL,
|
||||
|
@ -21,7 +21,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DPCode, DPType
|
||||
from .entity import IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import IntegerTypeData
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -2,11 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
from dataclasses import dataclass
|
||||
import json
|
||||
import struct
|
||||
from typing import Any, Literal, Self, overload
|
||||
from typing import Any, Literal, overload
|
||||
|
||||
from tuya_sharing import CustomerDevice, Manager
|
||||
|
||||
@ -15,7 +11,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import DOMAIN, LOGGER, TUYA_HA_SIGNAL_UPDATE_ENTITY, DPCode, DPType
|
||||
from .util import remap_value
|
||||
from .models import EnumTypeData, IntegerTypeData
|
||||
|
||||
_DPTYPE_MAPPING: dict[str, DPType] = {
|
||||
"Bitmap": DPType.RAW,
|
||||
@ -29,118 +25,6 @@ _DPTYPE_MAPPING: dict[str, DPType] = {
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class IntegerTypeData:
|
||||
"""Integer Type Data."""
|
||||
|
||||
dpcode: DPCode
|
||||
min: int
|
||||
max: int
|
||||
scale: float
|
||||
step: float
|
||||
unit: str | None = None
|
||||
type: str | None = None
|
||||
|
||||
@property
|
||||
def max_scaled(self) -> float:
|
||||
"""Return the max scaled."""
|
||||
return self.scale_value(self.max)
|
||||
|
||||
@property
|
||||
def min_scaled(self) -> float:
|
||||
"""Return the min scaled."""
|
||||
return self.scale_value(self.min)
|
||||
|
||||
@property
|
||||
def step_scaled(self) -> float:
|
||||
"""Return the step scaled."""
|
||||
return self.step / (10**self.scale)
|
||||
|
||||
def scale_value(self, value: float) -> float:
|
||||
"""Scale a value."""
|
||||
return value / (10**self.scale)
|
||||
|
||||
def scale_value_back(self, value: float) -> int:
|
||||
"""Return raw value for scaled."""
|
||||
return int(value * (10**self.scale))
|
||||
|
||||
def remap_value_to(
|
||||
self,
|
||||
value: float,
|
||||
to_min: float = 0,
|
||||
to_max: float = 255,
|
||||
reverse: bool = False,
|
||||
) -> float:
|
||||
"""Remap a value from this range to a new range."""
|
||||
return remap_value(value, self.min, self.max, to_min, to_max, reverse)
|
||||
|
||||
def remap_value_from(
|
||||
self,
|
||||
value: float,
|
||||
from_min: float = 0,
|
||||
from_max: float = 255,
|
||||
reverse: bool = False,
|
||||
) -> float:
|
||||
"""Remap a value from its current range to this range."""
|
||||
return remap_value(value, from_min, from_max, self.min, self.max, reverse)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, dpcode: DPCode, data: str) -> IntegerTypeData | None:
|
||||
"""Load JSON string and return a IntegerTypeData object."""
|
||||
if not (parsed := json.loads(data)):
|
||||
return None
|
||||
|
||||
return cls(
|
||||
dpcode,
|
||||
min=int(parsed["min"]),
|
||||
max=int(parsed["max"]),
|
||||
scale=float(parsed["scale"]),
|
||||
step=max(float(parsed["step"]), 1),
|
||||
unit=parsed.get("unit"),
|
||||
type=parsed.get("type"),
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class EnumTypeData:
|
||||
"""Enum Type Data."""
|
||||
|
||||
dpcode: DPCode
|
||||
range: list[str]
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, dpcode: DPCode, data: str) -> EnumTypeData | None:
|
||||
"""Load JSON string and return a EnumTypeData object."""
|
||||
if not (parsed := json.loads(data)):
|
||||
return None
|
||||
return cls(dpcode, **parsed)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ElectricityTypeData:
|
||||
"""Electricity Type Data."""
|
||||
|
||||
electriccurrent: str | None = None
|
||||
power: str | None = None
|
||||
voltage: str | None = None
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data: str) -> Self:
|
||||
"""Load JSON string and return a ElectricityTypeData object."""
|
||||
return cls(**json.loads(data.lower()))
|
||||
|
||||
@classmethod
|
||||
def from_raw(cls, data: str) -> Self:
|
||||
"""Decode base64 string and return a ElectricityTypeData object."""
|
||||
raw = base64.b64decode(data)
|
||||
voltage = struct.unpack(">H", raw[0:2])[0] / 10.0
|
||||
electriccurrent = struct.unpack(">L", b"\x00" + raw[2:5])[0] / 1000.0
|
||||
power = struct.unpack(">L", b"\x00" + raw[5:8])[0] / 1000.0
|
||||
return cls(
|
||||
electriccurrent=str(electriccurrent), power=str(power), voltage=str(voltage)
|
||||
)
|
||||
|
||||
|
||||
class TuyaEntity(Entity):
|
||||
"""Tuya base device."""
|
||||
|
||||
|
@ -22,7 +22,8 @@ from homeassistant.util.percentage import (
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DPCode, DPType
|
||||
from .entity import EnumTypeData, IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import EnumTypeData, IntegerTypeData
|
||||
|
||||
TUYA_SUPPORT_TYPE = {
|
||||
"cs", # Dehumidifier
|
||||
|
@ -19,7 +19,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DPCode, DPType
|
||||
from .entity import IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import IntegerTypeData
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -25,7 +25,8 @@ from homeassistant.util import color as color_util
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DPCode, DPType, WorkMode
|
||||
from .entity import IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import IntegerTypeData
|
||||
from .util import remap_value
|
||||
|
||||
|
||||
|
124
homeassistant/components/tuya/models.py
Normal file
124
homeassistant/components/tuya/models.py
Normal file
@ -0,0 +1,124 @@
|
||||
"""Tuya Home Assistant Base Device Model."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
from dataclasses import dataclass
|
||||
import json
|
||||
import struct
|
||||
from typing import Self
|
||||
|
||||
from .const import DPCode
|
||||
from .util import remap_value
|
||||
|
||||
|
||||
@dataclass
|
||||
class IntegerTypeData:
|
||||
"""Integer Type Data."""
|
||||
|
||||
dpcode: DPCode
|
||||
min: int
|
||||
max: int
|
||||
scale: float
|
||||
step: float
|
||||
unit: str | None = None
|
||||
type: str | None = None
|
||||
|
||||
@property
|
||||
def max_scaled(self) -> float:
|
||||
"""Return the max scaled."""
|
||||
return self.scale_value(self.max)
|
||||
|
||||
@property
|
||||
def min_scaled(self) -> float:
|
||||
"""Return the min scaled."""
|
||||
return self.scale_value(self.min)
|
||||
|
||||
@property
|
||||
def step_scaled(self) -> float:
|
||||
"""Return the step scaled."""
|
||||
return self.step / (10**self.scale)
|
||||
|
||||
def scale_value(self, value: float) -> float:
|
||||
"""Scale a value."""
|
||||
return value / (10**self.scale)
|
||||
|
||||
def scale_value_back(self, value: float) -> int:
|
||||
"""Return raw value for scaled."""
|
||||
return int(value * (10**self.scale))
|
||||
|
||||
def remap_value_to(
|
||||
self,
|
||||
value: float,
|
||||
to_min: float = 0,
|
||||
to_max: float = 255,
|
||||
reverse: bool = False,
|
||||
) -> float:
|
||||
"""Remap a value from this range to a new range."""
|
||||
return remap_value(value, self.min, self.max, to_min, to_max, reverse)
|
||||
|
||||
def remap_value_from(
|
||||
self,
|
||||
value: float,
|
||||
from_min: float = 0,
|
||||
from_max: float = 255,
|
||||
reverse: bool = False,
|
||||
) -> float:
|
||||
"""Remap a value from its current range to this range."""
|
||||
return remap_value(value, from_min, from_max, self.min, self.max, reverse)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, dpcode: DPCode, data: str) -> IntegerTypeData | None:
|
||||
"""Load JSON string and return a IntegerTypeData object."""
|
||||
if not (parsed := json.loads(data)):
|
||||
return None
|
||||
|
||||
return cls(
|
||||
dpcode,
|
||||
min=int(parsed["min"]),
|
||||
max=int(parsed["max"]),
|
||||
scale=float(parsed["scale"]),
|
||||
step=max(float(parsed["step"]), 1),
|
||||
unit=parsed.get("unit"),
|
||||
type=parsed.get("type"),
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class EnumTypeData:
|
||||
"""Enum Type Data."""
|
||||
|
||||
dpcode: DPCode
|
||||
range: list[str]
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, dpcode: DPCode, data: str) -> EnumTypeData | None:
|
||||
"""Load JSON string and return a EnumTypeData object."""
|
||||
if not (parsed := json.loads(data)):
|
||||
return None
|
||||
return cls(dpcode, **parsed)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ElectricityTypeData:
|
||||
"""Electricity Type Data."""
|
||||
|
||||
electriccurrent: str | None = None
|
||||
power: str | None = None
|
||||
voltage: str | None = None
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data: str) -> Self:
|
||||
"""Load JSON string and return a ElectricityTypeData object."""
|
||||
return cls(**json.loads(data.lower()))
|
||||
|
||||
@classmethod
|
||||
def from_raw(cls, data: str) -> Self:
|
||||
"""Decode base64 string and return a ElectricityTypeData object."""
|
||||
raw = base64.b64decode(data)
|
||||
voltage = struct.unpack(">H", raw[0:2])[0] / 10.0
|
||||
electriccurrent = struct.unpack(">L", b"\x00" + raw[2:5])[0] / 1000.0
|
||||
power = struct.unpack(">L", b"\x00" + raw[5:8])[0] / 1000.0
|
||||
return cls(
|
||||
electriccurrent=str(electriccurrent), power=str(power), voltage=str(voltage)
|
||||
)
|
@ -16,7 +16,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import DEVICE_CLASS_UNITS, DOMAIN, TUYA_DISCOVERY_NEW, DPCode, DPType
|
||||
from .entity import IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import IntegerTypeData
|
||||
|
||||
# All descriptions can be found here. Mostly the Integer data types in the
|
||||
# default instructions set of each category end up being a number.
|
||||
|
@ -35,7 +35,8 @@ from .const import (
|
||||
DPType,
|
||||
UnitOfMeasurement,
|
||||
)
|
||||
from .entity import ElectricityTypeData, EnumTypeData, IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import ElectricityTypeData, EnumTypeData, IntegerTypeData
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -17,7 +17,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DPCode, DPType
|
||||
from .entity import EnumTypeData, IntegerTypeData, TuyaEntity
|
||||
from .entity import TuyaEntity
|
||||
from .models import EnumTypeData, IntegerTypeData
|
||||
|
||||
TUYA_MODE_RETURN_HOME = "chargego"
|
||||
TUYA_STATUS_TO_HA = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user