forked from HomeAssistant/midea-meiju-codec
fix: cloud api loop error when device type not found.
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import base64
|
import base64
|
||||||
import voluptuous as vol
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from functools import partial
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.util.json import load_json
|
from homeassistant.util.json import load_json
|
||||||
|
|
||||||
@@ -14,7 +12,6 @@ from homeassistant.helpers.typing import ConfigType
|
|||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.core import (
|
from homeassistant.core import (
|
||||||
HomeAssistant,
|
HomeAssistant,
|
||||||
ServiceCall
|
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
Platform,
|
Platform,
|
||||||
@@ -97,26 +94,22 @@ async def load_device_config(hass: HomeAssistant, device_type, sn8):
|
|||||||
if any(k in raw for k in ["entities", "centralized", "queries", "manufacturer"]):
|
if any(k in raw for k in ["entities", "centralized", "queries", "manufacturer"]):
|
||||||
json_data = raw
|
json_data = raw
|
||||||
if not json_data:
|
if not json_data:
|
||||||
# 使用绝对路径并在执行器中导入,避免事件循环阻塞与相对导入触发包初始化循环
|
device_path = f".device_mapping.{'T0x%02X' % device_type}"
|
||||||
module_path = f"{__package__}.device_mapping.T0x{device_type:02X}"
|
|
||||||
try:
|
try:
|
||||||
mapping_module = await hass.async_add_executor_job(partial(import_module, module_path))
|
mapping_module = import_module(device_path, __package__)
|
||||||
|
MideaLogger.warning(f"device_path: % {device_path}")
|
||||||
|
MideaLogger.warning(f"mapping_module.DEVICE_MAPPING: % {mapping_module.DEVICE_MAPPING}")
|
||||||
|
if sn8 in mapping_module.DEVICE_MAPPING.keys():
|
||||||
|
json_data = mapping_module.DEVICE_MAPPING[sn8]
|
||||||
|
elif "default" in mapping_module.DEVICE_MAPPING:
|
||||||
|
json_data = mapping_module.DEVICE_MAPPING["default"]
|
||||||
|
MideaLogger.warning(f"json_data: % {json_data}")
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
mapping_module = None
|
MideaLogger.warning(f"Can't load mapping file for type {'T0x%02X' % device_type}")
|
||||||
MideaLogger.warning(f"Mapping module not found: {module_path}")
|
|
||||||
except Exception as e:
|
|
||||||
mapping_module = None
|
|
||||||
MideaLogger.warning(f"Import mapping module failed: {module_path}, err={e}")
|
|
||||||
|
|
||||||
if mapping_module and hasattr(mapping_module, "DEVICE_MAPPING"):
|
save_data = {sn8: json_data}
|
||||||
dm = getattr(mapping_module, "DEVICE_MAPPING") or {}
|
# offload save_json as well
|
||||||
if sn8 in dm.keys():
|
await hass.async_add_executor_job(save_json, config_file, save_data)
|
||||||
json_data = dm.get(sn8) or {}
|
|
||||||
elif "default" in dm:
|
|
||||||
json_data = dm.get("default") or {}
|
|
||||||
if len(json_data) > 0:
|
|
||||||
save_data = {sn8: json_data}
|
|
||||||
await hass.async_add_executor_job(save_json, config_file, save_data)
|
|
||||||
return json_data
|
return json_data
|
||||||
|
|
||||||
async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry):
|
async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry):
|
||||||
@@ -172,141 +165,136 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# 拉取家庭与设备列表
|
# 拉取家庭与设备列表
|
||||||
appliances = None
|
|
||||||
first_home_id = None
|
|
||||||
try:
|
try:
|
||||||
homes = await cloud.list_home()
|
homes = await cloud.list_home()
|
||||||
if homes and len(homes) > 0:
|
if homes and len(homes) > 0:
|
||||||
first_home_id = list(homes.keys())[0]
|
hass.data.setdefault(DOMAIN, {})
|
||||||
appliances = await cloud.list_appliances(first_home_id)
|
hass.data[DOMAIN].setdefault("accounts", {})
|
||||||
else:
|
bucket = {"device_list": {}, "coordinator_map": {}}
|
||||||
appliances = await cloud.list_appliances(None)
|
home_ids = list(homes.keys())
|
||||||
|
|
||||||
|
for home_id in home_ids:
|
||||||
|
appliances = await cloud.list_appliances(home_id)
|
||||||
|
if appliances is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 为每台设备构建占位设备与协调器(不连接本地)
|
||||||
|
for appliance_code, info in appliances.items():
|
||||||
|
MideaLogger.debug(f"info={info} ")
|
||||||
|
try:
|
||||||
|
device = MiedaDevice(
|
||||||
|
name=info.get(CONF_NAME) or info.get("name"),
|
||||||
|
device_id=appliance_code,
|
||||||
|
device_type=info.get(CONF_TYPE) or info.get("type"),
|
||||||
|
ip_address=None,
|
||||||
|
port=None,
|
||||||
|
token=None,
|
||||||
|
key=None,
|
||||||
|
connected=info.get("online"),
|
||||||
|
protocol=info.get(CONF_PROTOCOL) or 2,
|
||||||
|
model=info.get(CONF_MODEL),
|
||||||
|
subtype=info.get(CONF_MODEL_NUMBER),
|
||||||
|
sn=info.get(CONF_SN) or info.get("sn"),
|
||||||
|
sn8=info.get(CONF_SN8) or info.get("sn8"),
|
||||||
|
)
|
||||||
|
# 加载并应用设备映射(queries/centralized/calculate),并预置 attributes 键
|
||||||
|
try:
|
||||||
|
mapping = await load_device_config(
|
||||||
|
hass,
|
||||||
|
info.get(CONF_TYPE) or info.get("type"),
|
||||||
|
info.get(CONF_SN8) or info.get("sn8"),
|
||||||
|
) or {}
|
||||||
|
except Exception:
|
||||||
|
mapping = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
device.set_queries(mapping.get("queries", []))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
device.set_centralized(mapping.get("centralized", []))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
device.set_calculate(mapping.get("calculate", {}))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 预置 attributes:包含 centralized 里声明的所有键、entities 中使用到的所有属性键
|
||||||
|
try:
|
||||||
|
preset_keys = set(mapping.get("centralized", []))
|
||||||
|
entities_cfg = (mapping.get("entities") or {})
|
||||||
|
# 收集实体配置中直接引用的属性键
|
||||||
|
for platform_cfg in entities_cfg.values():
|
||||||
|
if not isinstance(platform_cfg, dict):
|
||||||
|
continue
|
||||||
|
for _, ecfg in platform_cfg.items():
|
||||||
|
if not isinstance(ecfg, dict):
|
||||||
|
continue
|
||||||
|
# 常见直接属性字段
|
||||||
|
for k in [
|
||||||
|
"power",
|
||||||
|
"aux_heat",
|
||||||
|
"current_temperature",
|
||||||
|
"target_temperature",
|
||||||
|
"oscillate",
|
||||||
|
"min_temp",
|
||||||
|
"max_temp",
|
||||||
|
]:
|
||||||
|
v = ecfg.get(k)
|
||||||
|
if isinstance(v, str):
|
||||||
|
preset_keys.add(v)
|
||||||
|
elif isinstance(v, list):
|
||||||
|
for vv in v:
|
||||||
|
if isinstance(vv, str):
|
||||||
|
preset_keys.add(vv)
|
||||||
|
# 模式映射里的条件字段
|
||||||
|
for map_key in [
|
||||||
|
"hvac_modes",
|
||||||
|
"preset_modes",
|
||||||
|
"swing_modes",
|
||||||
|
"fan_modes",
|
||||||
|
"operation_list",
|
||||||
|
"options",
|
||||||
|
]:
|
||||||
|
maps = ecfg.get(map_key) or {}
|
||||||
|
if isinstance(maps, dict):
|
||||||
|
for _, cond in maps.items():
|
||||||
|
if isinstance(cond, dict):
|
||||||
|
for attr_name in cond.keys():
|
||||||
|
preset_keys.add(attr_name)
|
||||||
|
# 传感器/开关等实体 key 本身也加入(其 key 即属性名)
|
||||||
|
for platform_name, platform_cfg in entities_cfg.items():
|
||||||
|
if not isinstance(platform_cfg, dict):
|
||||||
|
continue
|
||||||
|
platform_str = str(platform_name)
|
||||||
|
if platform_str in [
|
||||||
|
str(Platform.SENSOR),
|
||||||
|
str(Platform.BINARY_SENSOR),
|
||||||
|
str(Platform.SWITCH),
|
||||||
|
str(Platform.FAN),
|
||||||
|
str(Platform.SELECT),
|
||||||
|
]:
|
||||||
|
for entity_key in platform_cfg.keys():
|
||||||
|
preset_keys.add(entity_key)
|
||||||
|
# 写入默认空值
|
||||||
|
for k in preset_keys:
|
||||||
|
if k not in device.attributes:
|
||||||
|
device.attributes[k] = None
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
coordinator = MideaDataUpdateCoordinator(hass, config_entry, device, cloud=cloud)
|
||||||
|
# 后台刷新,避免初始化阻塞
|
||||||
|
hass.async_create_task(coordinator.async_config_entry_first_refresh())
|
||||||
|
bucket["device_list"][appliance_code] = info
|
||||||
|
bucket["coordinator_map"][appliance_code] = coordinator
|
||||||
|
except Exception as e:
|
||||||
|
MideaLogger.error(f"Init device failed: {appliance_code}, error: {e}")
|
||||||
|
hass.data[DOMAIN]["accounts"][config_entry.entry_id] = bucket
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
MideaLogger.error(f"Fetch appliances failed: {e}")
|
MideaLogger.error(f"Fetch appliances failed: {e}")
|
||||||
appliances = None
|
|
||||||
|
|
||||||
if appliances is None:
|
|
||||||
appliances = {}
|
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})
|
|
||||||
hass.data[DOMAIN].setdefault("accounts", {})
|
|
||||||
bucket = {"device_list": {}, "coordinator_map": {}, "cloud": cloud, "home_id": first_home_id}
|
|
||||||
|
|
||||||
# 为每台设备构建占位设备与协调器(不连接本地)
|
|
||||||
for appliance_code, info in appliances.items():
|
|
||||||
MideaLogger.debug(f"info={info} ")
|
|
||||||
try:
|
|
||||||
device = MiedaDevice(
|
|
||||||
name=info.get(CONF_NAME) or info.get("name"),
|
|
||||||
device_id=appliance_code,
|
|
||||||
device_type=info.get(CONF_TYPE) or info.get("type"),
|
|
||||||
ip_address=None,
|
|
||||||
port=None,
|
|
||||||
token=None,
|
|
||||||
key=None,
|
|
||||||
connected=info.get("online"),
|
|
||||||
protocol=info.get(CONF_PROTOCOL) or 2,
|
|
||||||
model=info.get(CONF_MODEL),
|
|
||||||
subtype=info.get(CONF_MODEL_NUMBER),
|
|
||||||
sn=info.get(CONF_SN) or info.get("sn"),
|
|
||||||
sn8=info.get(CONF_SN8) or info.get("sn8"),
|
|
||||||
)
|
|
||||||
# 加载并应用设备映射(queries/centralized/calculate),并预置 attributes 键
|
|
||||||
try:
|
|
||||||
mapping = await load_device_config(
|
|
||||||
hass,
|
|
||||||
info.get(CONF_TYPE) or info.get("type"),
|
|
||||||
info.get(CONF_SN8) or info.get("sn8"),
|
|
||||||
) or {}
|
|
||||||
except Exception:
|
|
||||||
mapping = {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
device.set_queries(mapping.get("queries", []))
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
device.set_centralized(mapping.get("centralized", []))
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
device.set_calculate(mapping.get("calculate", {}))
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 预置 attributes:包含 centralized 里声明的所有键、entities 中使用到的所有属性键
|
|
||||||
try:
|
|
||||||
preset_keys = set(mapping.get("centralized", []))
|
|
||||||
entities_cfg = (mapping.get("entities") or {})
|
|
||||||
# 收集实体配置中直接引用的属性键
|
|
||||||
for platform_cfg in entities_cfg.values():
|
|
||||||
if not isinstance(platform_cfg, dict):
|
|
||||||
continue
|
|
||||||
for _, ecfg in platform_cfg.items():
|
|
||||||
if not isinstance(ecfg, dict):
|
|
||||||
continue
|
|
||||||
# 常见直接属性字段
|
|
||||||
for k in [
|
|
||||||
"power",
|
|
||||||
"aux_heat",
|
|
||||||
"current_temperature",
|
|
||||||
"target_temperature",
|
|
||||||
"oscillate",
|
|
||||||
"min_temp",
|
|
||||||
"max_temp",
|
|
||||||
]:
|
|
||||||
v = ecfg.get(k)
|
|
||||||
if isinstance(v, str):
|
|
||||||
preset_keys.add(v)
|
|
||||||
elif isinstance(v, list):
|
|
||||||
for vv in v:
|
|
||||||
if isinstance(vv, str):
|
|
||||||
preset_keys.add(vv)
|
|
||||||
# 模式映射里的条件字段
|
|
||||||
for map_key in [
|
|
||||||
"hvac_modes",
|
|
||||||
"preset_modes",
|
|
||||||
"swing_modes",
|
|
||||||
"fan_modes",
|
|
||||||
"operation_list",
|
|
||||||
"options",
|
|
||||||
]:
|
|
||||||
maps = ecfg.get(map_key) or {}
|
|
||||||
if isinstance(maps, dict):
|
|
||||||
for _, cond in maps.items():
|
|
||||||
if isinstance(cond, dict):
|
|
||||||
for attr_name in cond.keys():
|
|
||||||
preset_keys.add(attr_name)
|
|
||||||
# 传感器/开关等实体 key 本身也加入(其 key 即属性名)
|
|
||||||
for platform_name, platform_cfg in entities_cfg.items():
|
|
||||||
if not isinstance(platform_cfg, dict):
|
|
||||||
continue
|
|
||||||
platform_str = str(platform_name)
|
|
||||||
if platform_str in [
|
|
||||||
str(Platform.SENSOR),
|
|
||||||
str(Platform.BINARY_SENSOR),
|
|
||||||
str(Platform.SWITCH),
|
|
||||||
str(Platform.FAN),
|
|
||||||
str(Platform.SELECT),
|
|
||||||
]:
|
|
||||||
for entity_key in platform_cfg.keys():
|
|
||||||
preset_keys.add(entity_key)
|
|
||||||
# 写入默认空值
|
|
||||||
for k in preset_keys:
|
|
||||||
if k not in device.attributes:
|
|
||||||
device.attributes[k] = None
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
coordinator = MideaDataUpdateCoordinator(hass, config_entry, device)
|
|
||||||
await coordinator.async_config_entry_first_refresh()
|
|
||||||
bucket["device_list"][appliance_code] = info
|
|
||||||
bucket["coordinator_map"][appliance_code] = coordinator
|
|
||||||
except Exception as e:
|
|
||||||
MideaLogger.error(f"Init device failed: {appliance_code}, error: {e}")
|
|
||||||
|
|
||||||
hass.data[DOMAIN]["accounts"][config_entry.entry_id] = bucket
|
|
||||||
|
|
||||||
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@@ -3,9 +3,9 @@ import time
|
|||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import base64
|
import base64
|
||||||
from threading import Lock
|
|
||||||
from aiohttp import ClientSession
|
from aiohttp import ClientSession
|
||||||
from secrets import token_hex
|
from secrets import token_hex
|
||||||
|
from .logger import MideaLogger
|
||||||
from .security import CloudSecurity, MeijuCloudSecurity, MSmartCloudSecurity
|
from .security import CloudSecurity, MeijuCloudSecurity, MSmartCloudSecurity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -50,7 +50,6 @@ class MideaCloud:
|
|||||||
self._device_id = CloudSecurity.get_deviceid(account)
|
self._device_id = CloudSecurity.get_deviceid(account)
|
||||||
self._session = session
|
self._session = session
|
||||||
self._security = security
|
self._security = security
|
||||||
self._api_lock = Lock()
|
|
||||||
self._app_key = app_key
|
self._app_key = app_key
|
||||||
self._account = account
|
self._account = account
|
||||||
self._password = password
|
self._password = password
|
||||||
@@ -86,16 +85,15 @@ class MideaCloud:
|
|||||||
"accesstoken": self._access_token
|
"accesstoken": self._access_token
|
||||||
})
|
})
|
||||||
response:dict = {"code": -1}
|
response:dict = {"code": -1}
|
||||||
for i in range(0, 3):
|
_LOGGER.debug(f"Midea cloud API header: {header}")
|
||||||
try:
|
_LOGGER.debug(f"Midea cloud API dump_data: {dump_data}")
|
||||||
with self._api_lock:
|
try:
|
||||||
r = await self._session.request("POST", url, headers=header, data=dump_data, timeout=10)
|
r = await self._session.request("POST", url, headers=header, data=dump_data, timeout=5)
|
||||||
raw = await r.read()
|
raw = await r.read()
|
||||||
_LOGGER.debug(f"Midea cloud API url: {url}, data: {data}, response: {raw}")
|
_LOGGER.debug(f"Midea cloud API url: {url}, data: {data}, response: {raw}")
|
||||||
response = json.loads(raw)
|
response = json.loads(raw)
|
||||||
break
|
except Exception as e:
|
||||||
except Exception as e:
|
_LOGGER.debug(f"API request attempt failed: {e}")
|
||||||
pass
|
|
||||||
|
|
||||||
if int(response["code"]) == 0 and "data" in response:
|
if int(response["code"]) == 0 and "data" in response:
|
||||||
return response["data"]
|
return response["data"]
|
||||||
@@ -251,7 +249,7 @@ class MeijuCloud(MideaCloud):
|
|||||||
"sn": self._security.aes_decrypt(appliance.get("sn")) if appliance.get("sn") else "",
|
"sn": self._security.aes_decrypt(appliance.get("sn")) if appliance.get("sn") else "",
|
||||||
"sn8": appliance.get("sn8", "00000000"),
|
"sn8": appliance.get("sn8", "00000000"),
|
||||||
"model_number": appliance.get("modelNumber", "0"),
|
"model_number": appliance.get("modelNumber", "0"),
|
||||||
"manufacturer_code":appliance.get("enterpriseCode", "0000"),
|
"manufacturer_code": appliance.get("enterpriseCode", "0000"),
|
||||||
"model": appliance.get("productModel"),
|
"model": appliance.get("productModel"),
|
||||||
"online": appliance.get("onlineStatus") == "1",
|
"online": appliance.get("onlineStatus") == "1",
|
||||||
}
|
}
|
||||||
@@ -267,9 +265,10 @@ class MeijuCloud(MideaCloud):
|
|||||||
data = {
|
data = {
|
||||||
"applianceCode": str(appliance_code),
|
"applianceCode": str(appliance_code),
|
||||||
"command": {
|
"command": {
|
||||||
"query": {"query_type": "total_query"}
|
"query": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MideaLogger.error(f"get_device_status: {data}")
|
||||||
if response := await self._api_request(
|
if response := await self._api_request(
|
||||||
endpoint="/mjl/v1/device/status/lua/get",
|
endpoint="/mjl/v1/device/status/lua/get",
|
||||||
data=data
|
data=data
|
||||||
|
@@ -10,7 +10,6 @@ from homeassistant.helpers.event import async_call_later
|
|||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from .core.device import MiedaDevice
|
from .core.device import MiedaDevice
|
||||||
from .const import DOMAIN
|
|
||||||
from .core.logger import MideaLogger
|
from .core.logger import MideaLogger
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -31,6 +30,7 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
device: MiedaDevice,
|
device: MiedaDevice,
|
||||||
|
cloud=None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the coordinator."""
|
"""Initialize the coordinator."""
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@@ -45,6 +45,7 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
|
|||||||
self.device = device
|
self.device = device
|
||||||
self.state_update_muted: CALLBACK_TYPE | None = None
|
self.state_update_muted: CALLBACK_TYPE | None = None
|
||||||
self._device_id = device.device_id
|
self._device_id = device.device_id
|
||||||
|
self._cloud = cloud
|
||||||
|
|
||||||
async def _async_setup(self) -> None:
|
async def _async_setup(self) -> None:
|
||||||
"""Set up the coordinator."""
|
"""Set up the coordinator."""
|
||||||
@@ -89,9 +90,8 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
|
|||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 尝试账号模式下的云端轮询(如果 cloud 存在且支持)
|
# 使用传入的 cloud 实例(若可用)
|
||||||
account_bucket = self.hass.data.get(DOMAIN, {}).get("accounts", {}).get(self.config_entry.entry_id)
|
cloud = self._cloud
|
||||||
cloud = account_bucket.get("cloud") if account_bucket else None
|
|
||||||
if cloud and hasattr(cloud, "get_device_status"):
|
if cloud and hasattr(cloud, "get_device_status"):
|
||||||
try:
|
try:
|
||||||
status = await cloud.get_device_status(self._device_id)
|
status = await cloud.get_device_status(self._device_id)
|
||||||
@@ -120,8 +120,7 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
|
|||||||
async def async_set_attribute(self, attribute: str, value) -> None:
|
async def async_set_attribute(self, attribute: str, value) -> None:
|
||||||
"""Set a device attribute."""
|
"""Set a device attribute."""
|
||||||
# 云端控制:构造 control 与 status(携带当前状态作为上下文)
|
# 云端控制:构造 control 与 status(携带当前状态作为上下文)
|
||||||
account_bucket = self.hass.data.get(DOMAIN, {}).get("accounts", {}).get(self.config_entry.entry_id)
|
cloud = self._cloud
|
||||||
cloud = account_bucket.get("cloud") if account_bucket else None
|
|
||||||
control = {attribute: value}
|
control = {attribute: value}
|
||||||
status = dict(self.device.attributes)
|
status = dict(self.device.attributes)
|
||||||
if cloud and hasattr(cloud, "send_device_control"):
|
if cloud and hasattr(cloud, "send_device_control"):
|
||||||
@@ -134,8 +133,7 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
|
|||||||
|
|
||||||
async def async_set_attributes(self, attributes: dict) -> None:
|
async def async_set_attributes(self, attributes: dict) -> None:
|
||||||
"""Set multiple device attributes."""
|
"""Set multiple device attributes."""
|
||||||
account_bucket = self.hass.data.get(DOMAIN, {}).get("accounts", {}).get(self.config_entry.entry_id)
|
cloud = self._cloud
|
||||||
cloud = account_bucket.get("cloud") if account_bucket else None
|
|
||||||
control = dict(attributes)
|
control = dict(attributes)
|
||||||
status = dict(self.device.attributes)
|
status = dict(self.device.attributes)
|
||||||
if cloud and hasattr(cloud, "send_device_control"):
|
if cloud and hasattr(cloud, "send_device_control"):
|
||||||
|
Reference in New Issue
Block a user