mirror of
https://github.com/home-assistant/core.git
synced 2026-04-27 06:26:17 +00:00
Add climate/switch
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from tuya_sharing import CustomerDevice, Manager
|
||||
@@ -28,6 +28,8 @@ from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
|
||||
from .entity import TuyaEntity
|
||||
from .models import IntegerTypeData
|
||||
from .util import get_dpcode
|
||||
from .xternal_tuya_quirks import TUYA_QUIRKS_REGISTRY
|
||||
from .xternal_tuya_quirks.climate import CommonClimateType, TuyaClimateDefinition
|
||||
|
||||
TUYA_HVAC_TO_HA = {
|
||||
"auto": HVACMode.HEAT_COOL,
|
||||
@@ -75,6 +77,22 @@ CLIMATE_DESCRIPTIONS: dict[DeviceCategory, TuyaClimateEntityDescription] = {
|
||||
),
|
||||
}
|
||||
|
||||
COMMON_CLIMATE_DEFINITIONS: dict[CommonClimateType, TuyaClimateEntityDescription] = {
|
||||
CommonClimateType.SWITCH_ONLY_HEAT_COOL: TuyaClimateEntityDescription(
|
||||
key="tbc",
|
||||
switch_only_hvac_mode=HVACMode.HEAT_COOL,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
def _create_quirk_description(
|
||||
definition: TuyaClimateDefinition,
|
||||
) -> TuyaClimateEntityDescription:
|
||||
return replace(
|
||||
COMMON_CLIMATE_DEFINITIONS[definition.common_type],
|
||||
key=definition.key,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@@ -90,7 +108,17 @@ async def async_setup_entry(
|
||||
entities: list[TuyaClimateEntity] = []
|
||||
for device_id in device_ids:
|
||||
device = manager.device_map[device_id]
|
||||
if device and device.category in CLIMATE_DESCRIPTIONS:
|
||||
if quirk := TUYA_QUIRKS_REGISTRY.get_quirk_for_device(device):
|
||||
entities.extend(
|
||||
TuyaClimateEntity(
|
||||
device,
|
||||
manager,
|
||||
_create_quirk_description(definition),
|
||||
hass.config.units.temperature_unit,
|
||||
)
|
||||
for definition in quirk.climate_definitions
|
||||
)
|
||||
elif device.category in CLIMATE_DESCRIPTIONS:
|
||||
entities.append(
|
||||
TuyaClimateEntity(
|
||||
device,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from tuya_sharing import CustomerDevice, Manager
|
||||
@@ -24,7 +24,7 @@ from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
|
||||
from .entity import TuyaEntity
|
||||
from .models import EnumTypeData, IntegerTypeData
|
||||
from .util import get_dpcode
|
||||
from .xternal_tuya_quirks import TUYA_QUIRKS_REGISTRY, parse_enum
|
||||
from .xternal_tuya_quirks import TUYA_QUIRKS_REGISTRY
|
||||
from .xternal_tuya_quirks.cover import CommonCoverType, TuyaCoverDefinition
|
||||
|
||||
|
||||
@@ -156,14 +156,12 @@ COMMON_COVER_DEFINITIONS: dict[CommonCoverType, TuyaCoverEntityDescription] = {
|
||||
def _create_quirk_description(
|
||||
definition: TuyaCoverDefinition,
|
||||
) -> TuyaCoverEntityDescription:
|
||||
common_definition = COMMON_COVER_DEFINITIONS[definition.common_type]
|
||||
return TuyaCoverEntityDescription(
|
||||
return replace(
|
||||
COMMON_COVER_DEFINITIONS[definition.common_type],
|
||||
key=definition.key,
|
||||
device_class=common_definition.device_class,
|
||||
translation_key=common_definition.translation_key,
|
||||
current_state=parse_enum(DPCode, definition.current_state_dp_code),
|
||||
current_position=parse_enum(DPCode, definition.current_position_dp_code),
|
||||
set_position=parse_enum(DPCode, definition.set_position_dp_code),
|
||||
current_state=definition.current_state_dp_code,
|
||||
current_position=definition.current_position_dp_code,
|
||||
set_position=definition.set_position_dp_code,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import replace
|
||||
|
||||
from tuya_sharing import CustomerDevice, Manager
|
||||
|
||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||
@@ -356,11 +358,9 @@ COMMON_SELECT_DEFINITIONS: dict[CommonSelectType, SelectEntityDescription] = {
|
||||
def _create_quirk_description(
|
||||
definition: TuyaSelectDefinition,
|
||||
) -> SelectEntityDescription:
|
||||
common_definition = COMMON_SELECT_DEFINITIONS[definition.common_type]
|
||||
return SelectEntityDescription(
|
||||
return replace(
|
||||
COMMON_SELECT_DEFINITIONS[definition.common_type],
|
||||
key=DPCode(definition.key),
|
||||
translation_key=common_definition.translation_key,
|
||||
entity_category=common_definition.entity_category,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
from typing import Any
|
||||
|
||||
from tuya_sharing import CustomerDevice, Manager
|
||||
@@ -73,7 +73,12 @@ class TuyaSensorEntityDescription(SensorEntityDescription):
|
||||
|
||||
complex_type: type[ComplexValue] | None = None
|
||||
subkey: str | None = None
|
||||
state_conversion: Callable[[Any], StateType] | None = None
|
||||
state_conversion: (
|
||||
Callable[
|
||||
[CustomerDevice, EnumTypeData | IntegerTypeData | None, Any], StateType
|
||||
]
|
||||
| None
|
||||
) = None
|
||||
|
||||
|
||||
# Commonly used battery sensors, that are reused in the sensors down below.
|
||||
@@ -960,7 +965,9 @@ SENSORS: dict[DeviceCategory, tuple[TuyaSensorEntityDescription, ...]] = {
|
||||
translation_key="wind_direction",
|
||||
device_class=SensorDeviceClass.WIND_DIRECTION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
state_conversion=lambda state: _WIND_DIRECTIONS.get(str(state)),
|
||||
state_conversion=lambda _device, _dptype, state: _WIND_DIRECTIONS.get(
|
||||
str(state)
|
||||
),
|
||||
),
|
||||
TuyaSensorEntityDescription(
|
||||
key=DPCode.DEW_POINT_TEMP,
|
||||
@@ -1627,23 +1634,27 @@ SENSORS[DeviceCategory.DGHSXJ] = SENSORS[DeviceCategory.SP]
|
||||
SENSORS[DeviceCategory.PC] = SENSORS[DeviceCategory.KG]
|
||||
|
||||
COMMON_SENSOR_DEFINITIONS: dict[CommonSensorType, TuyaSensorEntityDescription] = {
|
||||
CommonSensorType.TEMPERATURE: TuyaSensorEntityDescription(
|
||||
key="tbc",
|
||||
translation_key="temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
CommonSensorType.TIME_TOTAL: TuyaSensorEntityDescription(
|
||||
key="tbc",
|
||||
translation_key="last_operation_duration",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _create_quirk_description(
|
||||
definition: TuyaSensorDefinition,
|
||||
) -> TuyaSensorEntityDescription:
|
||||
common_definition = COMMON_SENSOR_DEFINITIONS[definition.common_type]
|
||||
return TuyaSensorEntityDescription(
|
||||
return replace(
|
||||
COMMON_SENSOR_DEFINITIONS[definition.common_type],
|
||||
key=DPCode(definition.key),
|
||||
translation_key=common_definition.translation_key,
|
||||
device_class=common_definition.device_class,
|
||||
entity_category=common_definition.entity_category,
|
||||
state_conversion=definition.state_conversion,
|
||||
)
|
||||
|
||||
|
||||
@@ -1782,7 +1793,7 @@ class TuyaSensorEntity(TuyaEntity, SensorEntity):
|
||||
|
||||
# Convert value, if required
|
||||
if (convert := self.entity_description.state_conversion) is not None:
|
||||
return convert(value)
|
||||
return convert(self.device, self._type_data, value)
|
||||
|
||||
# Scale integer/float value
|
||||
if isinstance(self._type_data, IntegerTypeData):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
from typing import Any
|
||||
|
||||
from tuya_sharing import CustomerDevice, Manager
|
||||
@@ -27,6 +27,8 @@ from homeassistant.helpers.issue_registry import (
|
||||
from . import TuyaConfigEntry
|
||||
from .const import DOMAIN, TUYA_DISCOVERY_NEW, DeviceCategory, DPCode
|
||||
from .entity import TuyaEntity
|
||||
from .xternal_tuya_quirks import TUYA_QUIRKS_REGISTRY
|
||||
from .xternal_tuya_quirks.switch import CommonSwitchType, TuyaSwitchDefinition
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
@@ -898,6 +900,23 @@ SWITCHES[DeviceCategory.CZ] = SWITCHES[DeviceCategory.PC]
|
||||
# Smart Camera - Low power consumption camera (duplicate of `sp`)
|
||||
SWITCHES[DeviceCategory.DGHSXJ] = SWITCHES[DeviceCategory.SP]
|
||||
|
||||
COMMON_SWITCH_DEFINITIONS: dict[CommonSwitchType, SwitchEntityDescription] = {
|
||||
CommonSwitchType.CHILD_LOCK: SwitchEntityDescription(
|
||||
key="tbc",
|
||||
translation_key="child_lock",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
def _create_quirk_description(
|
||||
definition: TuyaSwitchDefinition,
|
||||
) -> SwitchEntityDescription:
|
||||
return replace(
|
||||
COMMON_SWITCH_DEFINITIONS[definition.common_type],
|
||||
key=DPCode(definition.key),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@@ -914,7 +933,15 @@ async def async_setup_entry(
|
||||
entities: list[TuyaSwitchEntity] = []
|
||||
for device_id in device_ids:
|
||||
device = manager.device_map[device_id]
|
||||
if descriptions := SWITCHES.get(device.category):
|
||||
if quirk := TUYA_QUIRKS_REGISTRY.get_quirk_for_device(device):
|
||||
entities.extend(
|
||||
TuyaSwitchEntity(
|
||||
device, manager, _create_quirk_description(definition)
|
||||
)
|
||||
for definition in quirk.switch_definitions
|
||||
if definition.key in device.status
|
||||
)
|
||||
elif descriptions := SWITCHES.get(device.category):
|
||||
entities.extend(
|
||||
TuyaSwitchEntity(device, manager, description)
|
||||
for description in descriptions
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ..const import DPCode
|
||||
from ..xternal_tuya_quirks import TUYA_QUIRKS_REGISTRY, TuyaDeviceQuirk
|
||||
from ..xternal_tuya_quirks.cover import CommonCoverType
|
||||
from ..xternal_tuya_quirks.select import CommonSelectType
|
||||
@@ -13,17 +14,14 @@ from ..xternal_tuya_quirks.sensor import CommonSensorType
|
||||
TuyaDeviceQuirk()
|
||||
.applies_to(category="cl", product_id="g1cp07dsqnbdbbki")
|
||||
.add_common_cover(
|
||||
key="control",
|
||||
key=DPCode.CONTROL,
|
||||
common_type=CommonCoverType.CURTAIN,
|
||||
current_position_dp_code="percent_control",
|
||||
current_state_dp_code="control",
|
||||
set_position_dp_code="percent_control",
|
||||
set_state_dp_code="control",
|
||||
current_position_dp_code=DPCode.PERCENT_CONTROL,
|
||||
set_position_dp_code=DPCode.PERCENT_CONTROL,
|
||||
)
|
||||
.add_common_select(
|
||||
key="control_back_mode",
|
||||
key=DPCode.CONTROL_BACK_MODE,
|
||||
common_type=CommonSelectType.CONTROL_BACK_MODE,
|
||||
dp_code="control_back_mode",
|
||||
)
|
||||
.register(TUYA_QUIRKS_REGISTRY)
|
||||
)
|
||||
@@ -33,19 +31,17 @@ from ..xternal_tuya_quirks.sensor import CommonSensorType
|
||||
TuyaDeviceQuirk()
|
||||
.applies_to(category="cl", product_id="lfkr93x0ukp5gaia")
|
||||
.add_common_cover(
|
||||
key="control",
|
||||
key=DPCode.CONTROL,
|
||||
common_type=CommonCoverType.CURTAIN,
|
||||
current_state_dp_code="control",
|
||||
current_state_dp_code=DPCode.CONTROL,
|
||||
)
|
||||
.add_common_select(
|
||||
key="control_back_mode",
|
||||
key=DPCode.CONTROL_BACK_MODE,
|
||||
common_type=CommonSelectType.CONTROL_BACK_MODE,
|
||||
dp_code="control_back_mode",
|
||||
)
|
||||
.add_common_sensor(
|
||||
key="time_total",
|
||||
key=DPCode.TIME_TOTAL,
|
||||
common_type=CommonSensorType.TIME_TOTAL,
|
||||
dp_code="time_total",
|
||||
)
|
||||
.register(TUYA_QUIRKS_REGISTRY)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
"""Quirks for Tuya."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import cast
|
||||
|
||||
from ..const import DPCode
|
||||
from ..models import IntegerTypeData
|
||||
from ..xternal_tuya_quirks import TUYA_QUIRKS_REGISTRY, TuyaDeviceQuirk
|
||||
from ..xternal_tuya_quirks.climate import CommonClimateType
|
||||
from ..xternal_tuya_quirks.sensor import CommonSensorType
|
||||
from ..xternal_tuya_quirks.switch import CommonSwitchType
|
||||
from ..xternal_tuya_quirks.utils import scale_value_force_scale_1
|
||||
|
||||
(
|
||||
# This model has percent_state and percent_control but percent_state never
|
||||
# gets updated - force percent_control instead
|
||||
TuyaDeviceQuirk()
|
||||
.applies_to(category="wk", product_id="IAYz2WK1th0cMLmL")
|
||||
.add_common_climate(
|
||||
key="wk", # to avoid breaking change
|
||||
common_type=CommonClimateType.SWITCH_ONLY_HEAT_COOL,
|
||||
switch_dp_code=DPCode.SWITCH,
|
||||
current_temperature_dp_code=DPCode.UPPER_TEMP,
|
||||
set_temperature_dp_code=DPCode.TEMP_SET,
|
||||
)
|
||||
.add_common_sensor(
|
||||
key=DPCode.UPPER_TEMP,
|
||||
common_type=CommonSensorType.TEMPERATURE,
|
||||
state_conversion=lambda _device, dptype, value: scale_value_force_scale_1(
|
||||
cast(IntegerTypeData, dptype), cast(float, value)
|
||||
),
|
||||
)
|
||||
.add_common_switch(
|
||||
key=DPCode.CHILD_LOCK,
|
||||
common_type=CommonSwitchType.CHILD_LOCK,
|
||||
)
|
||||
.register(TUYA_QUIRKS_REGISTRY)
|
||||
)
|
||||
27
homeassistant/components/tuya/xternal_tuya_quirks/climate.py
Normal file
27
homeassistant/components/tuya/xternal_tuya_quirks/climate.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""Common climate quirks for Tuya devices."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from ..const import DPCode
|
||||
|
||||
|
||||
class CommonClimateType(StrEnum):
|
||||
"""Common climate types."""
|
||||
|
||||
SWITCH_ONLY_HEAT_COOL = "switch_only_heat_cool"
|
||||
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class TuyaClimateDefinition:
|
||||
"""Definition for a climate entity."""
|
||||
|
||||
key: str
|
||||
|
||||
common_type: CommonClimateType
|
||||
|
||||
current_temperature_dp_code: DPCode | None = None
|
||||
set_temperature_dp_code: DPCode | None = None
|
||||
switch_dp_code: DPCode | None = None
|
||||
@@ -5,6 +5,8 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from ..const import DPCode
|
||||
|
||||
|
||||
class CommonCoverType(StrEnum):
|
||||
"""Common cover types."""
|
||||
@@ -20,7 +22,7 @@ class TuyaCoverDefinition:
|
||||
|
||||
common_type: CommonCoverType
|
||||
|
||||
current_position_dp_code: str | None = None
|
||||
current_state_dp_code: str | None = None
|
||||
set_position_dp_code: str | None = None
|
||||
set_state_dp_code: str
|
||||
current_position_dp_code: DPCode | None = None
|
||||
current_state_dp_code: DPCode | None = None
|
||||
set_position_dp_code: DPCode | None = None
|
||||
set_state_dp_code: DPCode
|
||||
|
||||
@@ -2,13 +2,20 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
import inspect
|
||||
import pathlib
|
||||
from typing import TYPE_CHECKING, Self
|
||||
from typing import TYPE_CHECKING, Any, Self
|
||||
|
||||
from tuya_sharing import CustomerDevice
|
||||
|
||||
from ..const import DPCode
|
||||
from ..models import EnumTypeData, IntegerTypeData
|
||||
from .climate import CommonClimateType, TuyaClimateDefinition
|
||||
from .cover import CommonCoverType, TuyaCoverDefinition
|
||||
from .select import CommonSelectType, TuyaSelectDefinition
|
||||
from .sensor import CommonSensorType, TuyaSensorDefinition
|
||||
from .switch import CommonSwitchType, TuyaSwitchDefinition
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .registry import QuirksRegistry
|
||||
@@ -18,16 +25,20 @@ class TuyaDeviceQuirk:
|
||||
"""Quirk for Tuya device."""
|
||||
|
||||
_applies_to: list[tuple[str, str]]
|
||||
climate_definitions: list[TuyaClimateDefinition]
|
||||
cover_definitions: list[TuyaCoverDefinition]
|
||||
select_definitions: list[TuyaSelectDefinition]
|
||||
sensor_definitions: list[TuyaSensorDefinition]
|
||||
switch_definitions: list[TuyaSwitchDefinition]
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the quirk."""
|
||||
self._applies_to = []
|
||||
self.climate_definitions = []
|
||||
self.cover_definitions = []
|
||||
self.select_definitions = []
|
||||
self.sensor_definitions = []
|
||||
self.switch_definitions = []
|
||||
|
||||
current_frame = inspect.currentframe()
|
||||
if TYPE_CHECKING:
|
||||
@@ -48,15 +59,36 @@ class TuyaDeviceQuirk:
|
||||
for category, product_id in self._applies_to:
|
||||
registry.register(category, product_id, self)
|
||||
|
||||
def add_common_cover(
|
||||
def add_common_climate(
|
||||
self,
|
||||
*,
|
||||
key: str,
|
||||
common_type: CommonClimateType,
|
||||
current_temperature_dp_code: DPCode | None = None,
|
||||
set_temperature_dp_code: DPCode | None = None,
|
||||
switch_dp_code: DPCode | None = None,
|
||||
) -> Self:
|
||||
"""Add climate definition."""
|
||||
self.climate_definitions.append(
|
||||
TuyaClimateDefinition(
|
||||
key=key,
|
||||
common_type=common_type,
|
||||
switch_dp_code=switch_dp_code,
|
||||
current_temperature_dp_code=current_temperature_dp_code,
|
||||
set_temperature_dp_code=set_temperature_dp_code,
|
||||
)
|
||||
)
|
||||
return self
|
||||
|
||||
def add_common_cover(
|
||||
self,
|
||||
*,
|
||||
key: DPCode,
|
||||
common_type: CommonCoverType,
|
||||
current_position_dp_code: str | None = None,
|
||||
current_state_dp_code: str | None = None,
|
||||
set_position_dp_code: str | None = None,
|
||||
set_state_dp_code: str | None = None,
|
||||
current_position_dp_code: DPCode | None = None,
|
||||
current_state_dp_code: DPCode | None = None,
|
||||
set_position_dp_code: DPCode | None = None,
|
||||
set_state_dp_code: DPCode | None = None,
|
||||
) -> Self:
|
||||
"""Add cover definition."""
|
||||
self.cover_definitions.append(
|
||||
@@ -74,16 +106,14 @@ class TuyaDeviceQuirk:
|
||||
def add_common_select(
|
||||
self,
|
||||
*,
|
||||
key: str,
|
||||
key: DPCode,
|
||||
common_type: CommonSelectType,
|
||||
dp_code: str | None = None,
|
||||
) -> Self:
|
||||
"""Add select definition."""
|
||||
self.select_definitions.append(
|
||||
TuyaSelectDefinition(
|
||||
key=key,
|
||||
common_type=common_type,
|
||||
dp_code=dp_code or key,
|
||||
)
|
||||
)
|
||||
return self
|
||||
@@ -91,16 +121,34 @@ class TuyaDeviceQuirk:
|
||||
def add_common_sensor(
|
||||
self,
|
||||
*,
|
||||
key: str,
|
||||
key: DPCode,
|
||||
common_type: CommonSensorType,
|
||||
dp_code: str | None = None,
|
||||
state_conversion: Callable[
|
||||
[CustomerDevice, EnumTypeData | IntegerTypeData | None, Any], Any
|
||||
]
|
||||
| None = None,
|
||||
) -> Self:
|
||||
"""Add sensor definition."""
|
||||
self.sensor_definitions.append(
|
||||
TuyaSensorDefinition(
|
||||
key=key,
|
||||
common_type=common_type,
|
||||
dp_code=dp_code or key,
|
||||
state_conversion=state_conversion,
|
||||
)
|
||||
)
|
||||
return self
|
||||
|
||||
def add_common_switch(
|
||||
self,
|
||||
*,
|
||||
key: DPCode,
|
||||
common_type: CommonSwitchType,
|
||||
) -> Self:
|
||||
"""Add switch definition."""
|
||||
self.switch_definitions.append(
|
||||
TuyaSwitchDefinition(
|
||||
key=key,
|
||||
common_type=common_type,
|
||||
)
|
||||
)
|
||||
return self
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
"""Common cover quirks for Tuya devices."""
|
||||
"""Common select quirks for Tuya devices."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from ..const import DPCode
|
||||
|
||||
|
||||
class CommonSelectType(StrEnum):
|
||||
"""Common select types."""
|
||||
@@ -16,8 +18,6 @@ class CommonSelectType(StrEnum):
|
||||
class TuyaSelectDefinition:
|
||||
"""Definition for a select entity."""
|
||||
|
||||
key: str
|
||||
key: DPCode
|
||||
|
||||
common_type: CommonSelectType
|
||||
|
||||
dp_code: str
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
"""Common cover quirks for Tuya devices."""
|
||||
"""Common sensor quirks for Tuya devices."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
from typing import Any
|
||||
|
||||
from tuya_sharing import CustomerDevice
|
||||
|
||||
from ..const import DPCode
|
||||
from ..models import EnumTypeData, IntegerTypeData
|
||||
|
||||
|
||||
class CommonSensorType(StrEnum):
|
||||
"""Common sensor types."""
|
||||
|
||||
TEMPERATURE = "temperature"
|
||||
TIME_TOTAL = "time_total"
|
||||
|
||||
|
||||
@@ -16,8 +24,11 @@ class CommonSensorType(StrEnum):
|
||||
class TuyaSensorDefinition:
|
||||
"""Definition for a sensor entity."""
|
||||
|
||||
key: str
|
||||
key: DPCode
|
||||
|
||||
common_type: CommonSensorType
|
||||
|
||||
dp_code: str
|
||||
state_conversion: (
|
||||
Callable[[CustomerDevice, EnumTypeData | IntegerTypeData | None, Any], Any]
|
||||
| None
|
||||
) = None
|
||||
|
||||
23
homeassistant/components/tuya/xternal_tuya_quirks/switch.py
Normal file
23
homeassistant/components/tuya/xternal_tuya_quirks/switch.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""Common switch quirks for Tuya devices."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from ..const import DPCode
|
||||
|
||||
|
||||
class CommonSwitchType(StrEnum):
|
||||
"""Common switch types."""
|
||||
|
||||
CHILD_LOCK = "child_lock"
|
||||
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class TuyaSwitchDefinition:
|
||||
"""Definition for a switch entity."""
|
||||
|
||||
key: DPCode
|
||||
|
||||
common_type: CommonSwitchType
|
||||
18
homeassistant/components/tuya/xternal_tuya_quirks/utils.py
Normal file
18
homeassistant/components/tuya/xternal_tuya_quirks/utils.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""Common utility functions for Tuya quirks."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from ..models import IntegerTypeData
|
||||
|
||||
|
||||
def scale_value(value: float, step: float, scale: float) -> Any:
|
||||
"""Official scaling function from Tuya.
|
||||
|
||||
See https://support.tuya.com/en/help/_detail/Kadi66s463e2q
|
||||
"""
|
||||
return step * value / (10**scale)
|
||||
|
||||
|
||||
def scale_value_force_scale_1(dptype: IntegerTypeData, value: float) -> float:
|
||||
"""Some devices have incorrect scale, force scale=1."""
|
||||
return scale_value(value, dptype.step, 1)
|
||||
@@ -5857,6 +5857,62 @@
|
||||
'state': '219.72',
|
||||
})
|
||||
# ---
|
||||
# name: test_platform_setup_and_discovery[sensor.el_termostato_de_la_cocina_temperature-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.el_termostato_de_la_cocina_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Temperature',
|
||||
'platform': 'tuya',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'temperature',
|
||||
'unique_id': 'tuya.LmLMc0ht1KW2zYAIkwupper_temp',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_platform_setup_and_discovery[sensor.el_termostato_de_la_cocina_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'temperature',
|
||||
'friendly_name': 'El termostato de la cocina Temperature',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.el_termostato_de_la_cocina_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '27.5',
|
||||
})
|
||||
# ---
|
||||
# name: test_platform_setup_and_discovery[sensor.elivco_kitchen_socket_current-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
Reference in New Issue
Block a user