1
mirror of https://github.com/home-assistant/core synced 2024-09-06 10:29:55 +02:00

Replace all Tuya device property constants with an Enum (#57559)

This commit is contained in:
Franck Nijhof 2021-10-12 19:36:14 +02:00 committed by GitHub
parent c55e9136ee
commit a4357fdb95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 171 additions and 206 deletions

View File

@ -29,33 +29,10 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import HomeAssistantTuyaData
from .base import TuyaHaEntity
from .const import DOMAIN, TUYA_DISCOVERY_NEW
from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode
_LOGGER = logging.getLogger(__name__)
# Air Conditioner
# https://developer.tuya.com/en/docs/iot/f?id=K9gf46qujdmwb
DPCODE_SWITCH = "switch"
DPCODE_TEMP_SET = "temp_set"
DPCODE_TEMP_SET_F = "temp_set_f"
DPCODE_MODE = "mode"
DPCODE_HUMIDITY_SET = "humidity_set"
DPCODE_FAN_SPEED_ENUM = "fan_speed_enum"
# Temperature unit
DPCODE_TEMP_UNIT_CONVERT = "temp_unit_convert"
DPCODE_C_F = "c_f"
# swing flap switch
DPCODE_SWITCH_HORIZONTAL = "switch_horizontal"
DPCODE_SWITCH_VERTICAL = "switch_vertical"
# status
DPCODE_TEMP_CURRENT = "temp_current"
DPCODE_TEMP_CURRENT_F = "temp_current_f"
DPCODE_HUMIDITY_CURRENT = "humidity_current"
SWING_OFF = "swing_off"
SWING_VERTICAL = "swing_vertical"
SWING_HORIZONTAL = "swing_horizontal"
@ -72,6 +49,7 @@ TUYA_HVAC_TO_HA = {
"auto": HVAC_MODE_AUTO,
}
# https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
TUYA_SUPPORT_TYPE = {
"kt", # Air conditioner
"qn", # Heater
@ -108,14 +86,14 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
def __init__(self, device: TuyaDevice, device_manager: TuyaDeviceManager) -> None:
"""Init Tuya Ha Climate."""
super().__init__(device, device_manager)
if DPCODE_C_F in self.tuya_device.status:
self.dp_temp_unit = DPCODE_C_F
if DPCode.C_F in self.tuya_device.status:
self.dp_temp_unit = DPCode.C_F
else:
self.dp_temp_unit = DPCODE_TEMP_UNIT_CONVERT
self.dp_temp_unit = DPCode.TEMP_UNIT_CONVERT
def get_temp_set_scale(self) -> int | None:
"""Get temperature set scale."""
dp_temp_set = DPCODE_TEMP_SET if self.is_celsius() else DPCODE_TEMP_SET_F
dp_temp_set = DPCode.TEMP_SET if self.is_celsius() else DPCode.TEMP_SET_F
temp_set_value_range_item = self.tuya_device.status_range.get(dp_temp_set)
if not temp_set_value_range_item:
return None
@ -126,7 +104,7 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
def get_temp_current_scale(self) -> int | None:
"""Get temperature current scale."""
dp_temp_current = (
DPCODE_TEMP_CURRENT if self.is_celsius() else DPCODE_TEMP_CURRENT_F
DPCode.TEMP_CURRENT if self.is_celsius() else DPCode.TEMP_CURRENT_F
)
temp_current_value_range_item = self.tuya_device.status_range.get(
dp_temp_current
@ -143,46 +121,46 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
"""Set new target hvac mode."""
commands = []
if hvac_mode == HVAC_MODE_OFF:
commands.append({"code": DPCODE_SWITCH, "value": False})
commands.append({"code": DPCode.SWITCH, "value": False})
else:
commands.append({"code": DPCODE_SWITCH, "value": True})
commands.append({"code": DPCode.SWITCH, "value": True})
for tuya_mode, ha_mode in TUYA_HVAC_TO_HA.items():
if ha_mode == hvac_mode:
commands.append({"code": DPCODE_MODE, "value": tuya_mode})
commands.append({"code": DPCode.MODE, "value": tuya_mode})
break
self._send_command(commands)
def set_fan_mode(self, fan_mode: str) -> None:
"""Set new target fan mode."""
self._send_command([{"code": DPCODE_FAN_SPEED_ENUM, "value": fan_mode}])
self._send_command([{"code": DPCode.FAN_SPEED_ENUM, "value": fan_mode}])
def set_humidity(self, humidity: float) -> None:
"""Set new target humidity."""
self._send_command([{"code": DPCODE_HUMIDITY_SET, "value": int(humidity)}])
self._send_command([{"code": DPCode.HUMIDITY_SET, "value": int(humidity)}])
def set_swing_mode(self, swing_mode: str) -> None:
"""Set new target swing operation."""
if swing_mode == SWING_BOTH:
commands = [
{"code": DPCODE_SWITCH_VERTICAL, "value": True},
{"code": DPCODE_SWITCH_HORIZONTAL, "value": True},
{"code": DPCode.SWITCH_VERTICAL, "value": True},
{"code": DPCode.SWITCH_HORIZONTAL, "value": True},
]
elif swing_mode == SWING_HORIZONTAL:
commands = [
{"code": DPCODE_SWITCH_VERTICAL, "value": False},
{"code": DPCODE_SWITCH_HORIZONTAL, "value": True},
{"code": DPCode.SWITCH_VERTICAL, "value": False},
{"code": DPCode.SWITCH_HORIZONTAL, "value": True},
]
elif swing_mode == SWING_VERTICAL:
commands = [
{"code": DPCODE_SWITCH_VERTICAL, "value": True},
{"code": DPCODE_SWITCH_HORIZONTAL, "value": False},
{"code": DPCode.SWITCH_VERTICAL, "value": True},
{"code": DPCode.SWITCH_HORIZONTAL, "value": False},
]
else:
commands = [
{"code": DPCODE_SWITCH_VERTICAL, "value": False},
{"code": DPCODE_SWITCH_HORIZONTAL, "value": False},
{"code": DPCode.SWITCH_VERTICAL, "value": False},
{"code": DPCode.SWITCH_HORIZONTAL, "value": False},
]
self._send_command(commands)
@ -190,7 +168,7 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
def set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
_LOGGER.debug("climate temp-> %s", kwargs)
code = DPCODE_TEMP_SET if self.is_celsius() else DPCODE_TEMP_SET_F
code = DPCode.TEMP_SET if self.is_celsius() else DPCode.TEMP_SET_F
temp_set_scale = self.get_temp_set_scale()
if not temp_set_scale:
return
@ -212,8 +190,8 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
):
return True
if (
DPCODE_TEMP_SET in self.tuya_device.status
or DPCODE_TEMP_CURRENT in self.tuya_device.status
DPCode.TEMP_SET in self.tuya_device.status
or DPCode.TEMP_CURRENT in self.tuya_device.status
):
return True
return False
@ -229,8 +207,8 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
def current_temperature(self) -> float | None:
"""Return the current temperature."""
if (
DPCODE_TEMP_CURRENT not in self.tuya_device.status
and DPCODE_TEMP_CURRENT_F not in self.tuya_device.status
DPCode.TEMP_CURRENT not in self.tuya_device.status
and DPCode.TEMP_CURRENT_F not in self.tuya_device.status
):
return None
@ -239,12 +217,12 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
return None
if self.is_celsius():
temperature = self.tuya_device.status.get(DPCODE_TEMP_CURRENT)
temperature = self.tuya_device.status.get(DPCode.TEMP_CURRENT)
if not temperature:
return None
return temperature * 1.0 / (10 ** temp_current_scale)
temperature = self.tuya_device.status.get(DPCODE_TEMP_CURRENT_F)
temperature = self.tuya_device.status.get(DPCode.TEMP_CURRENT_F)
if not temperature:
return None
return temperature * 1.0 / (10 ** temp_current_scale)
@ -252,7 +230,7 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
@property
def current_humidity(self) -> int:
"""Return the current humidity."""
return int(self.tuya_device.status.get(DPCODE_HUMIDITY_CURRENT, 0))
return int(self.tuya_device.status.get(DPCode.HUMIDITY_CURRENT, 0))
@property
def target_temperature(self) -> float | None:
@ -261,7 +239,7 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
if temp_set_scale is None:
return None
dpcode_temp_set = self.tuya_device.status.get(DPCODE_TEMP_SET)
dpcode_temp_set = self.tuya_device.status.get(DPCode.TEMP_SET)
if dpcode_temp_set is None:
return None
@ -275,10 +253,10 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
return DEFAULT_MAX_TEMP
if self.is_celsius():
if DPCODE_TEMP_SET not in self.tuya_device.function:
if DPCode.TEMP_SET not in self.tuya_device.function:
return DEFAULT_MAX_TEMP
function_item = self.tuya_device.function.get(DPCODE_TEMP_SET)
function_item = self.tuya_device.function.get(DPCode.TEMP_SET)
if function_item is None:
return DEFAULT_MAX_TEMP
@ -288,10 +266,10 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
if temp_max is None:
return DEFAULT_MAX_TEMP
return temp_max * 1.0 / (10 ** scale)
if DPCODE_TEMP_SET_F not in self.tuya_device.function:
if DPCode.TEMP_SET_F not in self.tuya_device.function:
return DEFAULT_MAX_TEMP
function_item_f = self.tuya_device.function.get(DPCODE_TEMP_SET_F)
function_item_f = self.tuya_device.function.get(DPCode.TEMP_SET_F)
if function_item_f is None:
return DEFAULT_MAX_TEMP
@ -310,10 +288,10 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
return DEFAULT_MIN_TEMP
if self.is_celsius():
if DPCODE_TEMP_SET not in self.tuya_device.function:
if DPCode.TEMP_SET not in self.tuya_device.function:
return DEFAULT_MIN_TEMP
function_temp_item = self.tuya_device.function.get(DPCODE_TEMP_SET)
function_temp_item = self.tuya_device.function.get(DPCode.TEMP_SET)
if function_temp_item is None:
return DEFAULT_MIN_TEMP
temp_value = json.loads(function_temp_item.values)
@ -322,10 +300,10 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
return DEFAULT_MIN_TEMP
return temp_min * 1.0 / (10 ** temp_set_scal)
if DPCODE_TEMP_SET_F not in self.tuya_device.function:
if DPCode.TEMP_SET_F not in self.tuya_device.function:
return DEFAULT_MIN_TEMP
temp_value_temp_f = self.tuya_device.function.get(DPCODE_TEMP_SET_F)
temp_value_temp_f = self.tuya_device.function.get(DPCode.TEMP_SET_F)
if temp_value_temp_f is None:
return DEFAULT_MIN_TEMP
temp_value_f = json.loads(temp_value_temp_f.values)
@ -340,13 +318,13 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
def target_temperature_step(self) -> float | None:
"""Return target temperature setp."""
if (
DPCODE_TEMP_SET not in self.tuya_device.status_range
and DPCODE_TEMP_SET_F not in self.tuya_device.status_range
DPCode.TEMP_SET not in self.tuya_device.status_range
and DPCode.TEMP_SET_F not in self.tuya_device.status_range
):
return 1.0
temp_set_value_range = json.loads(
self.tuya_device.status_range.get(
DPCODE_TEMP_SET if self.is_celsius() else DPCODE_TEMP_SET_F
DPCode.TEMP_SET if self.is_celsius() else DPCode.TEMP_SET_F
).values
)
step = temp_set_value_range.get("step")
@ -362,25 +340,25 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
@property
def target_humidity(self) -> int:
"""Return target humidity."""
return int(self.tuya_device.status.get(DPCODE_HUMIDITY_SET, 0))
return int(self.tuya_device.status.get(DPCode.HUMIDITY_SET, 0))
@property
def hvac_mode(self) -> str:
"""Return hvac mode."""
if not self.tuya_device.status.get(DPCODE_SWITCH, False):
if not self.tuya_device.status.get(DPCode.SWITCH, False):
return HVAC_MODE_OFF
if DPCODE_MODE not in self.tuya_device.status:
if DPCode.MODE not in self.tuya_device.status:
return HVAC_MODE_OFF
if self.tuya_device.status.get(DPCODE_MODE) is not None:
return TUYA_HVAC_TO_HA[self.tuya_device.status[DPCODE_MODE]]
if self.tuya_device.status.get(DPCode.MODE) is not None:
return TUYA_HVAC_TO_HA[self.tuya_device.status[DPCode.MODE]]
return HVAC_MODE_OFF
@property
def hvac_modes(self) -> list[str]:
"""Return hvac modes for select."""
if DPCODE_MODE not in self.tuya_device.function:
if DPCode.MODE not in self.tuya_device.function:
return []
modes = json.loads(self.tuya_device.function.get(DPCODE_MODE, {}).values).get(
modes = json.loads(self.tuya_device.function.get(DPCode.MODE, {}).values).get(
"range"
)
@ -394,12 +372,12 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
@property
def fan_mode(self) -> str | None:
"""Return fan mode."""
return self.tuya_device.status.get(DPCODE_FAN_SPEED_ENUM)
return self.tuya_device.status.get(DPCode.FAN_SPEED_ENUM)
@property
def fan_modes(self) -> list[str]:
"""Return fan modes for select."""
fan_speed_device_function = self.tuya_device.function.get(DPCODE_FAN_SPEED_ENUM)
fan_speed_device_function = self.tuya_device.function.get(DPCode.FAN_SPEED_ENUM)
if not fan_speed_device_function:
return []
return json.loads(fan_speed_device_function.values).get("range", [])
@ -409,13 +387,13 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
"""Return swing mode."""
mode = 0
if (
DPCODE_SWITCH_HORIZONTAL in self.tuya_device.status
and self.tuya_device.status.get(DPCODE_SWITCH_HORIZONTAL)
DPCode.SWITCH_HORIZONTAL in self.tuya_device.status
and self.tuya_device.status.get(DPCode.SWITCH_HORIZONTAL)
):
mode += 1
if (
DPCODE_SWITCH_VERTICAL in self.tuya_device.status
and self.tuya_device.status.get(DPCODE_SWITCH_VERTICAL)
DPCode.SWITCH_VERTICAL in self.tuya_device.status
and self.tuya_device.status.get(DPCode.SWITCH_VERTICAL)
):
mode += 2
@ -437,17 +415,17 @@ class TuyaHaClimate(TuyaHaEntity, ClimateEntity):
"""Flag supported features."""
supports = 0
if (
DPCODE_TEMP_SET in self.tuya_device.status
or DPCODE_TEMP_SET_F in self.tuya_device.status
DPCode.TEMP_SET in self.tuya_device.status
or DPCode.TEMP_SET_F in self.tuya_device.status
):
supports |= SUPPORT_TARGET_TEMPERATURE
if DPCODE_FAN_SPEED_ENUM in self.tuya_device.status:
if DPCode.FAN_SPEED_ENUM in self.tuya_device.status:
supports |= SUPPORT_FAN_MODE
if DPCODE_HUMIDITY_SET in self.tuya_device.status:
if DPCode.HUMIDITY_SET in self.tuya_device.status:
supports |= SUPPORT_TARGET_HUMIDITY
if (
DPCODE_SWITCH_HORIZONTAL in self.tuya_device.status
or DPCODE_SWITCH_VERTICAL in self.tuya_device.status
DPCode.SWITCH_HORIZONTAL in self.tuya_device.status
or DPCode.SWITCH_VERTICAL in self.tuya_device.status
):
supports |= SUPPORT_SWING_MODE
return supports

View File

@ -1,5 +1,6 @@
"""Constants for the Tuya integration."""
from dataclasses import dataclass
from enum import Enum
from tuya_iot import TuyaCloudOpenAPIEndpoint
@ -54,6 +55,45 @@ SMARTLIFE_APP = "smartlife"
PLATFORMS = ["climate", "fan", "light", "scene", "switch"]
class DPCode(str, Enum):
"""Device Property Codes used by Tuya.
https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
"""
ANION = "anion" # Ionizer unit
BRIGHT_VALUE = "bright_value" # Brightness
C_F = "c_f" # Temperature unit switching
COLOUR_DATA = "colour_data" # Colored light mode
COLOUR_DATA_V2 = "colour_data_v2" # Colored light mode
FAN_DIRECTION = "fan_direction" # Fan direction
FAN_SPEED_ENUM = "fan_speed_enum" # Speed mode
FAN_SPEED_PERCENT = "fan_speed_percent" # Stepless speed
FILTER_RESET = "filter_reset" # Filter (cartridge) reset
HUMIDITY_CURRENT = "humidity_current" # Current humidity
HUMIDITY_SET = "humidity_set" # Humidity setting
LIGHT = "light" # Light
LOCK = "lock" # Lock / Child lock
MODE = "mode" # Working mode / Mode
PUMP_RESET = "pump_reset" # Water pump reset
SPEED = "speed" # Speed level
START = "start" # Start
SWITCH = "switch" # Switch
SWITCH_HORIZONTAL = "switch_horizontal" # Horizontal swing flap switch
SWITCH_LED = "switch_led" # Switch
SWITCH_VERTICAL = "switch_vertical" # Vertical swing flap switch
TEMP_CURRENT = "temp_current" # Current temperature in °C
TEMP_CURRENT_F = "temp_current_f" # Current temperature in °F
TEMP_SET = "temp_set" # Set the temperature in °C
TEMP_SET_F = "temp_set_f" # Set the temperature in °F
TEMP_UNIT_CONVERT = "temp_unit_convert" # Temperature unit switching
TEMP_VALUE = "temp_value" # Color temperature
UV = "uv" # UV sterilization
WATER_RESET = "water_reset" # Resetting of water usage days
WET = "wet" # Humidification
WORK_MODE = "work_mode" # Working mode
@dataclass
class Country:
"""Describe a supported country."""

View File

@ -2,7 +2,6 @@
from __future__ import annotations
import json
import logging
from typing import Any
from tuya_iot import TuyaDevice, TuyaDeviceManager
@ -27,23 +26,7 @@ from homeassistant.util.percentage import (
from . import HomeAssistantTuyaData
from .base import TuyaHaEntity
from .const import DOMAIN, TUYA_DISCOVERY_NEW
_LOGGER = logging.getLogger(__name__)
# Fan
# https://developer.tuya.com/en/docs/iot/f?id=K9gf45vs7vkge
DPCODE_SWITCH = "switch"
DPCODE_FAN_SPEED = "fan_speed_percent"
DPCODE_MODE = "mode"
DPCODE_SWITCH_HORIZONTAL = "switch_horizontal"
DPCODE_FAN_DIRECTION = "fan_direction"
# Air Purifier
# https://developer.tuya.com/en/docs/iot/s?id=K9gf48r41mn81
DPCODE_AP_FAN_SPEED = "speed"
DPCODE_AP_FAN_SPEED_ENUM = "fan_speed_enum"
from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode
TUYA_SUPPORT_TYPE = {
"fs", # Fan
@ -82,9 +65,9 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
super().__init__(device, device_manager)
self.ha_preset_modes = []
if DPCODE_MODE in self.tuya_device.function:
if DPCode.MODE in self.tuya_device.function:
self.ha_preset_modes = json.loads(
self.tuya_device.function[DPCODE_MODE].values
self.tuya_device.function[DPCode.MODE].values
).get("range", [])
# Air purifier fan can be controlled either via the ranged values or via the enum.
@ -94,13 +77,13 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
self.air_purifier_speed_range_len = 0
self.air_purifier_speed_range_enum = []
if self.tuya_device.category == "kj" and (
DPCODE_AP_FAN_SPEED_ENUM in self.tuya_device.function
or DPCODE_AP_FAN_SPEED in self.tuya_device.function
DPCode.FAN_SPEED_ENUM in self.tuya_device.function
or DPCode.SPEED in self.tuya_device.function
):
if DPCODE_AP_FAN_SPEED_ENUM in self.tuya_device.function:
self.dp_code_speed_enum = DPCODE_AP_FAN_SPEED_ENUM
if DPCode.FAN_SPEED_ENUM in self.tuya_device.function:
self.dp_code_speed_enum = DPCode.FAN_SPEED_ENUM
else:
self.dp_code_speed_enum = DPCODE_AP_FAN_SPEED
self.dp_code_speed_enum = DPCode.SPEED
data = json.loads(
self.tuya_device.function[self.dp_code_speed_enum].values
@ -111,11 +94,11 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
def set_preset_mode(self, preset_mode: str) -> None:
"""Set the preset mode of the fan."""
self._send_command([{"code": DPCODE_MODE, "value": preset_mode}])
self._send_command([{"code": DPCode.MODE, "value": preset_mode}])
def set_direction(self, direction: str) -> None:
"""Set the direction of the fan."""
self._send_command([{"code": DPCODE_FAN_DIRECTION, "value": direction}])
self._send_command([{"code": DPCode.FAN_DIRECTION, "value": direction}])
def set_percentage(self, percentage: int) -> None:
"""Set the speed of the fan, as a percentage."""
@ -132,11 +115,13 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
]
)
else:
self._send_command([{"code": DPCODE_FAN_SPEED, "value": percentage}])
self._send_command(
[{"code": DPCode.FAN_SPEED_PERCENT, "value": percentage}]
)
def turn_off(self, **kwargs: Any) -> None:
"""Turn the fan off."""
self._send_command([{"code": DPCODE_SWITCH, "value": False}])
self._send_command([{"code": DPCode.SWITCH, "value": False}])
def turn_on(
self,
@ -146,28 +131,28 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
**kwargs: Any,
) -> None:
"""Turn on the fan."""
self._send_command([{"code": DPCODE_SWITCH, "value": True}])
self._send_command([{"code": DPCode.SWITCH, "value": True}])
def oscillate(self, oscillating: bool) -> None:
"""Oscillate the fan."""
self._send_command([{"code": DPCODE_SWITCH_HORIZONTAL, "value": oscillating}])
self._send_command([{"code": DPCode.SWITCH_HORIZONTAL, "value": oscillating}])
@property
def is_on(self) -> bool:
"""Return true if fan is on."""
return self.tuya_device.status.get(DPCODE_SWITCH, False)
return self.tuya_device.status.get(DPCode.SWITCH, False)
@property
def current_direction(self) -> str:
"""Return the current direction of the fan."""
if self.tuya_device.status[DPCODE_FAN_DIRECTION]:
if self.tuya_device.status[DPCode.FAN_DIRECTION]:
return DIRECTION_FORWARD
return DIRECTION_REVERSE
@property
def oscillating(self) -> bool:
"""Return true if the fan is oscillating."""
return self.tuya_device.status.get(DPCODE_SWITCH_HORIZONTAL, False)
return self.tuya_device.status.get(DPCode.SWITCH_HORIZONTAL, False)
@property
def preset_modes(self) -> list[str]:
@ -177,7 +162,7 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
@property
def preset_mode(self) -> str:
"""Return the current preset_mode."""
return self.tuya_device.status[DPCODE_MODE]
return self.tuya_device.status[DPCode.MODE]
@property
def percentage(self) -> int | None:
@ -189,16 +174,16 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
self.tuya_device.category == "kj"
and self.air_purifier_speed_range_len > 1
and not self.air_purifier_speed_range_enum
and DPCODE_AP_FAN_SPEED_ENUM in self.tuya_device.status
and DPCode.FAN_SPEED_ENUM in self.tuya_device.status
):
# if air-purifier speed enumeration is supported we will prefer it.
return ordered_list_item_to_percentage(
self.air_purifier_speed_range_enum,
self.tuya_device.status[DPCODE_AP_FAN_SPEED_ENUM],
self.tuya_device.status[DPCode.FAN_SPEED_ENUM],
)
# some type may not have the fan_speed_percent key
return self.tuya_device.status.get(DPCODE_FAN_SPEED)
return self.tuya_device.status.get(DPCode.FAN_SPEED_PERCENT)
@property
def speed_count(self) -> int:
@ -211,19 +196,19 @@ class TuyaHaFan(TuyaHaEntity, FanEntity):
def supported_features(self):
"""Flag supported features."""
supports = 0
if DPCODE_MODE in self.tuya_device.status:
if DPCode.MODE in self.tuya_device.status:
supports |= SUPPORT_PRESET_MODE
if DPCODE_FAN_SPEED in self.tuya_device.status:
if DPCode.FAN_SPEED_PERCENT in self.tuya_device.status:
supports |= SUPPORT_SET_SPEED
if DPCODE_SWITCH_HORIZONTAL in self.tuya_device.status:
if DPCode.SWITCH_HORIZONTAL in self.tuya_device.status:
supports |= SUPPORT_OSCILLATE
if DPCODE_FAN_DIRECTION in self.tuya_device.status:
if DPCode.FAN_DIRECTION in self.tuya_device.status:
supports |= SUPPORT_DIRECTION
# Air Purifier specific
if (
DPCODE_AP_FAN_SPEED in self.tuya_device.status
or DPCODE_AP_FAN_SPEED_ENUM in self.tuya_device.status
DPCode.SPEED in self.tuya_device.status
or DPCode.FAN_SPEED_ENUM in self.tuya_device.status
):
supports |= SUPPORT_SET_SPEED
return supports

View File

@ -24,21 +24,10 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import HomeAssistantTuyaData
from .base import TuyaHaEntity
from .const import DOMAIN, TUYA_DISCOVERY_NEW
from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode
_LOGGER = logging.getLogger(__name__)
# Light(dj)
# https://developer.tuya.com/en/docs/iot/f?id=K9i5ql3v98hn3
DPCODE_SWITCH = "switch_led"
DPCODE_WORK_MODE = "work_mode"
DPCODE_BRIGHT_VALUE = "bright_value"
DPCODE_TEMP_VALUE = "temp_value"
DPCODE_COLOUR_DATA = "colour_data"
DPCODE_COLOUR_DATA_V2 = "colour_data_v2"
DPCODE_LIGHT = "light"
MIREDS_MAX = 500
MIREDS_MIN = 153
@ -50,6 +39,7 @@ HSV_HA_SATURATION_MAX = 100
WORK_MODE_WHITE = "white"
WORK_MODE_COLOUR = "colour"
# https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
TUYA_SUPPORT_TYPE = {
"dj", # Light
"dd", # Light strip
@ -102,16 +92,16 @@ class TuyaHaLight(TuyaHaEntity, LightEntity):
def __init__(self, device: TuyaDevice, device_manager: TuyaDeviceManager) -> None:
"""Init TuyaHaLight."""
self.dp_code_bright = DPCODE_BRIGHT_VALUE
self.dp_code_temp = DPCODE_TEMP_VALUE
self.dp_code_colour = DPCODE_COLOUR_DATA
self.dp_code_bright = DPCode.BRIGHT_VALUE
self.dp_code_temp = DPCode.TEMP_VALUE
self.dp_code_colour = DPCode.COLOUR_DATA
for key in device.function:
if key.startswith(DPCODE_BRIGHT_VALUE):
if key.startswith(DPCode.BRIGHT_VALUE):
self.dp_code_bright = key
elif key.startswith(DPCODE_TEMP_VALUE):
elif key.startswith(DPCode.TEMP_VALUE):
self.dp_code_temp = key
elif key.startswith(DPCODE_COLOUR_DATA):
elif key.startswith(DPCode.COLOUR_DATA):
self.dp_code_colour = key
super().__init__(device, device_manager)
@ -119,7 +109,7 @@ class TuyaHaLight(TuyaHaEntity, LightEntity):
@property
def is_on(self) -> bool:
"""Return true if light is on."""
return self.tuya_device.status.get(DPCODE_SWITCH, False)
return self.tuya_device.status.get(DPCode.SWITCH_LED, False)
def turn_on(self, **kwargs: Any) -> None:
"""Turn on or control the light."""
@ -127,12 +117,12 @@ class TuyaHaLight(TuyaHaEntity, LightEntity):
_LOGGER.debug("light kwargs-> %s", kwargs)
if (
DPCODE_LIGHT in self.tuya_device.status
and DPCODE_SWITCH not in self.tuya_device.status
DPCode.LIGHT in self.tuya_device.status
and DPCode.SWITCH_LED not in self.tuya_device.status
):
commands += [{"code": DPCODE_LIGHT, "value": True}]
commands += [{"code": DPCode.LIGHT, "value": True}]
else:
commands += [{"code": DPCODE_SWITCH, "value": True}]
commands += [{"code": DPCode.SWITCH_LED, "value": True}]
if ATTR_BRIGHTNESS in kwargs:
if self._work_mode().startswith(WORK_MODE_COLOUR):
@ -177,8 +167,8 @@ class TuyaHaLight(TuyaHaEntity, LightEntity):
commands += [
{"code": self.dp_code_colour, "value": json.dumps(colour_data)}
]
if self.tuya_device.status[DPCODE_WORK_MODE] != "colour":
commands += [{"code": DPCODE_WORK_MODE, "value": "colour"}]
if self.tuya_device.status[DPCode.WORK_MODE] != "colour":
commands += [{"code": DPCode.WORK_MODE, "value": "colour"}]
if ATTR_COLOR_TEMP in kwargs:
# temp color
@ -200,20 +190,20 @@ class TuyaHaLight(TuyaHaEntity, LightEntity):
)
commands += [{"code": self.dp_code_bright, "value": int(tuya_brightness)}]
if self.tuya_device.status[DPCODE_WORK_MODE] != "white":
commands += [{"code": DPCODE_WORK_MODE, "value": "white"}]
if self.tuya_device.status[DPCode.WORK_MODE] != "white":
commands += [{"code": DPCode.WORK_MODE, "value": "white"}]
self._send_command(commands)
def turn_off(self, **kwargs: Any) -> None:
"""Instruct the light to turn off."""
if (
DPCODE_LIGHT in self.tuya_device.status
and DPCODE_SWITCH not in self.tuya_device.status
DPCode.LIGHT in self.tuya_device.status
and DPCode.SWITCH_LED not in self.tuya_device.status
):
commands = [{"code": DPCODE_LIGHT, "value": False}]
commands = [{"code": DPCode.LIGHT, "value": False}]
else:
commands = [{"code": DPCODE_SWITCH, "value": False}]
commands = [{"code": DPCode.SWITCH_LED, "value": False}]
self._send_command(commands)
@property
@ -319,7 +309,7 @@ class TuyaHaLight(TuyaHaEntity, LightEntity):
return None
colour_data = json.loads(colour_json)
if (
self.dp_code_colour == DPCODE_COLOUR_DATA_V2
self.dp_code_colour == DPCode.COLOUR_DATA_V2
or colour_data.get("v", 0) > 255
or colour_data.get("s", 0) > 255
):
@ -327,7 +317,7 @@ class TuyaHaLight(TuyaHaEntity, LightEntity):
return DEFAULT_HSV
def _work_mode(self) -> str:
return self.tuya_device.status.get(DPCODE_WORK_MODE, "")
return self.tuya_device.status.get(DPCode.WORK_MODE, "")
def _get_hsv(self) -> dict[str, int]:
return json.loads(self.tuya_device.status[self.dp_code_colour])

View File

@ -1,7 +1,6 @@
"""Support for Tuya switches."""
from __future__ import annotations
import logging
from typing import Any
from tuya_iot import TuyaDevice, TuyaDeviceManager
@ -14,10 +13,9 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import HomeAssistantTuyaData
from .base import TuyaHaEntity
from .const import DOMAIN, TUYA_DISCOVERY_NEW
_LOGGER = logging.getLogger(__name__)
from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode
# https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
TUYA_SUPPORT_TYPE = {
"kg", # Switch
"cz", # Socket
@ -29,28 +27,6 @@ TUYA_SUPPORT_TYPE = {
"xxj", # Diffuser
}
# Switch(kg), Socket(cz), Power Strip(pc)
# https://developer.tuya.com/en/docs/iot/categorykgczpc?id=Kaiuz08zj1l4y
DPCODE_SWITCH = "switch"
# Air Purifier
# https://developer.tuya.com/en/docs/iot/categorykj?id=Kaiuz1atqo5l7
# Pet Water Feeder
# https://developer.tuya.com/en/docs/iot/f?id=K9gf46aewxem5
DPCODE_ANION = "anion" # Air Purifier - Ionizer unit
# Air Purifier - Filter cartridge resetting; Pet Water Feeder - Filter cartridge resetting
DPCODE_FRESET = "filter_reset"
DPCODE_LIGHT = "light" # Air Purifier - Light
DPCODE_LOCK = "lock" # Air Purifier - Child lock
# Air Purifier - UV sterilization; Pet Water Feeder - UV sterilization
DPCODE_UV = "uv"
DPCODE_WET = "wet" # Air Purifier - Humidification unit
DPCODE_PRESET = "pump_reset" # Pet Water Feeder - Water pump resetting
DPCODE_WRESET = "water_reset" # Pet Water Feeder - Resetting of water usage days
DPCODE_START = "start"
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
@ -88,12 +64,12 @@ def _setup_entities(
for function in device.function:
if device.category == "kj":
if function in [
DPCODE_ANION,
DPCODE_FRESET,
DPCODE_LIGHT,
DPCODE_LOCK,
DPCODE_UV,
DPCODE_WET,
DPCode.ANION,
DPCode.FILTER_RESET,
DPCode.LIGHT,
DPCode.LOCK,
DPCode.UV,
DPCode.WET,
]:
entities.append(TuyaHaSwitch(device, device_manager, function))
@ -101,17 +77,17 @@ def _setup_entities(
if (
function
in [
DPCODE_FRESET,
DPCODE_UV,
DPCODE_PRESET,
DPCODE_WRESET,
DPCode.FILTER_RESET,
DPCode.UV,
DPCode.PUMP_RESET,
DPCode.WATER_RESET,
]
or function.startswith(DPCODE_SWITCH)
or function.startswith(DPCode.SWITCH)
):
entities.append(TuyaHaSwitch(device, device_manager, function))
elif function.startswith(DPCODE_START) or function.startswith(
DPCODE_SWITCH
elif function.startswith(DPCode.START) or function.startswith(
DPCode.SWITCH
):
entities.append(TuyaHaSwitch(device, device_manager, function))
@ -121,8 +97,8 @@ def _setup_entities(
class TuyaHaSwitch(TuyaHaEntity, SwitchEntity):
"""Tuya Switch Device."""
dp_code_switch = DPCODE_SWITCH
dp_code_start = DPCODE_START
dp_code_switch = DPCode.SWITCH
dp_code_start = DPCode.START
def __init__(
self, device: TuyaDevice, device_manager: TuyaDeviceManager, dp_code: str = ""
@ -132,15 +108,11 @@ class TuyaHaSwitch(TuyaHaEntity, SwitchEntity):
self.dp_code = dp_code
self.channel = (
dp_code.replace(DPCODE_SWITCH, "")
if dp_code.startswith(DPCODE_SWITCH)
dp_code.replace(DPCode.SWITCH, "")
if dp_code.startswith(DPCode.SWITCH)
else dp_code
)
@property
def unique_id(self) -> str | None:
"""Return a unique ID."""
return f"{super().unique_id}{self.channel}"
self._attr_unique_id = f"{super().unique_id}{self.channel}"
@property
def name(self) -> str | None: