mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 01:46:11 -04:00
Move quirks to sub-folder
This commit is contained in:
@@ -23,6 +23,7 @@ from . import TuyaConfigEntry
|
||||
from .const import TUYA_DISCOVERY_NEW, DeviceCategory, DPCode, DPType
|
||||
from .entity import TuyaEntity
|
||||
from .models import EnumTypeData, IntegerTypeData
|
||||
from .quirks import TUYA_QUIRKS_REGISTRY, TuyaCoverDefinition, parse_enum
|
||||
from .util import get_dpcode
|
||||
|
||||
|
||||
@@ -164,6 +165,19 @@ def _apply_quirk(
|
||||
return description
|
||||
|
||||
|
||||
def _create_quirk_description(
|
||||
definition: TuyaCoverDefinition,
|
||||
) -> TuyaCoverEntityDescription:
|
||||
return TuyaCoverEntityDescription(
|
||||
key=DPCode(definition.key),
|
||||
translation_key=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),
|
||||
device_class=parse_enum(CoverDeviceClass, definition.device_class),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: TuyaConfigEntry,
|
||||
@@ -178,7 +192,18 @@ async def async_setup_entry(
|
||||
entities: list[TuyaCoverEntity] = []
|
||||
for device_id in device_ids:
|
||||
device = manager.device_map[device_id]
|
||||
if descriptions := COVERS.get(device.category):
|
||||
if quirk := TUYA_QUIRKS_REGISTRY.get_quirk_for_device(device):
|
||||
entities.extend(
|
||||
TuyaCoverEntity(
|
||||
device, manager, _create_quirk_description(definition)
|
||||
)
|
||||
for definition in quirk.cover_definitions
|
||||
if (
|
||||
definition.key in device.function
|
||||
or definition.key in device.status_range
|
||||
)
|
||||
)
|
||||
elif descriptions := COVERS.get(device.category):
|
||||
entities.extend(
|
||||
TuyaCoverEntity(device, manager, _apply_quirk(device, description))
|
||||
for description in descriptions
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Quirks for Tuya."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .device_quirk import DeviceQuirk, TuyaCoverDefinition, TuyaCoverDeviceClass
|
||||
from .homeassistant import parse_enum
|
||||
from .registry import QuirksRegistry
|
||||
|
||||
__all__ = [
|
||||
"QUIRKS_REGISTRY",
|
||||
"QuirksRegistry",
|
||||
"TuyaCoverDefinition",
|
||||
"TuyaCoverDeviceClass",
|
||||
"parse_enum",
|
||||
]
|
||||
|
||||
TUYA_QUIRKS_REGISTRY = QuirksRegistry()
|
||||
|
||||
(
|
||||
# This model has percent_control / percent_state / situation_set
|
||||
# but they never get updated - use control instead to get the state
|
||||
DeviceQuirk()
|
||||
.applies_to(category="cl", product_id="lfkr93x0ukp5gaia")
|
||||
.add_cover(
|
||||
key="control",
|
||||
translation_key="curtain",
|
||||
translation_string="curtain",
|
||||
current_state_dp_code="control",
|
||||
device_class=TuyaCoverDeviceClass.CURTAIN,
|
||||
)
|
||||
.register(TUYA_QUIRKS_REGISTRY)
|
||||
)
|
||||
@@ -0,0 +1,79 @@
|
||||
"""Quirks registry."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Self
|
||||
|
||||
from .homeassistant import TuyaCoverDeviceClass
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .registry import QuirksRegistry
|
||||
|
||||
|
||||
@dataclass
|
||||
class BaseTuyaDefinition:
|
||||
"""Definition for a Tuya device."""
|
||||
|
||||
key: str
|
||||
translation_key: str
|
||||
translation_string: str
|
||||
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class TuyaCoverDefinition(BaseTuyaDefinition):
|
||||
"""Definition for a cover device."""
|
||||
|
||||
device_class: TuyaCoverDeviceClass | None = None
|
||||
|
||||
current_state_dp_code: str | None = None
|
||||
current_position_dp_code: str | None = None
|
||||
set_position_dp_code: str | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class DeviceQuirk:
|
||||
"""Quirk for Tuya device."""
|
||||
|
||||
_applies_to: list[tuple[str, str]]
|
||||
cover_definitions: list[TuyaCoverDefinition]
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the quirk."""
|
||||
self._applies_to = []
|
||||
self.cover_definitions = []
|
||||
|
||||
def applies_to(self, *, category: str, product_id: str) -> Self:
|
||||
"""Set the device type the quirk applies to."""
|
||||
self._applies_to.append((category, product_id))
|
||||
return self
|
||||
|
||||
def register(self, registry: QuirksRegistry) -> None:
|
||||
"""Register the quirk in the registry."""
|
||||
for category, product_id in self._applies_to:
|
||||
registry.register(category, product_id, self)
|
||||
|
||||
def add_cover(
|
||||
self,
|
||||
*,
|
||||
key: str,
|
||||
translation_key: str,
|
||||
translation_string: str,
|
||||
device_class: TuyaCoverDeviceClass | None = None,
|
||||
current_state_dp_code: str | None = None,
|
||||
current_position_dp_code: str | None = None,
|
||||
set_position_dp_code: str | None = None,
|
||||
) -> Self:
|
||||
"""Add cover quirk."""
|
||||
self.cover_definitions.append(
|
||||
TuyaCoverDefinition(
|
||||
key=key,
|
||||
translation_key=translation_key,
|
||||
translation_string=translation_string,
|
||||
device_class=device_class,
|
||||
current_state_dp_code=current_state_dp_code,
|
||||
current_position_dp_code=current_position_dp_code,
|
||||
set_position_dp_code=set_position_dp_code,
|
||||
)
|
||||
)
|
||||
return self
|
||||
@@ -0,0 +1,31 @@
|
||||
"""Quirks registry."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
def parse_enum[T: StrEnum](enum_class: type[T], value: str | None) -> T | None:
|
||||
"""Parse a string to an enum member, or return None if value is None."""
|
||||
if value is None:
|
||||
return None
|
||||
try:
|
||||
return enum_class(value)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
class TuyaCoverDeviceClass(StrEnum):
|
||||
"""Device class for cover."""
|
||||
|
||||
# Keep synchronized with homeassistant
|
||||
AWNING = "awning"
|
||||
BLIND = "blind"
|
||||
CURTAIN = "curtain"
|
||||
DAMPER = "damper"
|
||||
DOOR = "door"
|
||||
GARAGE = "garage"
|
||||
GATE = "gate"
|
||||
SHADE = "shade"
|
||||
SHUTTER = "shutter"
|
||||
WINDOW = "window"
|
||||
@@ -0,0 +1,36 @@
|
||||
"""Quirks registry."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Self
|
||||
|
||||
from tuya_sharing import CustomerDevice
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .device_quirk import DeviceQuirk
|
||||
|
||||
|
||||
class QuirksRegistry:
|
||||
"""Registry for Tuya quirks."""
|
||||
|
||||
instance: Self
|
||||
|
||||
_quirks: dict[str, dict[str, DeviceQuirk]]
|
||||
|
||||
def __new__(cls) -> Self:
|
||||
"""Create a new class."""
|
||||
if not hasattr(cls, "instance"):
|
||||
cls.instance = super().__new__(cls)
|
||||
return cls.instance
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the registry."""
|
||||
self._quirks = {}
|
||||
|
||||
def register(self, category: str, product_id: str, quirk: DeviceQuirk) -> None:
|
||||
"""Register a quirk for a specific device type."""
|
||||
self._quirks.setdefault(category, {})[product_id] = quirk
|
||||
|
||||
def get_quirk_for_device(self, device: CustomerDevice) -> DeviceQuirk | None:
|
||||
"""Get the quirk for a specific device."""
|
||||
return self._quirks.get(device.category, {}).get(device.product_id)
|
||||
Reference in New Issue
Block a user