From a4357fdb957bcad2827597a440fab9f0dc31567e Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 12 Oct 2021 19:36:14 +0200 Subject: [PATCH] Replace all Tuya device property constants with an Enum (#57559) --- homeassistant/components/tuya/climate.py | 140 ++++++++++------------- homeassistant/components/tuya/const.py | 40 +++++++ homeassistant/components/tuya/fan.py | 73 +++++------- homeassistant/components/tuya/light.py | 56 ++++----- homeassistant/components/tuya/switch.py | 68 ++++------- 5 files changed, 171 insertions(+), 206 deletions(-) diff --git a/homeassistant/components/tuya/climate.py b/homeassistant/components/tuya/climate.py index ac309464054..fd1b48f865b 100644 --- a/homeassistant/components/tuya/climate.py +++ b/homeassistant/components/tuya/climate.py @@ -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 diff --git a/homeassistant/components/tuya/const.py b/homeassistant/components/tuya/const.py index 6d92383a871..359c1740c75 100644 --- a/homeassistant/components/tuya/const.py +++ b/homeassistant/components/tuya/const.py @@ -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.""" diff --git a/homeassistant/components/tuya/fan.py b/homeassistant/components/tuya/fan.py index 88aa1ab53b9..eedc9020374 100644 --- a/homeassistant/components/tuya/fan.py +++ b/homeassistant/components/tuya/fan.py @@ -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 diff --git a/homeassistant/components/tuya/light.py b/homeassistant/components/tuya/light.py index 1970ba4c312..40f1628f2a7 100644 --- a/homeassistant/components/tuya/light.py +++ b/homeassistant/components/tuya/light.py @@ -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]) diff --git a/homeassistant/components/tuya/switch.py b/homeassistant/components/tuya/switch.py index af723a3d4f4..663603d2727 100644 --- a/homeassistant/components/tuya/switch.py +++ b/homeassistant/components/tuya/switch.py @@ -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: