diff --git a/custom_components/midea_auto_cloud/core/device.py b/custom_components/midea_auto_cloud/core/device.py index 54f6a70..9e10c81 100644 --- a/custom_components/midea_auto_cloud/core/device.py +++ b/custom_components/midea_auto_cloud/core/device.py @@ -83,6 +83,14 @@ class MiedaDevice(threading.Thread): self._lua_runtime = MideaCodec(lua_file, device_type=self._attributes.get("device_type"), sn=sn, subtype=subtype) if lua_file is not None else None self._cloud = cloud + def _determine_control_status_based_on_running(self, running_status): + # 根据运行状态确定控制状态, 只有当运行状态是"start"时,控制状态才为"start" + if running_status == "start": + return "start" + # 其他所有情况(包括standby、pause、off、error等),控制状态应为pause + else: + return "pause" + @property def device_name(self): return self._device_name @@ -170,9 +178,26 @@ class MiedaDevice(threading.Thread): if self._device_type == 0xD9 and attribute == "db_location_selection": # 更新属性 self._attributes[attribute] = value + + # 更新db_location(用于查询) + if value == "left": + self._attributes["db_location"] = 1 + elif value == "right": + self._attributes["db_location"] = 2 + # 立即刷新状态以显示新筒的状态 await self.refresh_status() - return + + # 获取当前运行状态 + running_status = self._attributes.get("db_running_status") + if running_status is not None: + # 根据运行状态确定控制状态 + control_status = self._determine_control_status_based_on_running(running_status) + # 更新本地属性 + self._attributes["db_control_status"] = control_status + # 添加到要发送的状态中(如果需要发送到云端) + new_status["db_control_status"] = control_status + # return # 发送到云端,所以注释teturn # 针对T0xD9复式洗衣机,根据选择的筒添加db_location参数 if self._device_type == 0xD9 and attribute != "db_location_selection": @@ -209,16 +234,31 @@ class MiedaDevice(threading.Thread): await cloud.send_device_control(self._device_id, control=nested_status, status=self._attributes) async def set_attributes(self, attributes): - # 针对T0xD9复式洗衣机,当切换筒选择时,立即刷新状态以显示新筒的状态 + # 针对T0xD9复式洗衣机,当切换筒选择时 if self._device_type == 0xD9 and "db_location_selection" in attributes: - # 更新属性 - for attribute, value in attributes.items(): - if attribute in self._attributes.keys(): - self._attributes[attribute] = value + location_selection = attributes["db_location_selection"] + + # 更新本地属性 + self._attributes["db_location_selection"] = location_selection + + # 更新db_location(用于查询) + if location_selection == "left": + self._attributes["db_location"] = 1 + elif location_selection == "right": + self._attributes["db_location"] = 2 + # 立即刷新状态以显示新筒的状态 await self.refresh_status() - return - + + # 获取当前运行状态 + running_status = self._attributes.get("db_running_status") + if running_status is not None: + # 根据运行状态确定控制状态 + control_status = self._determine_control_status_based_on_running(running_status) + # 更新本地属性 + self._attributes["db_control_status"] = control_status + # return # 发送到云端,所以注释teturn + new_status = {} for attr in self._centralized: new_status[attr] = self._attributes.get(attr) @@ -227,15 +267,26 @@ class MiedaDevice(threading.Thread): if attribute in self._attributes.keys(): has_new = True new_status[attribute] = value - - # 针对T0xD9复式洗衣机,根据选择的筒添加db_location参数 - if self._device_type == 0xD9 and "db_location_selection" not in attributes: - location_selection = self._attributes.get("db_location_selection", "left") - if location_selection == "left": - new_status["db_location"] = 1 - elif location_selection == "right": - new_status["db_location"] = 2 - + + # 针对T0xD9复式洗衣机,确保发送到云端的控制命令包含筒位置信息 + if self._device_type == 0xD9: + # 如果attributes中有db_location_selection,确保new_status也有 + if "db_location_selection" in attributes: + location_selection = attributes["db_location_selection"] + new_status["db_location_selection"] = location_selection + # 添加对应的db_location + if location_selection == "left": + new_status["db_location"] = 1 + elif location_selection == "right": + new_status["db_location"] = 2 + # 如果没有db_location_selection,但当前有选择,添加db_location + elif "db_location_selection" not in attributes and self._attributes.get("db_location_selection"): + location_selection = self._attributes.get("db_location_selection", "left") + if location_selection == "left": + new_status["db_location"] = 1 + elif location_selection == "right": + new_status["db_location"] = 2 + # Convert dot-notation attributes to nested structure for transmission nested_status = self._convert_to_nested_structure(new_status) diff --git a/custom_components/midea_auto_cloud/device_mapping/T0x26.py b/custom_components/midea_auto_cloud/device_mapping/T0x26.py index ae23d35..d85bd9b 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0x26.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0x26.py @@ -1,4 +1,4 @@ -from homeassistant.const import Platform, UnitOfTemperature, PRECISION_HALVES, UnitOfTime +from homeassistant.const import Platform, UnitOfTemperature, PERCENTAGE, PRECISION_HALVES, UnitOfTime from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass from homeassistant.components.binary_sensor import BinarySensorDeviceClass from homeassistant.components.switch import SwitchDeviceClass @@ -141,5 +141,91 @@ DEVICE_MAPPING = { } } } + }, + "M0100040": { + "rationale": ["off", "on"], + "queries": [{}], + "centralized": [], + "entities": { + Platform.NUMBER: { + "bath_temperature": { + "min": 30, + "max": 42, + "step": 1, + "unit_of_measurement": UnitOfTemperature.CELSIUS + }, + "heating_temperature": { + "min": 30, + "max": 42, + "step": 1, + "unit_of_measurement": UnitOfTemperature.CELSIUS + }, + "main_light_brightness": { + "min": 10, + "max": 100, + "step": 1, + "unit_of_measurement": PERCENTAGE + } + }, + Platform.SWITCH: { + "radar_induction_enable": { + "device_class": SwitchDeviceClass.SWITCH, + }, + "wifi_led_enable": { + "device_class": SwitchDeviceClass.SWITCH, + } + }, + Platform.SELECT: { + "wind_direction": { + "options": { + "60": {"heating_direction": "60", "bath_direction": "60", "blowing_direction": "60", "drying_direction": "60"}, + "70": {"heating_direction": "70", "bath_direction": "70", "blowing_direction": "70", "drying_direction": "70"}, + "80": {"heating_direction": "80", "bath_direction": "80", "blowing_direction": "80", "drying_direction": "80"}, + "90": {"heating_direction": "90", "bath_direction": "90", "blowing_direction": "90", "drying_direction": "90"}, + "100": {"heating_direction": "100", "bath_direction": "100", "blowing_direction": "100", "drying_direction": "100"}, + "110": {"heating_direction": "110", "bath_direction": "110", "blowing_direction": "110", "drying_direction": "110"}, + "120": {"heating_direction": "120", "bath_direction": "120", "blowing_direction": "120", "drying_direction": "120"}, + "swing": {"heating_direction": "253", "bath_direction": "253", "blowing_direction": "253", "drying_direction": "253"} + } + }, + "light_mode": { + "options": { + "close_all": {"light_mode": "close_all"}, + "night_light": {"light_mode": "night_light"}, + "main_light": {"light_mode": "main_light"} + } + }, + "mode": { + "options": { + "close_all": {"mode": "close_all"}, + "heating": {"mode": "heating"}, + "bath": {"mode": "bath"}, + "blowing": {"mode": "blowing"}, + "ventilation": {"mode": "ventilation"}, + "drying": {"mode": "drying"} + } + }, + }, + Platform.SENSOR: { + "night_light_brightness": { + "unit_of_measurement": PERCENTAGE, + "state_class": SensorStateClass.MEASUREMENT + }, + "main_light_brightness": { + "unit_of_measurement": PERCENTAGE, + "state_class": SensorStateClass.MEASUREMENT + }, + "current_temperature": { + "device_class": SensorDeviceClass.TEMPERATURE, + "unit_of_measurement": UnitOfTemperature.CELSIUS, + "state_class": SensorStateClass.MEASUREMENT + }, + "delay_time": { + "device_class": SensorDeviceClass.DURATION, + "unit_of_measurement": UnitOfTime.MINUTES, + "state_class": SensorStateClass.MEASUREMENT + } + } + } } } diff --git a/custom_components/midea_auto_cloud/device_mapping/T0xAC.py b/custom_components/midea_auto_cloud/device_mapping/T0xAC.py index 7f995f6..9f79efb 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0xAC.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0xAC.py @@ -754,5 +754,202 @@ DEVICE_MAPPING = { }, }, } + }, + "23096653": { + "rationale": ["off", "on"], + "queries": [{}, {"query_type":"run_status"}, {"query_type":"indoor_humidity"}, {"query_type":"indoor_temperature"}], + "calculate": { + "get": [ + { + "lvalue": "[total_elec_value]", + "rvalue": "float([total_elec]) / 1000" + }, + ], + }, + "centralized": [], + "entities": { + Platform.CLIMATE: { + "thermostat": { + "power": "power", + "hvac_modes": { + "off": {"power": "off"}, + "heat": {"power": "on", "mode": "heat"}, + "cool": {"power": "on", "mode": "cool"}, + "auto": {"power": "on", "mode": "auto"}, + "dry": {"power": "on", "mode": "dry"}, + "fan_only": {"power": "on", "mode": "fan"} + }, + "preset_modes": { + "none": { + "eco": "off", + "cool_power_saving": 0, + "strong_wind": "off" + }, + "eco": {"eco": "on", "cool_power_saving": 1}, + "boost": {"strong_wind": "on"} + }, + "fan_modes": { + "silent": {"wind_speed": 20}, + "low": {"wind_speed": 40}, + "medium": {"wind_speed": 60}, + "high": {"wind_speed": 80}, + "full": {"wind_speed": 100}, + "auto": {"wind_speed": 102} + }, + "target_temperature": ["temperature", "small_temperature"], + "current_temperature": "indoor_temperature", + "pre_mode": "mode", + "aux_heat": "ptc", + "min_temp": 17, + "max_temp": 30, + "temperature_unit": UnitOfTemperature.CELSIUS, + "precision": PRECISION_HALVES, + } + }, + Platform.SWITCH: { + "fengguan_remove_odor": { + "device_class": SwitchDeviceClass.SWITCH, + "rationale": ["on", "off"], + "translation_key": "disinfect", + }, + "power": { + "device_class": SwitchDeviceClass.SWITCH, + }, + "ptc": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "aux_heat", + } + }, + Platform.SELECT: { + "follow_body_sense": { + "options": { + "on": {"follow_body_sense": "on", "follow_body_sense_enable": 1}, + "off": {"follow_body_sense": "off", "follow_body_sense_enable": 1}, + } + } + }, + Platform.SENSOR: { + "mode": { + "device_class": SensorDeviceClass.ENUM, + }, + "indoor_temperature": { + "device_class": SensorDeviceClass.TEMPERATURE, + "unit_of_measurement": UnitOfTemperature.CELSIUS, + "state_class": SensorStateClass.MEASUREMENT + }, + "total_elec_value": { + "device_class": SensorDeviceClass.ENERGY, + "unit_of_measurement": "kWh", + "state_class": SensorStateClass.TOTAL_INCREASING + } + } + } + }, + "23096633": { + "rationale": ["off", "on"], + "queries": [{}, {"query_type":"run_status"}, {"query_type":"indoor_humidity"}, {"query_type":"indoor_temperature"}], + "calculate": { + "get": [ + { + "lvalue": "[total_elec_value]", + "rvalue": "float([total_elec]) / 1000" + }, + ], + }, + "centralized": [], + "entities": { + Platform.CLIMATE: { + "thermostat": { + "power": "power", + "hvac_modes": { + "off": {"power": "off"}, + "heat": {"power": "on", "mode": "heat"}, + "cool": {"power": "on", "mode": "cool"}, + "auto": {"power": "on", "mode": "auto"}, + "dry": {"power": "on", "mode": "dry"}, + "fan_only": {"power": "on", "mode": "fan"} + }, + "preset_modes": { + "none": { + "eco": "off", + "cool_power_saving": 0, + "strong_wind": "off" + }, + "eco": {"eco": "on", "cool_power_saving": 1}, + "boost": {"strong_wind": "on"} + }, + "fan_modes": { + "silent": {"wind_speed": 20}, + "low": {"wind_speed": 40}, + "medium": {"wind_speed": 60}, + "high": {"wind_speed": 80}, + "full": {"wind_speed": 100}, + "auto": {"wind_speed": 102} + }, + "target_temperature": ["temperature", "small_temperature"], + "current_temperature": "indoor_temperature", + "pre_mode": "mode", + "aux_heat": "ptc", + "min_temp": 17, + "max_temp": 30, + "temperature_unit": UnitOfTemperature.CELSIUS, + "precision": PRECISION_HALVES, + } + }, + Platform.SWITCH: { + "power": { + "device_class": SwitchDeviceClass.SWITCH, + }, + "ptc": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "aux_heat", + } + }, + Platform.SELECT: { + "new_wind_model_intake_enable": { + "options": { + "off": {"new_wind_model_intake_switch": "off"}, + "low": {"new_wind_model_intake_switch": "on", "new_wind_model_intake_wind": "40"}, + "medium": {"new_wind_model_intake_switch": "on", "new_wind_model_intake_wind": "60"}, + "high": {"new_wind_model_intake_switch": "on", "new_wind_model_intake_wind": "80"}, + "full": {"new_wind_model_intake_switch": "on", "new_wind_model_intake_wind": "100"} + } + }, + "new_wind_model_exhaust_enable": { + "options": { + "off": {"new_wind_model_exhaust_switch": "off"}, + "silent": {"new_wind_model_exhaust_switch": "on", "new_wind_model_exhaust_wind": "20"}, + "high": {"new_wind_model_exhaust_switch": "on", "new_wind_model_exhaust_wind": "80"}, + "full": {"new_wind_model_exhaust_switch": "on", "new_wind_model_exhaust_wind": "100"} + } + }, + "follow_body_sense": { + "options": { + "on": {"follow_body_sense": "on", "follow_body_sense_enable": 1}, + "off": {"follow_body_sense": "off", "follow_body_sense_enable": 1}, + } + } + }, + Platform.SENSOR: { + "mode": { + "device_class": SensorDeviceClass.ENUM, + }, + "indoor_temperature": { + "device_class": SensorDeviceClass.TEMPERATURE, + "unit_of_measurement": UnitOfTemperature.CELSIUS, + "state_class": SensorStateClass.MEASUREMENT + }, + "indoor_humidity": { + "device_class": SensorDeviceClass.HUMIDITY, + "unit_of_measurement": "%", + "state_class": SensorStateClass.MEASUREMENT + }, + "total_elec_value": { + "device_class": SensorDeviceClass.ENERGY, + "unit_of_measurement": "kWh", + "state_class": SensorStateClass.TOTAL_INCREASING + } + } + } } } diff --git a/custom_components/midea_auto_cloud/device_mapping/T0xD9.py b/custom_components/midea_auto_cloud/device_mapping/T0xD9.py index 07f4d6b..1996109 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0xD9.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0xD9.py @@ -24,29 +24,13 @@ DEVICE_MAPPING = { }, }, Platform.SWITCH: { - "db_clean_notification": { + "db_power": { "device_class": SwitchDeviceClass.SWITCH, - "rationale": [0, 1], }, - "db_baby_lock": { + "db_control_status": { "device_class": SwitchDeviceClass.SWITCH, - "rationale": [0, 1], - }, - "db_light": { - "device_class": SwitchDeviceClass.SWITCH, - "rationale": [0, 1], - }, - "db_steam_wash": { - "device_class": SwitchDeviceClass.SWITCH, - "rationale": [0, 1], - }, - "db_fast_clean_wash": { - "device_class": SwitchDeviceClass.SWITCH, - "rationale": [0, 1], - }, - "db_wash_dry_link": { - "device_class": SwitchDeviceClass.SWITCH, - "rationale": [0, 1], + "rationale": ["pause", "start"], + "translation_key": "control_status", } }, Platform.SELECT: { @@ -56,104 +40,26 @@ DEVICE_MAPPING = { "right": {"db_location_selection": "right"} } }, - "db_running_status": { - "options": { - "off": {"db_power": "off", "db_running_status": "off"}, - "standby": {"db_power": "on", "db_running_status": "standby"}, - "start": {"db_power": "on", "db_running_status": "start"}, - "pause": {"db_power": "on", "db_running_status": "pause"}, - "end": {"db_power": "on", "db_running_status": "end"}, - "fault": {"db_power": "on", "db_running_status": "fault"}, - "delay": {"db_power": "on", "db_running_status": "delay"} - } - }, "db_program": { "options": { - "cotton": {"db_program": "cotton"}, - "eco": {"db_program": "eco"}, - "fast_wash": {"db_program": "fast_wash"}, - "mixed_wash": {"db_program": "mixed_wash"}, - "wool": {"db_program": "wool"}, - "ssp": {"db_program": "ssp"}, - "sport_clothes": {"db_program": "sport_clothes"}, - "single_dehytration": {"db_program": "single_dehytration"}, - "rinsing_dehydration": {"db_program": "rinsing_dehydration"}, - "big": {"db_program": "big"}, "baby_clothes": {"db_program": "baby_clothes"}, - "down_jacket": {"db_program": "down_jacket"}, - "color": {"db_program": "color"}, - "intelligent": {"db_program": "intelligent"}, - "quick_wash": {"db_program": "quick_wash"}, - "shirt": {"db_program": "shirt"}, - "fiber": {"db_program": "fiber"}, - "enzyme": {"db_program": "enzyme"}, - "underwear": {"db_program": "underwear"}, - "outdoor": {"db_program": "outdoor"}, - "air_wash": {"db_program": "air_wash"}, - "single_drying": {"db_program": "single_drying"}, - "steep": {"db_program": "steep"}, - "kids": {"db_program": "kids"}, - "water_baby_clothes": {"db_program": "water_baby_clothes"}, - "fast_wash_30": {"db_program": "fast_wash_30"}, - "water_shirt": {"db_program": "water_shirt"}, - "water_mixed_wash": {"db_program": "water_mixed_wash"}, - "water_fiber": {"db_program": "water_fiber"}, - "water_kids": {"db_program": "water_kids"}, - "water_underwear": {"db_program": "water_underwear"}, - "specialist": {"db_program": "specialist"}, - "love": {"db_program": "love"}, - "water_intelligent": {"db_program": "water_intelligent"}, - "water_steep": {"db_program": "water_steep"}, - "water_fast_wash_30": {"db_program": "water_fast_wash_30"}, - "new_water_cotton": {"db_program": "new_water_cotton"}, - "water_eco": {"db_program": "water_eco"}, - "wash_drying_60": {"db_program": "wash_drying_60"}, - "self_wash_5": {"db_program": "self_wash_5"}, - "fast_wash_min": {"db_program": "fast_wash_min"}, - "mixed_wash_min": {"db_program": "mixed_wash_min"}, - "dehydration_min": {"db_program": "dehydration_min"}, - "self_wash_min": {"db_program": "self_wash_min"}, - "baby_clothes_min": {"db_program": "baby_clothes_min"}, - "silk_wash": {"db_program": "silk_wash"}, - "prevent_allergy": {"db_program": "prevent_allergy"}, - "cold_wash": {"db_program": "cold_wash"}, - "soft_wash": {"db_program": "soft_wash"}, - "remove_mite_wash": {"db_program": "remove_mite_wash"}, - "water_intense_wash": {"db_program": "water_intense_wash"}, - "fast_dry": {"db_program": "fast_dry"}, - "water_outdoor": {"db_program": "water_outdoor"}, - "spring_autumn_wash": {"db_program": "spring_autumn_wash"}, - "summer_wash": {"db_program": "summer_wash"}, - "winter_wash": {"db_program": "winter_wash"}, - "jean": {"db_program": "jean"}, - "new_clothes_wash": {"db_program": "new_clothes_wash"}, - "silk": {"db_program": "silk"}, - "insight_wash": {"db_program": "insight_wash"}, - "fitness_clothes": {"db_program": "fitness_clothes"}, - "mink": {"db_program": "mink"}, - "fresh_air": {"db_program": "fresh_air"}, - "bucket_dry": {"db_program": "bucket_dry"}, - "jacket": {"db_program": "jacket"}, - "bath_towel": {"db_program": "bath_towel"}, - "night_fresh_wash": {"db_program": "night_fresh_wash"}, - "degerm": {"db_program": "degerm"}, - "heart_wash": {"db_program": "heart_wash"}, - "water_cold_wash": {"db_program": "water_cold_wash"}, - "water_prevent_allergy": {"db_program": "water_prevent_allergy"}, - "water_remove_mite_wash": {"db_program": "water_remove_mite_wash"}, - "water_ssp": {"db_program": "water_ssp"}, - "standard": {"db_program": "standard"}, - "green_wool": {"db_program": "green_wool"}, - "cook_wash": {"db_program": "cook_wash"}, - "fresh_remove_wrinkle": {"db_program": "fresh_remove_wrinkle"}, - "steam_sterilize_wash": {"db_program": "steam_sterilize_wash"}, - "sterilize_wash": {"db_program": "sterilize_wash"}, - "white_clothes_clean": {"db_program": "white_clothes_clean"}, + "baby_clothes_dry": {"db_program": "151"}, "clean_stains": {"db_program": "clean_stains"}, - "prevent_cross_color": {"db_program": "prevent_cross_color"}, - "quick_dry_clothes": {"db_program": "quick_dry_clothes"}, - "yoga_clothes": {"db_program": "yoga_clothes"} - } + "cold_wash": {"db_program": "cold_wash"}, + "cook_wash": {"db_program": "cook_wash"}, + "fast_wash": {"db_program": "137"}, + "hot_wind_dry": {"db_program": "153"}, + "rinsing_dehydration": {"db_program": "rinsing_dehydration"}, + "self_wash_5": {"db_program": "self_wash_5"}, + "single_dehytration": {"db_program": "single_dehytration"}, + "single_drying": {"db_program": "single_drying"}, + "small_wash_dry": {"db_program": "138"}, + "socks": {"db_program": "148"}, + "standard": {"db_program": "standard"}, + "underpants": {"db_program": "156"}, + "underwear": {"db_program": "underwear"}, + "water_ssp": {"db_program": "water_ssp"} + } } }, Platform.SENSOR: { diff --git a/custom_components/midea_auto_cloud/device_mapping/T0xFA.py b/custom_components/midea_auto_cloud/device_mapping/T0xFA.py index 1d9c925..b897ebb 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0xFA.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0xFA.py @@ -205,5 +205,54 @@ DEVICE_MAPPING = { } } } + }, + "5600119Z": { + "rationale": ["off", "on"], + "queries": [{}], + "centralized": [], + "entities": { + Platform.SWITCH: { + "display_on_off": { + "device_class": SwitchDeviceClass.SWITCH, + "rationale": ["on", "off"], + "translation_key": "screen_close", + }, + "humidify": { + "device_class": SwitchDeviceClass.SWITCH, + "rationale": ["off", "1"], + }, + "waterions": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "anion", + } + }, + Platform.FAN: { + "fan": { + "power": "power", + "speeds": list({"gear": value + 1} for value in range(0, 3)), + "oscillate": "swing", + "preset_modes": { + "normal": { + "mode": "normal", + "speeds": list({"gear": value + 1} for value in range(0, 3)) + }, + "sleep": { + "mode": "sleep", + "speeds": list({"gear": value + 1} for value in range(0, 2)) + }, + "baby": { + "mode": "baby", + "speeds": list({"gear": value + 1} for value in range(0, 1)) + } + } + } + }, + Platform.SENSOR: { + "water_feedback": { + "device_class": SensorDeviceClass.ENUM, + "state_class": SensorStateClass.MEASUREMENT + } + } + } } } diff --git a/custom_components/midea_auto_cloud/device_mapping/T0xFB.py b/custom_components/midea_auto_cloud/device_mapping/T0xFB.py index de09936..09462d8 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0xFB.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0xFB.py @@ -1,5 +1,5 @@ from homeassistant.const import Platform, UnitOfTemperature, UnitOfVolume, UnitOfTime, PERCENTAGE, PRECISION_HALVES, \ - UnitOfEnergy, UnitOfPower + PRECISION_WHOLE, UnitOfEnergy, UnitOfPower from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass from homeassistant.components.binary_sensor import BinarySensorDeviceClass from homeassistant.components.switch import SwitchDeviceClass @@ -16,6 +16,7 @@ DEVICE_MAPPING = { }, "screen_close": { "device_class": SwitchDeviceClass.SWITCH, + "rationale": ["on", "off"], } }, Platform.CLIMATE: { @@ -49,5 +50,64 @@ DEVICE_MAPPING = { } } } + }, + "570667EC": { + "rationale": ["off", "on"], + "queries": [{}], + "centralized": [], + "entities": { + Platform.SWITCH: { + "auto_power_off": { + "device_class": SwitchDeviceClass.SWITCH, + }, + "humidification": { + "device_class": SwitchDeviceClass.SWITCH, + "rationale": ['off', 'no_change'], + }, + "lock": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "child_lock", + }, + "screen_close": { + "device_class": SwitchDeviceClass.SWITCH, + "rationale": ['on', 'off'], + }, + "voice": { + "device_class": SwitchDeviceClass.SWITCH, + "rationale": ['close_buzzer', 'open_buzzer'], + } + }, + Platform.CLIMATE: { + "electric_heater": { + "power": "power", + "hvac_modes": { + "off": {"power": "off"}, + "heat": {"power": "on"} + }, + "target_temperature": "temperature", + "current_temperature": "cur_temperature", + "min_temp": 5, + "max_temp": 35, + "temperature_unit": UnitOfTemperature.CELSIUS, + "precision": PRECISION_WHOLE, + } + }, + Platform.SELECT: { + "gear": { + "options": { + "left_warm": {"gear": 1}, + "right_warm": {"gear": 2}, + "full_on": {"gear": 3} + } + } + }, + Platform.SENSOR: { + "power_statistics": { + "device_class": SensorDeviceClass.POWER, + "unit_of_measurement": UnitOfPower.WATT, + "state_class": SensorStateClass.MEASUREMENT + } + } + } } } diff --git a/custom_components/midea_auto_cloud/device_mapping/T0xFC.py b/custom_components/midea_auto_cloud/device_mapping/T0xFC.py index 4c11e80..39e6ad1 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0xFC.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0xFC.py @@ -99,5 +99,90 @@ DEVICE_MAPPING = { } } } + }, + "571Z3081": { + "rationale": ["off", "on"], + "queries": [{}], + "centralized": [], + "entities": { + Platform.SWITCH: { + "power": { + "device_class": SwitchDeviceClass.SWITCH, + }, + "buzzer": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "voice", + }, + "lock": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "child_lock", + }, + "waterions":{ + "device_class": SwitchDeviceClass.SWITCH, + } + }, + Platform.SELECT: { + "mode": { + "options": { + "manual": {"mode": "manual"}, + "sleep": {"mode": "sleep"}, + "auto": {"mode": "auto"}, + "air_dry": {"mode": "air_dry"} + } + }, + "bias_gear":{ + "options": { + "瑜伽静修场景": {"mode": "auto", "sub_mode": "denoise", "bias_gear": -20}, + "室内对话场景": {"mode": "auto", "sub_mode": "denoise", "bias_gear": -10} + } + }, + "bright": { + "options": { + "全亮": {"bright": 0}, + "半亮": {"bright": 6}, + "熄灭": {"bright": 7} + } + }, + "gear": { + "options": { + "low": {"wind_speed": 1}, + "medium": {"wind_speed": 2}, + "high": {"wind_speed": 3} + } + } + }, + Platform.SENSOR: { + "temperature_feedback": { + "device_class": SensorDeviceClass.TEMPERATURE, + "unit_of_measurement": UnitOfTemperature.CELSIUS, + "state_class": SensorStateClass.MEASUREMENT + }, + "humidify_feedback": { + "device_class": SensorDeviceClass.HUMIDITY, + "unit_of_measurement": "%", + "state_class": SensorStateClass.MEASUREMENT + }, + "hcho":{ + "device_class": SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS, + "unit_of_measurement": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + "state_class": SensorStateClass.MEASUREMENT + }, + "pm1":{ + "device_class": SensorDeviceClass.PM1, + "unit_of_measurement": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + "state_class": SensorStateClass.MEASUREMENT + }, + "pm25":{ + "device_class": SensorDeviceClass.PM25, + "unit_of_measurement": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + "state_class": SensorStateClass.MEASUREMENT + }, + "pm10":{ + "device_class": SensorDeviceClass.PM10, + "unit_of_measurement": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + "state_class": SensorStateClass.MEASUREMENT + } + } + } } } diff --git a/custom_components/midea_auto_cloud/device_mapping/T0xFD.py b/custom_components/midea_auto_cloud/device_mapping/T0xFD.py index 143a7e0..cc67e47 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0xFD.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0xFD.py @@ -156,5 +156,87 @@ DEVICE_MAPPING = { } } } + }, + "202Z310H": { + "rationale": ["off", "on"], + "queries": [{}], + "centralized": [], + "entities": { + Platform.SWITCH: { + "buzzer": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "voice", + }, + "airDry_on_off": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "airdry_on_off", + }, + "power": { + "device_class": SwitchDeviceClass.SWITCH, + }, + "power_on_timer": { + "device_class": SwitchDeviceClass.SWITCH, + }, + "power_off_timer": { + "device_class": SwitchDeviceClass.SWITCH, + } + }, + Platform.BINARY_SENSOR: { + "add_water_flag": { + "device_class": BinarySensorDeviceClass.PROBLEM, + } + }, + Platform.SELECT: { + "humidity_mode": { + "options": { + "manual": {"humidity_mode": "manual"}, + "auto": {"humidity_mode": "auto"}, + "sleep": {"humidity_mode": "sleep"} + } + }, + "wind_speed": { + "options": { + "low": {"wind_speed": "low"}, + "middle": {"wind_speed": "middle"}, + "high": {"wind_speed": "high"} + } + } + }, + Platform.SENSOR: { + "running_percent": { + "device_class": SensorDeviceClass.POWER_FACTOR, + "unit_of_measurement": PERCENTAGE, + "state_class": SensorStateClass.MEASUREMENT + }, + "error_code": { + "device_class": SensorDeviceClass.ENUM + }, + "cur_temperature": { + "device_class": SensorDeviceClass.TEMPERATURE, + "unit_of_measurement": UnitOfTemperature.CELSIUS, + "state_class": SensorStateClass.MEASUREMENT + }, + "air_dry_left_time": { + "device_class": SensorDeviceClass.DURATION, + "unit_of_measurement": UnitOfTime.MINUTES, + "state_class": SensorStateClass.MEASUREMENT + }, + "time_on": { + "device_class": SensorDeviceClass.DURATION, + "unit_of_measurement": UnitOfTime.MINUTES, + "state_class": SensorStateClass.MEASUREMENT + }, + "time_off": { + "device_class": SensorDeviceClass.DURATION, + "unit_of_measurement": UnitOfTime.MINUTES, + "state_class": SensorStateClass.MEASUREMENT + }, + "tank_status": { + "device_class": SensorDeviceClass.BATTERY, + "unit_of_measurement": PERCENTAGE, + "state_class": SensorStateClass.MEASUREMENT + } + } + } } } \ No newline at end of file diff --git a/custom_components/midea_auto_cloud/fan.py b/custom_components/midea_auto_cloud/fan.py index 8cc0b43..f3f0495 100644 --- a/custom_components/midea_auto_cloud/fan.py +++ b/custom_components/midea_auto_cloud/fan.py @@ -69,6 +69,8 @@ class MideaFanEntity(MideaEntity, FanEntity): self._key_oscillate = self._config.get("oscillate") self._key_directions = self._config.get("directions") self._attr_speed_count = len(self._key_speeds) if self._key_speeds else 0 + self._current_preset_mode = None + self._current_speeds = self._key_speeds @property def supported_features(self): @@ -77,7 +79,7 @@ class MideaFanEntity(MideaEntity, FanEntity): features |= FanEntityFeature.TURN_OFF if self._key_preset_modes is not None and len(self._key_preset_modes) > 0: features |= FanEntityFeature.PRESET_MODE - if self._key_speeds is not None and len(self._key_speeds) > 0: + if self._current_speeds is not None and len(self._current_speeds) > 0: features |= FanEntityFeature.SET_SPEED if self._key_oscillate is not None: features |= FanEntityFeature.OSCILLATE @@ -99,13 +101,39 @@ class MideaFanEntity(MideaEntity, FanEntity): def preset_mode(self): if self._key_preset_modes is None: return None - return self._dict_get_selected(self._key_preset_modes) + + current_mode = self._dict_get_selected(self._key_preset_modes) + + if current_mode: + mode_config = self._key_preset_modes.get(current_mode, {}) + + # 切换到该模式的档位配置 + if "speeds" in mode_config: + self._current_speeds = mode_config["speeds"] + self._attr_speed_count = len(self._current_speeds) + else: + # 使用全局配置 + self._current_speeds = self._key_speeds + self._attr_speed_count = len(self._current_speeds) if self._current_speeds else 0 + + self._current_preset_mode = current_mode + + return current_mode @property def percentage(self): - index = self._list_get_selected(self._key_speeds) + # 如果风扇关闭,返回0%(这样UI会显示"关闭") + if not self.is_on: + return 0 + + index = self._list_get_selected(self._current_speeds) if index is None: - return None + return 0 + + # 计算百分比:档位1对应最小百分比,最大档位对应100% + if self._attr_speed_count <= 1: + return 100 # 只有一个档位时,开启就是100% + return round((index + 1) * 100 / self._attr_speed_count) @property @@ -124,11 +152,40 @@ class MideaFanEntity(MideaEntity, FanEntity): ): new_status = {} if preset_mode is not None and self._key_preset_modes is not None: - new_status.update(self._key_preset_modes.get(preset_mode, {})) - if percentage is not None and self._key_speeds: - index = round(percentage * self._attr_speed_count / 100) - 1 - index = max(0, min(index, len(self._key_speeds) - 1)) - new_status.update(self._key_speeds[index]) + mode_config = self._key_preset_modes.get(preset_mode, {}) + new_status.update({"mode": mode_config.get("mode")}) + + # 切换到该模式的档位配置 + if "speeds" in mode_config: + self._current_speeds = mode_config["speeds"] + self._attr_speed_count = len(self._current_speeds) + else: + self._current_speeds = self._key_speeds + self._attr_speed_count = len(self._current_speeds) if self._current_speeds else 0 + + self._current_preset_mode = preset_mode + + # 如果只有一个档位,自动设置 + if "speeds" in mode_config and len(mode_config["speeds"]) == 1: + new_status.update(mode_config["speeds"][0]) + + # 使用当前模式的速度配置 + if percentage is not None and self._current_speeds: + # 如果百分比为0,直接关闭(但async_turn_on不应该传入0) + if percentage == 0: + await self.async_turn_off() + return + + # 计算档位索引(至少为1档) + if self._attr_speed_count <= 1: + index = 0 + else: + index = round(percentage * self._attr_speed_count / 100) - 1 + index = max(0, min(index, len(self._current_speeds) - 1)) + + new_status.update(self._current_speeds[index]) + + # 打开风扇 await self._async_set_status_on_off(self._key_power, True) if new_status: await self.async_set_attributes(new_status) @@ -137,18 +194,59 @@ class MideaFanEntity(MideaEntity, FanEntity): await self._async_set_status_on_off(self._key_power, False) async def async_set_percentage(self, percentage: int): - if not self._key_speeds: + if not self._current_speeds: return - index = round(percentage * self._attr_speed_count / 100) - if 0 < index <= len(self._key_speeds): - new_status = self._key_speeds[index - 1] + + # 处理关闭情况(0% 表示关闭) + if percentage == 0: + await self.async_turn_off() + return + + # 如果风扇当前是关闭状态,先打开风扇 + if not self.is_on: + await self._async_set_status_on_off(self._key_power, True) + + # 将百分比转换为档位索引(从1开始,因为0%已处理) + if self._attr_speed_count <= 1: + index = 0 + else: + # 百分比1-100对应档位1到最大档位 + index = round((percentage / 100) * self._attr_speed_count) + index = max(1, min(index, self._attr_speed_count)) # 确保至少为1档 + + # 获取对应档位的配置 + if 1 <= index <= len(self._current_speeds): + new_status = self._current_speeds[index - 1] # 索引从0开始,所以减1 await self.async_set_attributes(new_status) async def async_set_preset_mode(self, preset_mode: str): if not self._key_preset_modes: return - new_status = self._key_preset_modes.get(preset_mode) - if new_status: + + mode_config = self._key_preset_modes.get(preset_mode, {}) + if mode_config: + + # 如果风扇当前是关闭状态,先打开风扇 + if not self.is_on: + await self._async_set_status_on_off(self._key_power, True) + + # 切换到该模式的档位配置 + if "speeds" in mode_config: + self._current_speeds = mode_config["speeds"] + self._attr_speed_count = len(self._current_speeds) + else: + self._current_speeds = self._key_speeds + self._attr_speed_count = len(self._current_speeds) if self._current_speeds else 0 + + self._current_preset_mode = preset_mode + + # 设置模式 + new_status = {"mode": mode_config.get("mode")} + + # 如果只有一个档位,自动设置 + if "speeds" in mode_config and len(mode_config["speeds"]) == 1: + new_status.update(mode_config["speeds"][0]) + await self.async_set_attributes(new_status) async def async_oscillate(self, oscillating: bool): diff --git a/custom_components/midea_auto_cloud/translations/en.json b/custom_components/midea_auto_cloud/translations/en.json index 4154f35..3ee8c0f 100644 --- a/custom_components/midea_auto_cloud/translations/en.json +++ b/custom_components/midea_auto_cloud/translations/en.json @@ -408,6 +408,25 @@ } }, "select": { + "new_wind_model_intake_enable": { + "name": "Intake Wind", + "state": { + "off": "Off", + "low": "Low Speed", + "medium": "Medium Speed", + "high": "High Speed", + "full": "Turbo" + } + }, + "new_wind_model_exhaust_enable": { + "name": "Exhaust Wind", + "state": { + "off": "Off", + "silent": "Silent", + "high": "High Speed", + "full": "Turbo" + } + }, "updown": { "name": "Running Status" }, @@ -544,6 +563,7 @@ "humidity_mode": { "name": "Humidity Mode", "state": { + "auto": "auto", "manual": "manual", "moist_skin": "moist skin", "sleep": "sleep" @@ -570,9 +590,14 @@ "mode": { "name": "Mode", "state": { + "air_dry": "Air Dry Mode", + "auto": "Auto Mode", + "manual": "Manual Mode", "normal": "normal", "factory_test": "factory test", + "fast": "Fast Mode", "service": "service", + "sleep": "Sleep Mode", "normal_continus": "normal continus" } }, @@ -747,6 +772,7 @@ "state": { "low": "low", "medium": "medium", + "middle": "middle", "high": "high", "auto": "auto", "invalid": "invalid" @@ -828,7 +854,15 @@ "name": "Sleep Sensor" }, "gear": { - "name": "Gear" + "name": "Gear", + "state": { + "low": "Low", + "medium": "Medium", + "high": "High", + "left_warm": "Left Warm", + "right_warm": "Right Warm", + "full_on": "Full On" + } }, "ptc": { "name": "PTC" @@ -1902,6 +1936,9 @@ }, "tw1_out_water_temp": { "name": "Outlet Water Temperature" + }, + "total_elec_value": { + "name": "Total Electricity" } }, "light": { @@ -1998,6 +2035,18 @@ } }, "switch": { + "auto_power_off": { + "name": "Auto Power Off" + }, + "power_on_timer": { + "name": "Power On Timer" + }, + "power_off_timer": { + "name": "Power Off Timer" + }, + "voice": { + "name": "Sound" + }, "laundry": { "name": "One Key Laundry" }, @@ -2023,7 +2072,7 @@ "name": "Wind Change with Temperature" }, "screen_close": { - "name": "Screen Close" + "name": "Screen Display" }, "anion": { "name": "Anion" @@ -2706,6 +2755,9 @@ "function_zone_power": { "name": "Function Zone Power" }, + "humidify": { + "name": "Cool Wind" + }, "humidify_power": { "name": "Humidify Power" }, diff --git a/custom_components/midea_auto_cloud/translations/zh-Hans.json b/custom_components/midea_auto_cloud/translations/zh-Hans.json index d3ca10a..c5ad9e9 100644 --- a/custom_components/midea_auto_cloud/translations/zh-Hans.json +++ b/custom_components/midea_auto_cloud/translations/zh-Hans.json @@ -408,6 +408,25 @@ } }, "select": { + "new_wind_model_intake_enable": { + "name": "新风", + "state": { + "off": "关闭", + "low": "低速", + "medium": "中速", + "high": "高速", + "full": "强劲" + } + }, + "new_wind_model_exhaust_enable": { + "name": "排风", + "state": { + "off": "关闭", + "silent": "静音", + "high": "高速", + "full": "强劲" + } + }, "updown": { "name": "运行状态", "state": { @@ -423,7 +442,11 @@ "name": "左右摆风角度" }, "follow_body_sense": { - "name": "随身感" + "name": "随身感", + "state": { + "on": "开", + "off": "关" + } }, "bright": { "name": "亮度" @@ -500,7 +523,7 @@ "ssp": "SSP", "sport_clothes": "运动服", "single_dehytration": "单脱水", - "rinsing_dehydration": "漂洗脱水", + "rinsing_dehydration": "漂+脱", "big": "大件", "baby_clothes": "婴儿服", "down_jacket": "羽绒服", @@ -510,7 +533,7 @@ "shirt": "衬衫", "fiber": "化纤", "enzyme": "酶洗", - "underwear": "内衣", + "underwear": "文胸", "outdoor": "户外", "air_wash": "空气洗", "single_drying": "单烘干", @@ -531,7 +554,7 @@ "new_water_cotton": "新水洗棉", "water_eco": "水洗节能", "wash_drying_60": "洗烘60", - "self_wash_5": "自洁5", + "self_wash_5": "筒自洁", "fast_wash_min": "快洗分钟", "mixed_wash_min": "混合洗分钟", "dehydration_min": "脱水分钟", @@ -564,18 +587,23 @@ "water_cold_wash": "水洗冷水", "water_prevent_allergy": "水洗防过敏", "water_remove_mite_wash": "水洗除螨", - "water_ssp": "水洗SSP", + "water_ssp": "深度洁筒", "standard": "标准", "green_wool": "绿色羊毛", - "cook_wash": "烹饪洗", + "cook_wash": "高温煮洗", "fresh_remove_wrinkle": "清新去皱", "steam_sterilize_wash": "蒸汽杀菌洗", "sterilize_wash": "杀菌洗", "white_clothes_clean": "白衣清洁", - "clean_stains": "去渍", + "clean_stains": "特渍洗", "prevent_cross_color": "防串色", "quick_dry_clothes": "快干衣物", - "yoga_clothes": "瑜伽服" + "yoga_clothes": "瑜伽服", + "baby_clothes_dry": "婴童服烘", + "hot_wind_dry": "热风暖衣", + "small_wash_dry": "小件智洗烘", + "socks": "袜子", + "underpants": "内裤" } }, "db_running_status": { @@ -644,6 +672,7 @@ "humidity_mode": { "name": "湿度模式", "state": { + "auto": "AI湿随温变", "manual": "手动", "moist_skin": "润肤", "sleep": "睡眠" @@ -670,10 +699,21 @@ "mode": { "name": "运行模式", "state": { + "air_dry": "风芯模式", + "auto": "智能托管", + "manual": "手动模式", "normal": "正常", "factory_test": "工厂测试", + "fast": "速净模式", "service": "服务", - "normal_continus": "正常连续" + "sleep": "睡眠模式", + "normal_continus": "正常连续", + "close_all": "关闭", + "heating": "取暖", + "bath": "安心沐浴", + "blowing": "吹风", + "ventilation": "换气", + "drying": "干燥" } }, "mode_state": { @@ -847,6 +887,7 @@ "state": { "low": "低速", "medium": "中速", + "middle": "中速", "high": "高速", "auto": "自动", "invalid": "无效" @@ -928,7 +969,15 @@ "name": "睡眠传感器" }, "gear": { - "name": "档位" + "name": "档位", + "state": { + "low": "低", + "medium": "中", + "high": "高", + "left_warm": "左暖", + "right_warm": "右暖", + "full_on": "全开" + } }, "ptc": { "name": "电辅热" @@ -958,7 +1007,12 @@ "name": "加热方向" }, "light_mode": { - "name": "灯光模式" + "name": "灯光模式", + "state": { + "close_all": "关闭", + "night_light": "夜灯", + "main_light": "照明" + } }, "bath_direction": { "name": "浴室方向" @@ -966,6 +1020,19 @@ "drying_direction": { "name": "烘干方向" }, + "wind_direction": { + "name": "吹风方向", + "state": { + "60": "60°", + "70": "70°", + "80": "80°", + "90": "90°", + "100": "100°", + "110": "110°", + "120": "120°", + "swing": "自动摆风" + } + }, "air_set_hour": { "name": "烘干存储设置时间" }, @@ -2002,6 +2069,9 @@ }, "tw1_out_water_temp": { "name": "出水温度" + }, + "total_elec_value": { + "name": "总耗电量" } }, "light": { @@ -2010,6 +2080,15 @@ } }, "number": { + "bath_temperature": { + "name": "沐浴温度" + }, + "heating_temperature": { + "name": "取暖温度" + }, + "main_light_brightness": { + "name": "照明亮度" + }, "light_brightness": { "name": "照明亮度" }, @@ -2094,10 +2173,37 @@ }, "fan": { "fan": { - "name": "风扇" + "name": "风扇", + "state_attributes": { + "preset_mode": { + "state": { + "baby": "宝宝风", + "normal": "正常风", + "sleep": "睡眠风", + "self_selection": "自选风", + "sleeping_wind": "睡眠风", + "purified_wind": "净化风" + } + } + } } }, "switch": { + "radar_induction_enable": { + "name": "人感夜灯" + }, + "auto_power_off": { + "name": "待机超时自动关机" + }, + "power_on_timer": { + "name": "定时开机" + }, + "power_off_timer": { + "name": "定时关机" + }, + "voice": { + "name": "声音" + }, "laundry": { "name": "一键晾衣" }, @@ -2123,7 +2229,7 @@ "name": "风随温变" }, "screen_close": { - "name": "屏幕关闭" + "name": "屏幕显示" }, "anion": { "name": "负离子" @@ -2321,7 +2427,7 @@ "name": "启停" }, "airdry_on_off": { - "name": "风干开关" + "name": "湿帘风干" }, "airswitch": { "name": "烘干存储开关" @@ -2806,6 +2912,9 @@ "function_zone_power": { "name": "功能区电源" }, + "humidify": { + "name": "清凉风" + }, "humidify_power": { "name": "加湿电源" },