Skip to content

Commit 43e241e

Browse files
authored
Use process_raw_value in Tuya RawTypeInformation (home-assistant#158521)
1 parent 6af7052 commit 43e241e

File tree

5 files changed

+27
-29
lines changed

5 files changed

+27
-29
lines changed

homeassistant/components/tuya/alarm_control_panel.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from . import TuyaConfigEntry
2121
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode
2222
from .entity import TuyaEntity
23-
from .models import DPCodeBase64Wrapper, DPCodeEnumWrapper
23+
from .models import DPCodeEnumWrapper, DPCodeRawWrapper
2424

2525
ALARM: dict[DeviceCategory, tuple[AlarmControlPanelEntityDescription, ...]] = {
2626
DeviceCategory.MAL: (
@@ -32,7 +32,7 @@
3232
}
3333

3434

35-
class _AlarmChangedByWrapper(DPCodeBase64Wrapper):
35+
class _AlarmChangedByWrapper(DPCodeRawWrapper):
3636
"""Wrapper for changed_by.
3737
3838
Decode base64 to utf-16be string, but only if alarm has been triggered.
@@ -42,10 +42,10 @@ def read_device_status(self, device: CustomerDevice) -> str | None:
4242
"""Read the device status."""
4343
if (
4444
device.status.get(DPCode.MASTER_STATE) != "alarm"
45-
or (data := self.read_bytes(device)) is None
45+
or (status := super().read_device_status(device)) is None
4646
):
4747
return None
48-
return data.decode("utf-16be")
48+
return status.decode("utf-16be")
4949

5050

5151
class _AlarmModeWrapper(DPCodeEnumWrapper):
@@ -182,8 +182,6 @@ def alarm_state(self) -> AlarmControlPanelState | None:
182182
@property
183183
def changed_by(self) -> str | None:
184184
"""Last change triggered by."""
185-
if self._changed_by_wrapper is None:
186-
return None
187185
return self._read_wrapper(self._changed_by_wrapper)
188186

189187
async def async_alarm_disarm(self, code: str | None = None) -> None:

homeassistant/components/tuya/event.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode
2222
from .entity import TuyaEntity
2323
from .models import (
24-
DPCodeBase64Wrapper,
2524
DPCodeEnumWrapper,
25+
DPCodeRawWrapper,
2626
DPCodeStringWrapper,
2727
DPCodeTypeInformationWrapper,
2828
)
@@ -82,17 +82,17 @@ def get_event_attributes(self, device: CustomerDevice) -> dict[str, Any] | None:
8282
return {"message": b64decode(raw_value).decode("utf-8")}
8383

8484

85-
class _DoorbellPicWrapper(DPCodeBase64Wrapper, _DPCodeEventWrapper):
85+
class _DoorbellPicWrapper(DPCodeRawWrapper, _DPCodeEventWrapper):
8686
"""Wrapper for a RAW message on DPCode.DOORBELL_PIC.
8787
8888
It is expected that the RAW data is base64/utf8 encoded URL of the picture.
8989
"""
9090

9191
def get_event_attributes(self, device: CustomerDevice) -> dict[str, Any] | None:
9292
"""Return the event attributes for the doorbell picture."""
93-
if (raw_value := self._read_device_status_raw(device)) is None:
93+
if (status := super().read_device_status(device)) is None:
9494
return None
95-
return {"message": b64decode(raw_value).decode("utf-8")}
95+
return {"message": status.decode("utf-8")}
9696

9797

9898
@dataclass(frozen=True)

homeassistant/components/tuya/models.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from __future__ import annotations
44

5-
import base64
65
from typing import Any, Self
76

87
from tuya_sharing import CustomerDevice
@@ -114,20 +113,6 @@ def find_dpcode(
114113
return None
115114

116115

117-
class DPCodeBase64Wrapper(DPCodeTypeInformationWrapper[RawTypeInformation]):
118-
"""Wrapper to extract information from a RAW/binary value."""
119-
120-
_DPTYPE = RawTypeInformation
121-
122-
def read_bytes(self, device: CustomerDevice) -> bytes | None:
123-
"""Read the device value for the dpcode."""
124-
if (raw_value := self._read_device_status_raw(device)) is None or (
125-
len(decoded := base64.b64decode(raw_value)) == 0
126-
):
127-
return None
128-
return decoded
129-
130-
131116
class DPCodeBooleanWrapper(DPCodeTypeInformationWrapper[BooleanTypeInformation]):
132117
"""Simple wrapper for boolean values.
133118
@@ -198,6 +183,12 @@ def _convert_value_to_raw_value(self, device: CustomerDevice, value: Any) -> Any
198183
)
199184

200185

186+
class DPCodeRawWrapper(DPCodeTypeInformationWrapper[RawTypeInformation]):
187+
"""Wrapper to extract information from a RAW/binary value."""
188+
189+
_DPTYPE = RawTypeInformation
190+
191+
201192
class DPCodeStringWrapper(DPCodeTypeInformationWrapper[StringTypeInformation]):
202193
"""Wrapper to extract information from a STRING value."""
203194

homeassistant/components/tuya/sensor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@
3939
)
4040
from .entity import TuyaEntity
4141
from .models import (
42-
DPCodeBase64Wrapper,
4342
DPCodeEnumWrapper,
4443
DPCodeIntegerWrapper,
4544
DPCodeJsonWrapper,
45+
DPCodeRawWrapper,
4646
DPCodeTypeInformationWrapper,
4747
DPCodeWrapper,
4848
)
@@ -119,7 +119,7 @@ def read_device_status(self, device: CustomerDevice) -> float | None:
119119
return raw_value.get("voltage")
120120

121121

122-
class _RawElectricityDataWrapper(DPCodeBase64Wrapper):
122+
class _RawElectricityDataWrapper(DPCodeRawWrapper):
123123
"""Custom DPCode Wrapper for extracting ElectricityData from base64."""
124124

125125
def _convert(self, value: ElectricityData) -> float:
@@ -128,7 +128,7 @@ def _convert(self, value: ElectricityData) -> float:
128128

129129
def read_device_status(self, device: CustomerDevice) -> float | None:
130130
"""Read the device value for the dpcode."""
131-
if (raw_value := super().read_bytes(device)) is None or (
131+
if (raw_value := super().read_device_status(device)) is None or (
132132
value := ElectricityData.from_bytes(raw_value)
133133
) is None:
134134
return None

homeassistant/components/tuya/type_information.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import base64
56
from dataclasses import dataclass
67
from typing import Any, ClassVar, Self, cast
78

@@ -292,11 +293,19 @@ class JsonTypeInformation(TypeInformation[Any]):
292293

293294

294295
@dataclass(kw_only=True)
295-
class RawTypeInformation(TypeInformation[Any]):
296+
class RawTypeInformation(TypeInformation[bytes]):
296297
"""Raw type information."""
297298

298299
_DPTYPE = DPType.RAW
299300

301+
def process_raw_value(
302+
self, raw_value: Any | None, device: CustomerDevice
303+
) -> bytes | None:
304+
"""Read and process raw value against this type information."""
305+
if raw_value is None:
306+
return None
307+
return base64.b64decode(raw_value)
308+
300309

301310
@dataclass(kw_only=True)
302311
class StringTypeInformation(TypeInformation[str]):

0 commit comments

Comments
 (0)