|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | | -import base64 |
6 | | -from dataclasses import dataclass |
7 | | -import json |
8 | | -import struct |
9 | | -from typing import Any, Literal, Self, overload |
| 5 | +from typing import Any, Literal, overload |
10 | 6 |
|
11 | 7 | from tuya_sharing import CustomerDevice, Manager |
12 | 8 |
|
|
15 | 11 | from homeassistant.helpers.entity import Entity |
16 | 12 |
|
17 | 13 | from .const import DOMAIN, LOGGER, TUYA_HA_SIGNAL_UPDATE_ENTITY, DPCode, DPType |
18 | | -from .util import remap_value |
| 14 | +from .models import EnumTypeData, IntegerTypeData |
19 | 15 |
|
20 | 16 | _DPTYPE_MAPPING: dict[str, DPType] = { |
21 | 17 | "Bitmap": DPType.RAW, |
|
29 | 25 | } |
30 | 26 |
|
31 | 27 |
|
32 | | -@dataclass |
33 | | -class IntegerTypeData: |
34 | | - """Integer Type Data.""" |
35 | | - |
36 | | - dpcode: DPCode |
37 | | - min: int |
38 | | - max: int |
39 | | - scale: float |
40 | | - step: float |
41 | | - unit: str | None = None |
42 | | - type: str | None = None |
43 | | - |
44 | | - @property |
45 | | - def max_scaled(self) -> float: |
46 | | - """Return the max scaled.""" |
47 | | - return self.scale_value(self.max) |
48 | | - |
49 | | - @property |
50 | | - def min_scaled(self) -> float: |
51 | | - """Return the min scaled.""" |
52 | | - return self.scale_value(self.min) |
53 | | - |
54 | | - @property |
55 | | - def step_scaled(self) -> float: |
56 | | - """Return the step scaled.""" |
57 | | - return self.step / (10**self.scale) |
58 | | - |
59 | | - def scale_value(self, value: float) -> float: |
60 | | - """Scale a value.""" |
61 | | - return value / (10**self.scale) |
62 | | - |
63 | | - def scale_value_back(self, value: float) -> int: |
64 | | - """Return raw value for scaled.""" |
65 | | - return int(value * (10**self.scale)) |
66 | | - |
67 | | - def remap_value_to( |
68 | | - self, |
69 | | - value: float, |
70 | | - to_min: float = 0, |
71 | | - to_max: float = 255, |
72 | | - reverse: bool = False, |
73 | | - ) -> float: |
74 | | - """Remap a value from this range to a new range.""" |
75 | | - return remap_value(value, self.min, self.max, to_min, to_max, reverse) |
76 | | - |
77 | | - def remap_value_from( |
78 | | - self, |
79 | | - value: float, |
80 | | - from_min: float = 0, |
81 | | - from_max: float = 255, |
82 | | - reverse: bool = False, |
83 | | - ) -> float: |
84 | | - """Remap a value from its current range to this range.""" |
85 | | - return remap_value(value, from_min, from_max, self.min, self.max, reverse) |
86 | | - |
87 | | - @classmethod |
88 | | - def from_json(cls, dpcode: DPCode, data: str) -> IntegerTypeData | None: |
89 | | - """Load JSON string and return a IntegerTypeData object.""" |
90 | | - if not (parsed := json.loads(data)): |
91 | | - return None |
92 | | - |
93 | | - return cls( |
94 | | - dpcode, |
95 | | - min=int(parsed["min"]), |
96 | | - max=int(parsed["max"]), |
97 | | - scale=float(parsed["scale"]), |
98 | | - step=max(float(parsed["step"]), 1), |
99 | | - unit=parsed.get("unit"), |
100 | | - type=parsed.get("type"), |
101 | | - ) |
102 | | - |
103 | | - |
104 | | -@dataclass |
105 | | -class EnumTypeData: |
106 | | - """Enum Type Data.""" |
107 | | - |
108 | | - dpcode: DPCode |
109 | | - range: list[str] |
110 | | - |
111 | | - @classmethod |
112 | | - def from_json(cls, dpcode: DPCode, data: str) -> EnumTypeData | None: |
113 | | - """Load JSON string and return a EnumTypeData object.""" |
114 | | - if not (parsed := json.loads(data)): |
115 | | - return None |
116 | | - return cls(dpcode, **parsed) |
117 | | - |
118 | | - |
119 | | -@dataclass |
120 | | -class ElectricityTypeData: |
121 | | - """Electricity Type Data.""" |
122 | | - |
123 | | - electriccurrent: str | None = None |
124 | | - power: str | None = None |
125 | | - voltage: str | None = None |
126 | | - |
127 | | - @classmethod |
128 | | - def from_json(cls, data: str) -> Self: |
129 | | - """Load JSON string and return a ElectricityTypeData object.""" |
130 | | - return cls(**json.loads(data.lower())) |
131 | | - |
132 | | - @classmethod |
133 | | - def from_raw(cls, data: str) -> Self: |
134 | | - """Decode base64 string and return a ElectricityTypeData object.""" |
135 | | - raw = base64.b64decode(data) |
136 | | - voltage = struct.unpack(">H", raw[0:2])[0] / 10.0 |
137 | | - electriccurrent = struct.unpack(">L", b"\x00" + raw[2:5])[0] / 1000.0 |
138 | | - power = struct.unpack(">L", b"\x00" + raw[5:8])[0] / 1000.0 |
139 | | - return cls( |
140 | | - electriccurrent=str(electriccurrent), power=str(power), voltage=str(voltage) |
141 | | - ) |
142 | | - |
143 | | - |
144 | 28 | class TuyaEntity(Entity): |
145 | 29 | """Tuya base device.""" |
146 | 30 |
|
|
0 commit comments