From e3f0bf9dfc6e200a2430c4ad6fa787a8fbf6cc64 Mon Sep 17 00:00:00 2001 From: sususweet Date: Wed, 4 Feb 2026 23:33:42 +0800 Subject: [PATCH] fix: local buzzer control for T0xAC. Fix #102. --- .../midea_auto_cloud/__init__.py | 19 ++++++++ .../midea_auto_cloud/core/device.py | 23 +++++++++- .../midea_auto_cloud/data_coordinator.py | 14 +++++- .../midea_auto_cloud/device_mapping/T0xAC.py | 44 ++++++++++++++++--- 4 files changed, 91 insertions(+), 9 deletions(-) diff --git a/custom_components/midea_auto_cloud/__init__.py b/custom_components/midea_auto_cloud/__init__.py index f5d0996..c58d933 100644 --- a/custom_components/midea_auto_cloud/__init__.py +++ b/custom_components/midea_auto_cloud/__init__.py @@ -308,6 +308,25 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry): except Exception: pass + # 提取并设置默认值 + try: + default_values = {} + entities_cfg = (mapping.get("entities") or {}) + for platform_cfg in entities_cfg.values(): + if not isinstance(platform_cfg, dict): + continue + for entity_key, ecfg in platform_cfg.items(): + if not isinstance(ecfg, dict): + continue + # 检查是否有 default_value 字段 + if "default_value" in ecfg: + # 使用 entity_key 作为属性名,或者使用 attribute 字段 + attr_name = ecfg.get("attribute", entity_key) + default_values[attr_name] = ecfg["default_value"] + device.set_default_values(default_values) + except Exception: + traceback.print_exc() + # 预置 attributes:包含 centralized 里声明的所有键、entities 中使用到的所有属性键 try: preset_keys = set(mapping.get("centralized", [])) diff --git a/custom_components/midea_auto_cloud/core/device.py b/custom_components/midea_auto_cloud/core/device.py index c8239aa..d6c4f8e 100644 --- a/custom_components/midea_auto_cloud/core/device.py +++ b/custom_components/midea_auto_cloud/core/device.py @@ -80,6 +80,7 @@ class MiedaDevice(threading.Thread): self._centralized = [] self._calculate_get = [] self._calculate_set = [] + self._default_values = {} 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 @@ -142,6 +143,10 @@ class MiedaDevice(threading.Thread): self._calculate_get = values_get if values_get else [] self._calculate_set = values_set if values_set else [] + def set_default_values(self, default_values: dict): + """设置属性的默认值""" + self._default_values = default_values or {} + def get_attribute(self, attribute): return self._attributes.get(attribute) @@ -417,6 +422,13 @@ class MiedaDevice(threading.Thread): def _parse_cloud_message(self, status, update=True): # MideaLogger.debug(f"Received: {decrypted}") new_status = {} + # 对于有默认值的变量,在解析前先设置一次默认值 + for attr, default_value in self._default_values.items(): + # self._attributes[attr] = default_value + if attr not in self._attributes or self._attributes[attr] is None: + new_status[attr] = default_value + + # 处理云端返回的状态,云端结果会覆盖默认值 for single in status.keys(): value = status.get(single) if single not in self._attributes or self._attributes[single] != value: @@ -439,15 +451,22 @@ class MiedaDevice(threading.Thread): .replace("[", "[\"") calculate_str2 = \ (f"{lvalue.replace('[', 'new_status[').replace("]", "\"]")} = " - f"{rvalue.replace('[', 'self._attributes[').replace(']', "\"]")}") \ + f"{rvalue.replace('[', 'new_status[').replace(']', "\"]")}") \ .replace("[", "[\"") try: exec(calculate_str1) + except Exception as e: + traceback.print_exc() + MideaLogger.warning( + f"Calculation Error: {lvalue} = {rvalue}, calculate_str1: {calculate_str1}", + self._device_id + ) + try: exec(calculate_str2) except Exception as e: traceback.print_exc() MideaLogger.warning( - f"Calculation Error: {lvalue} = {rvalue}, calculate_str1: {calculate_str1}, calculate_str2: {calculate_str2}", + f"Calculation Error: {lvalue} = {rvalue}, calculate_str2: {calculate_str2}", self._device_id ) if update: diff --git a/custom_components/midea_auto_cloud/data_coordinator.py b/custom_components/midea_auto_cloud/data_coordinator.py index 90ef2de..a7af46f 100644 --- a/custom_components/midea_auto_cloud/data_coordinator.py +++ b/custom_components/midea_auto_cloud/data_coordinator.py @@ -193,6 +193,7 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]): async def async_set_attributes(self, attributes: dict) -> None: """Set multiple device attributes.""" # 云端控制:构造 control 与 status(携带当前状态作为上下文) + # 计算逻辑使用所有属性(包括有默认值的变量) for c in self.device._calculate_set: lvalue = c.get("lvalue") rvalue = c.get("rvalue") @@ -215,7 +216,18 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]): f"Calculation Error: {lvalue} = {rvalue}, calculate_str1: {calculate_str1}", self._device_id ) - await self.device.set_attributes(attributes) + + # 冻结有默认值的变量:从发送到云端的 attributes 中移除 + attributes_to_send = {} + for attr, value in attributes.items(): + # 如果该属性有默认值,则不发送到云端,只更新本地状态 + if attr not in self.device._default_values: + attributes_to_send[attr] = value + + # 只发送没有默认值的属性到云端 + if attributes_to_send: + await self.device.set_attributes(attributes_to_send) + # 更新所有属性到本地状态(包括有默认值的变量) self.device.attributes.update(attributes) self.mute_state_update_for_a_while() self.async_update_listeners() diff --git a/custom_components/midea_auto_cloud/device_mapping/T0xAC.py b/custom_components/midea_auto_cloud/device_mapping/T0xAC.py index 831f77d..1aadcfa 100644 --- a/custom_components/midea_auto_cloud/device_mapping/T0xAC.py +++ b/custom_components/midea_auto_cloud/device_mapping/T0xAC.py @@ -1128,9 +1128,17 @@ DEVICE_MAPPING = { }, ("22012369", "22040023", "22270043"): { "rationale": ["off", "on"], - "queries": [{}, {"query_type": "run_status"}, {"query_type": "indoor_temperature"}], - "centralized": ["power", "temperature", "mode", "eco", "comfort_power_save", - "wind_swing_lr", "wind_swing_ud", "wind_speed", "ptc", "dry"], + "queries": [{}], + "centralized": ["buzzer"], + "calculate":{ + "get": [ + { + "lvalue": "[screen_display]", + "rvalue": "[screen_display_now]" + }, + ], + "set": [] + }, "entities": { Platform.CLIMATE: { "thermostat": { @@ -1176,6 +1184,14 @@ DEVICE_MAPPING = { } }, Platform.SWITCH: { + "buzzer": { + "device_class": SwitchDeviceClass.SWITCH, + "default_value": "on", + }, + "screen_display": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "screen_close", + }, "dry": { "device_class": SwitchDeviceClass.SWITCH, }, @@ -1203,9 +1219,17 @@ DEVICE_MAPPING = { }, "22251077": { "rationale": ["off", "on"], - "queries": [{}, {"query_type": "run_status"}, {"query_type": "indoor_temperature"}], - "centralized": ["power", "temperature", "mode", "eco", "comfort_power_save", - "wind_swing_lr", "wind_swing_lr_under", "wind_swing_ud", "wind_speed", "ptc", "dry"], + "queries": [{}, {"query_type": "prevent_straight_wind"}], + "centralized": ["buzzer"], + "calculate":{ + "get": [ + { + "lvalue": "[screen_display]", + "rvalue": "[screen_display_now]" + }, + ], + "set": [] + }, "entities": { Platform.CLIMATE: { "thermostat": { @@ -1251,6 +1275,14 @@ DEVICE_MAPPING = { } }, Platform.SWITCH: { + "buzzer": { + "device_class": SwitchDeviceClass.SWITCH, + "default_value": "on", + }, + "screen_display": { + "device_class": SwitchDeviceClass.SWITCH, + "translation_key": "screen_close", + }, "dry": { "device_class": SwitchDeviceClass.SWITCH, },