diff --git a/custom_components/localtuya/const.py b/custom_components/localtuya/const.py index 3c505b3fd..d83fd4bb1 100644 --- a/custom_components/localtuya/const.py +++ b/custom_components/localtuya/const.py @@ -145,6 +145,7 @@ CONF_PAUSED_STATE = "paused_state" CONF_RETURN_MODE = "return_mode" CONF_STOP_STATUS = "stop_status" +CONF_PAUSE_DP = "pause_dp" # number CONF_MIN_VALUE = "min_value" diff --git a/custom_components/localtuya/core/ha_entities/base.py b/custom_components/localtuya/core/ha_entities/base.py index 6fcb407fc..e9fb3191b 100644 --- a/custom_components/localtuya/core/ha_entities/base.py +++ b/custom_components/localtuya/core/ha_entities/base.py @@ -140,6 +140,7 @@ class DPCode(StrEnum): BATTERY_PERCENTAGE = "battery_percentage" # Battery percentage BATTERY_STATE = "battery_state" # Battery state BATTERY_VALUE = "battery_value" # Battery value + BREAK_CLEAN = "break_clean" BRIGHTNESS_MAX_1 = "brightness_max_1" BRIGHTNESS_MAX_2 = "brightness_max_2" BRIGHTNESS_MAX_3 = "brightness_max_3" @@ -227,6 +228,7 @@ class DPCode(StrEnum): DELAY_SET = "delay_set" DEVICE_STATE1 = "device_state1" DEVICE_STATE2 = "device_state2" + DIRECTION_CONTROL = "direction_control" DISINFECTION = "disinfection" DOORBELL = "doorbell" DOORCONTACT_STATE = "doorcontact_state" # Status of door window sensor @@ -586,6 +588,7 @@ class DPCode(StrEnum): VOC_STATE = "voc_state" VOC_VALUE = "voc_value" VOICE_BT_PLAY = "voice_bt_play" + VOICE_LANGUAGE = "voice_language" VOICE_MIC = "voice_mic" VOICE_PLAY = "voice_play" VOICE_SWITCH = "voice_switch" @@ -615,5 +618,6 @@ class DPCode(StrEnum): WORK_POWER = "work_power" WORK_STATE = "work_state" WORK_STATUS = "work_status" + Y_MOP = "y_mop" ZONE_ATTRIBUTE = "zone_attribute" ZONE_NUMBER = "zone_number" diff --git a/custom_components/localtuya/core/ha_entities/binary_sensors.py b/custom_components/localtuya/core/ha_entities/binary_sensors.py index d43d76ba7..5fc5e2965 100644 --- a/custom_components/localtuya/core/ha_entities/binary_sensors.py +++ b/custom_components/localtuya/core/ha_entities/binary_sensors.py @@ -420,3 +420,4 @@ def localtuya_binarySensor(state_on="1"): BINARY_SENSORS["cs"] = FAULT_SENSOR BINARY_SENSORS["jsq"] = FAULT_SENSOR BINARY_SENSORS["kt"] = FAULT_SENSOR +BINARY_SENSORS["sd"] = FAULT_SENSOR diff --git a/custom_components/localtuya/core/ha_entities/selects.py b/custom_components/localtuya/core/ha_entities/selects.py index 806631010..5c31b7126 100644 --- a/custom_components/localtuya/core/ha_entities/selects.py +++ b/custom_components/localtuya/core/ha_entities/selects.py @@ -158,27 +158,51 @@ def localtuya_selector(options): id=DPCode.CUP_NUMBER, name="Cups", icon="mdi:numeric", - custom_configs=localtuya_selector("1,2,3,4,5,6,7,8,9,10,11,12"), + custom_configs=localtuya_selector( + { + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9", + "10": "10", + "11": "11", + "12": "12", + } + ), ), LocalTuyaEntity( id=DPCode.CONCENTRATION_SET, name="Concentration", icon="mdi:altimeter", entity_category=EntityCategory.CONFIG, - custom_configs=localtuya_selector("regular,middle,bold"), + custom_configs=localtuya_selector( + {"regular": "REGULAR", "middle": "MIDDLE", "bold": "BOLD"} + ), ), LocalTuyaEntity( id=DPCode.MATERIAL, name="Material", entity_category=EntityCategory.CONFIG, - custom_configs=localtuya_selector("bean,powder"), + custom_configs=localtuya_selector({"bean": "BEAN", "powder": "POWDER"}), ), LocalTuyaEntity( id=DPCode.MODE, name="Mode", icon="mdi:coffee", custom_configs=localtuya_selector( - "espresso,americano,machiatto,caffe_latte,cafe_mocha,cappuccino" + { + "espresso": "Espresso", + "americano": "Americano", + "machiatto": "Machiatto", + "caffe_latte": "Latte", + "caffe_mocha": "Mocha", + "cappuccino": "Cappuccino", + } ), ), ), @@ -428,21 +452,31 @@ def localtuya_selector(options): id=DPCode.ALARM_VOLUME, name="Volume", entity_category=EntityCategory.CONFIG, - custom_configs=localtuya_selector("low,middle,high,mute"), + custom_configs=localtuya_selector( + {"low": "LOW", "middle": "MIDDLE", "high": "HIGH", "mute": "MUTE"} + ), ), LocalTuyaEntity( id=DPCode.ALARM_STATE, name="State", entity_category=EntityCategory.CONFIG, custom_configs=localtuya_selector( - "alarm_sound,alarm_light,alarm_sound_light,normal" + { + "alarm_sound": "Sound", + "alarm_light": "Light", + "alarm_sound_light": "Sound and Light", + "normal": "NNORMAL", + } ), ), LocalTuyaEntity( id=DPCode.BRIGHT_STATE, name="Brightness", entity_category=EntityCategory.CONFIG, - custom_configs=localtuya_selector("low,middle,high,strong"), + entity_category=EntityCategory.CONFIG, + custom_configs=localtuya_selector( + {"low": "LOW", "middle": "MIDDLE", "high": "HIGH", "strong": "MAX"} + ), ), ), # Smart Camera @@ -560,19 +594,25 @@ def localtuya_selector(options): id=DPCode.LED_TYPE_1, entity_category=EntityCategory.CONFIG, name="Led Type 1", - custom_configs=localtuya_selector("led,incandescent,halogen"), + custom_configs=localtuya_selector( + {"led": "Led", "incandescent": "Incandescent", "halogen": "Halogen"} + ), ), LocalTuyaEntity( id=DPCode.LED_TYPE_2, entity_category=EntityCategory.CONFIG, name="Led Type 2", - custom_configs=localtuya_selector("led,incandescent,halogen"), + custom_configs=localtuya_selector( + {"led": "Led", "incandescent": "Incandescent", "halogen": "Halogen"} + ), ), LocalTuyaEntity( id=DPCode.LED_TYPE_3, entity_category=EntityCategory.CONFIG, name="Led Type 3", - custom_configs=localtuya_selector("led,incandescent,halogen"), + custom_configs=localtuya_selector( + {"led": "Led", "incandescent": "Incandescent", "halogen": "Halogen"} + ), ), ), # Dimmer @@ -582,13 +622,17 @@ def localtuya_selector(options): id=DPCode.LED_TYPE_1, entity_category=EntityCategory.CONFIG, name="Led Type 1", - custom_configs=localtuya_selector("led,incandescent,halogen"), + custom_configs=localtuya_selector( + {"led": "Led", "incandescent": "Incandescent", "halogen": "Halogen"} + ), ), LocalTuyaEntity( id=DPCode.LED_TYPE_2, entity_category=EntityCategory.CONFIG, name="Led Type 2", - custom_configs=localtuya_selector("led,incandescent,halogen"), + custom_configs=localtuya_selector( + {"led": "Led", "incandescent": "Incandescent", "halogen": "Halogen"} + ), ), ), # Fingerbot @@ -597,7 +641,9 @@ def localtuya_selector(options): id=DPCode.MODE, entity_category=EntityCategory.CONFIG, name="Fingerbot Mode", - custom_configs=localtuya_selector("click,switch,toggle"), + custom_configs=localtuya_selector( + {"click": "Click", "switch": "Switch", "toggle": "Toggle"} + ), ), ), # Robot Vacuum @@ -608,22 +654,39 @@ def localtuya_selector(options): entity_category=EntityCategory.CONFIG, icon="mdi:water-opacity", name="Water Tank Adjustment", - custom_configs=localtuya_selector("low,middle,high,closed"), + custom_configs=localtuya_selector( + {"low": "Low", "middle": "Middle", "high": "High", "closed": "Closed"} + ), ), LocalTuyaEntity( id=DPCode.COLLECTION_MODE, entity_category=EntityCategory.CONFIG, icon="mdi:air-filter", name="Dust Collection Mode", - custom_configs=localtuya_selector("small,middle,large"), + custom_configs=localtuya_selector( + {"small": "Small", "middle": "Middle", "large": "Large"} + ), + ), + LocalTuyaEntity( + id=DPCode.VOICE_LANGUAGE, + entity_category=EntityCategory.CONFIG, + icon="mdi:air-filter", + name="Dust Collection Mode", + custom_configs=localtuya_selector({"cn": "Chinese", "en": "English"}), ), LocalTuyaEntity( - id=DPCode.MODE, + id=DPCode.DIRECTION_CONTROL, entity_category=EntityCategory.CONFIG, - icon="mdi:layers-outline", - name="Mode", + icon="mdi:arrow-all", + name="Direction", custom_configs=localtuya_selector( - "standby,random,smart,wall_follow,mop,spiral,left_spiral,right_spiral,right_bow,left_bow,partial_bow,chargego" + { + "foward": "Forward", + "backward": "Backward", + "turn_left": "Left", + "turn_right": "Right", + "stop": "Stop", + } ), ), ), @@ -662,7 +725,9 @@ def localtuya_selector(options): entity_category=EntityCategory.CONFIG, icon="mdi:ceiling-fan-light", name="Light mode", - custom_configs=localtuya_selector("white,colour,colourful"), + custom_configs=localtuya_selector( + {"white": "White", "colour": "Colour", "colourful": "Colourful"} + ), ), LocalTuyaEntity( id=DPCode.COUNTDOWN, @@ -713,7 +778,16 @@ def localtuya_selector(options): entity_category=EntityCategory.CONFIG, icon="mdi:spray", name="Spraying mode", - custom_configs=localtuya_selector("auto,health,baby,sleep,humidity,work"), + custom_configs=localtuya_selector( + { + "auto": "AUTO", + "health": "Health", + "baby": "BABY", + "sleep": "SLEEP", + "humidity": "HUMIDITY", + "work": "WORK", + } + ), ), LocalTuyaEntity( id=DPCode.LEVEL, @@ -721,7 +795,18 @@ def localtuya_selector(options): icon="mdi:spray", name="Spraying level", custom_configs=localtuya_selector( - "level_1,level_2,level_3,level_4,level_5,level_6,level_7,level_8,level_9,level_10" + { + "level_1": "LEVEL 1", + "level_2": "LEVEL 2", + "level_3": "LEVEL 3", + "level_4": "LEVEL 4", + "level_5": "LEVEL 5", + "level_6": "LEVEL 6", + "level_7": "LEVEL 7", + "level_8": "LEVEL 8", + "level_9": "LEVEL 9", + "level_10": "LEVEL 10", + } ), ), LocalTuyaEntity( @@ -729,7 +814,9 @@ def localtuya_selector(options): entity_category=EntityCategory.CONFIG, icon="mdi:lightbulb-multiple", name="Mood light", - custom_configs=localtuya_selector("1,2,3,4,5"), + custom_configs=localtuya_selector( + {"1": "1", "2": "2", "3": "3", "4": "4", "5": "5"} + ), ), LocalTuyaEntity( id=DPCode.COUNTDOWN, @@ -803,7 +890,16 @@ def localtuya_selector(options): entity_category=EntityCategory.CONFIG, name="Cooking Mode", custom_configs=localtuya_selector( - "vegetables,meat,shrimp,fish,chicken,drumsticks,beef,rice" + { + "vegetables": "Vegetables", + "meat": "Meat", + "shrimp": "Shrimp", + "fish": "Fish", + "chicken": "Chicken", + "drumsticks": "Drumsticks", + "beef": "Beef", + "rice": "Rice", + } ), ), ), diff --git a/custom_components/localtuya/core/ha_entities/switches.py b/custom_components/localtuya/core/ha_entities/switches.py index fd6f06c52..6047c5891 100644 --- a/custom_components/localtuya/core/ha_entities/switches.py +++ b/custom_components/localtuya/core/ha_entities/switches.py @@ -495,6 +495,30 @@ icon="mdi:account-voice", entity_category=EntityCategory.CONFIG, ), + LocalTuyaEntity( + id=DPCode.SEEK, + name="Device locating", + icon="mdi:select-marker", + entity_category=EntityCategory.CONFIG, + ), + LocalTuyaEntity( + id=DPCode.RESET_MAP, + name="Map Resetting", + icon="mdi:backup-restore", + entity_category=EntityCategory.CONFIG, + ), + LocalTuyaEntity( + id=DPCode.BREAK_CLEAN, + name="Resumable Cleaning", + icon="mdi:cog-play-outline", + entity_category=EntityCategory.CONFIG, + ), + LocalTuyaEntity( + id=DPCode.Y_MOP, + name="Mop Y", + icon="mdi:dots-vertical", + entity_category=EntityCategory.CONFIG, + ), ), # Siren Alarm # https://developer.tuya.com/en/docs/iot/categorysgbj?id=Kaiuz37tlpbnu diff --git a/custom_components/localtuya/core/ha_entities/vacuums.py b/custom_components/localtuya/core/ha_entities/vacuums.py index f66e7f1de..1cdcd7de9 100644 --- a/custom_components/localtuya/core/ha_entities/vacuums.py +++ b/custom_components/localtuya/core/ha_entities/vacuums.py @@ -5,7 +5,7 @@ Modified by: xZetsubou """ -from .base import DPCode, LocalTuyaEntity, CONF_DEVICE_CLASS, EntityCategory +from .base import DPCode, LocalTuyaEntity, CLOUD_VALUE CONF_POWERGO_DP = "powergo_dp" CONF_IDLE_STATUS_VALUE = "idle_status_value" @@ -47,19 +47,57 @@ } +def localtuya_vaccuums( + modes: str = None, + returning_status_value: str = None, + return_mode: str = None, + fan_speeds: str = None, + paused_state: str = None, + stop_status: str = None, + idle_status_value: str = None, +) -> dict: + """Will return dict with CONF MIN AND CONF MAX, scale 1 is default, 1=1""" + data = { + CONF_MODES: CLOUD_VALUE(modes, CONF_MODE_DP, "range", str), + CONF_IDLE_STATUS_VALUE: idle_status_value or DEFAULT_IDLE_STATUS, + CONF_STOP_STATUS: stop_status or DEFAULT_STOP_STATUS, + CONF_PAUSED_STATE: paused_state or DEFAULT_PAUSED_STATE, + CONF_FAN_SPEEDS: CLOUD_VALUE(fan_speeds, CONF_FAN_SPEED_DP, "range", str), + CONF_RETURN_MODE: return_mode or DEFAULT_RETURN_MODE, + CONF_RETURNING_STATUS_VALUE: returning_status_value or DEFAULT_RETURNING_STATUS, + } + + return data + + VACUUMS: dict[str, tuple[LocalTuyaEntity, ...]] = { # Robot Vacuum # https://developer.tuya.com/en/docs/iot/fsd?id=K9gf487ck1tlo "sd": ( LocalTuyaEntity( - id=(DPCode.SWITCH, DPCode.POWER), + id=(DPCode.SWITCH, DPCode.POWER, DPCode.POWER_GO), icon="mdi:robot-vacuum", powergo_dp=DPCode.POWER_GO, battery_dp=(DPCode.BATTERY_PERCENTAGE, DPCode.ELECTRICITY_LEFT), mode_dp=DPCode.MODE, - clean_time_dp=(DPCode.TOTAL_CLEAN_AREA, DPCode.TOTAL_CLEAN_TIME), + fan_speed_dp=DPCode.SUCTION, + clean_time_dp=( + DPCode.CLEAN_TIME, + DPCode.TOTAL_CLEAN_AREA, + DPCode.TOTAL_CLEAN_TIME, + ), clean_area_dp=DPCode.CLEAN_AREA, clean_record_dp=DPCode.CLEAN_RECORD, + fault_dp=DPCode.FAULT, + custom_configs=localtuya_vaccuums( + modes=DEFAULT_MODES, + returning_status_value=DEFAULT_RETURNING_STATUS, + return_mode=DEFAULT_RETURN_MODE, + fan_speeds=DEFAULT_FAN_SPEEDS, + paused_state=DEFAULT_PAUSED_STATE, + stop_status=DEFAULT_STOP_STATUS, + idle_status_value=DEFAULT_IDLE_STATUS, + ), ), ), } diff --git a/custom_components/localtuya/translations/ar.json b/custom_components/localtuya/translations/ar.json index 118df7d87..c17fdbc6a 100644 --- a/custom_components/localtuya/translations/ar.json +++ b/custom_components/localtuya/translations/ar.json @@ -175,6 +175,7 @@ "clean_area_dp": "Clean Area DP (usually 32)", "clean_record_dp": "Clean Record DP (usually 34)", "locate_dp": "Locate DP (usually 31)", + "pause_dp":"Pause DP", "paused_state": "Pause state (pause, paused, etc)", "stop_status": "Stop status", "brightness": "Brightness (only for white color)", diff --git a/custom_components/localtuya/translations/en.json b/custom_components/localtuya/translations/en.json index 6ac95da4c..76f95110e 100644 --- a/custom_components/localtuya/translations/en.json +++ b/custom_components/localtuya/translations/en.json @@ -179,6 +179,7 @@ "clean_area_dp": "Clean Area DP (usually 32)", "clean_record_dp": "Clean Record DP (usually 34)", "locate_dp": "Locate DP (usually 31)", + "pause_dp":"Pause DP", "paused_state": "Pause state (pause, paused, etc)", "stop_status": "Stop status", "brightness": "Brightness (only for white color)", diff --git a/custom_components/localtuya/translations/it.json b/custom_components/localtuya/translations/it.json index d23cca7da..649a73490 100644 --- a/custom_components/localtuya/translations/it.json +++ b/custom_components/localtuya/translations/it.json @@ -174,6 +174,7 @@ "clean_area_dp": "Clean Area DP (usually 32)", "clean_record_dp": "Clean Record DP (usually 34)", "locate_dp": "Locate DP (usually 31)", + "pause_dp":"Pause DP", "paused_state": "Pause state (pause, paused, etc)", "stop_status": "Stop status", "brightness": "Brightness (only for white color)", diff --git a/custom_components/localtuya/translations/pl.json b/custom_components/localtuya/translations/pl.json index 9b53271ba..d383e7ebf 100644 --- a/custom_components/localtuya/translations/pl.json +++ b/custom_components/localtuya/translations/pl.json @@ -179,6 +179,7 @@ "clean_area_dp": "DP obszaru czyszczenia (zazwyczaj 32)", "clean_record_dp": "DP zapisu czyszczenia (zazwyczaj 34)", "locate_dp": "DP lokalizacji (zazwyczaj 31)", + "pause_dp":"Pause DP", "paused_state": "Stan pauzy (pauza, itp)", "stop_status": "Status zatrzymania", "brightness": "Jasność (tylko dla koloru białego)", diff --git a/custom_components/localtuya/translations/pt-BR.json b/custom_components/localtuya/translations/pt-BR.json index afae6126d..9cb7a9da8 100644 --- a/custom_components/localtuya/translations/pt-BR.json +++ b/custom_components/localtuya/translations/pt-BR.json @@ -174,6 +174,7 @@ "clean_area_dp": "Clean Area DP (usually 32)", "clean_record_dp": "Clean Record DP (usually 34)", "locate_dp": "Locate DP (usually 31)", + "pause_dp":"Pause DP", "paused_state": "Pause state (pause, paused, etc)", "stop_status": "Stop status", "brightness": "Brightness (only for white color)", diff --git a/custom_components/localtuya/vacuum.py b/custom_components/localtuya/vacuum.py index 1388fb871..e4a57aa09 100644 --- a/custom_components/localtuya/vacuum.py +++ b/custom_components/localtuya/vacuum.py @@ -1,4 +1,5 @@ """Platform to locally control Tuya-based vacuum devices.""" + import logging from functools import partial from .config_flow import _col_to_select @@ -35,6 +36,7 @@ CONF_RETURN_MODE, CONF_RETURNING_STATUS_VALUE, CONF_STOP_STATUS, + CONF_PAUSE_DP, ) _LOGGER = logging.getLogger(__name__) @@ -76,6 +78,7 @@ def flow_schema(dps): vol.Optional(CONF_CLEAN_RECORD_DP): _col_to_select(dps, is_dps=True), vol.Optional(CONF_LOCATE_DP): _col_to_select(dps, is_dps=True), vol.Optional(CONF_FAULT_DP): _col_to_select(dps, is_dps=True), + vol.Optional(CONF_PAUSE_DP): _col_to_select(dps, is_dps=True), vol.Optional(CONF_PAUSED_STATE, default=DEFAULT_PAUSED_STATE): str, vol.Optional(CONF_STOP_STATUS, default=DEFAULT_STOP_STATUS): str, } @@ -93,26 +96,30 @@ def __init__(self, device, config_entry, switchid, **kwargs): self._idle_status_list = [] if self.has_config(CONF_IDLE_STATUS_VALUE): - self._idle_status_list = self._config[CONF_IDLE_STATUS_VALUE].split(",") + status = self._config[CONF_IDLE_STATUS_VALUE].split(",") + self._idle_status_list = [state.lstrip() for state in status] self._modes_list = [] if self.has_config(CONF_MODES): - self._modes_list = self._config[CONF_MODES].split(",") + modes_list = self._config[CONF_MODES].split(",") + self._modes_list = [mode.lstrip() for mode in modes_list] self._attrs[MODES_LIST] = self._modes_list self._docked_status_list = [] if self.has_config(CONF_DOCKED_STATUS_VALUE): - self._docked_status_list = self._config[CONF_DOCKED_STATUS_VALUE].split(",") + docked_status = self._config[CONF_DOCKED_STATUS_VALUE].split(",") + self._docked_status_list = [state.lstrip() for state in docked_status] self._fan_speed_list = [] if self.has_config(CONF_FAN_SPEEDS): - self._fan_speed_list = self._config[CONF_FAN_SPEEDS].split(",") + fan_speeds = self._config[CONF_FAN_SPEEDS].split(",") + self._fan_speed_list = [speed.lstrip() for speed in fan_speeds] self._fan_speed = "" self._cleaning_mode = "" @property - def supported_features(self): + def supported_features(self) -> VacuumEntityFeature: """Flag supported features.""" supported_features = ( VacuumEntityFeature.START @@ -123,13 +130,13 @@ def supported_features(self): ) if self.has_config(CONF_RETURN_MODE): - supported_features = supported_features | VacuumEntityFeature.RETURN_HOME + supported_features |= VacuumEntityFeature.RETURN_HOME if self.has_config(CONF_FAN_SPEED_DP): - supported_features = supported_features | VacuumEntityFeature.FAN_SPEED + supported_features |= VacuumEntityFeature.FAN_SPEED if self.has_config(CONF_BATTERY_DP): - supported_features = supported_features | VacuumEntityFeature.BATTERY + supported_features |= VacuumEntityFeature.BATTERY if self.has_config(CONF_LOCATE_DP): - supported_features = supported_features | VacuumEntityFeature.LOCATE + supported_features |= VacuumEntityFeature.LOCATE return supported_features @@ -164,6 +171,9 @@ async def async_start(self, **kwargs): async def async_pause(self, **kwargs): """Stop the vacuum cleaner, do not return to base.""" + if self.has_config(CONF_PAUSE_DP): + return await self._device.set_dp(False, self._config[CONF_PAUSE_DP]) + await self._device.set_dp(False, self._config[CONF_POWERGO_DP]) async def async_return_to_base(self, **kwargs): @@ -182,7 +192,8 @@ async def async_stop(self, **kwargs): self._config[CONF_STOP_STATUS], self._config[CONF_MODE_DP] ) else: - _LOGGER.error("Missing command for stop in commands set.") + await self.async_pause() + # _LOGGER.error("Missing command for stop in commands set.") async def async_clean_spot(self, **kwargs): """Perform a spot clean-up."""