Merge pull request #84 from Cyborg2017/staging

Perform updates for multiple devices.
This commit is contained in:
Yingqi Tang
2026-01-05 20:04:05 +08:00
committed by GitHub
11 changed files with 939 additions and 164 deletions

View File

@@ -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)

View File

@@ -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
}
}
}
}
}

View File

@@ -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
}
}
}
}
}

View File

@@ -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: {

View File

@@ -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
}
}
}
}
}

View File

@@ -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
}
}
}
}
}

View File

@@ -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
}
}
}
}
}

View File

@@ -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
}
}
}
}
}

View File

@@ -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):

View File

@@ -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"
},

View File

@@ -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": "加湿电源"
},