11 Commits

Author SHA1 Message Date
sususweet
b6e7bcb729 fix: T0xCA translation issues. 2025-09-25 11:55:06 +08:00
sususweet
c12158cd09 fix: translation and unit issues. 2025-09-25 11:45:46 +08:00
sususweet
40ba24c32a feat: support more devices. 2025-09-25 10:50:39 +08:00
sususweet
f99019bdca feat: support more devices. 2025-09-24 23:31:31 +08:00
sususweet
2af99c11da feat: update readme 2025-09-24 20:59:17 +08:00
sususweet
b1bf76f292 feat: refactor code to add more devices. 2025-09-24 20:56:04 +08:00
sususweet
51f0fcc8dc feat: refactor code to add more attributes. 2025-09-24 19:57:11 +08:00
sususweet
39f88365e5 feat: add more device support 2025-09-24 18:20:58 +08:00
sususweet
2f88658fda fix: cloud api loop error when device type not found. 2025-09-24 16:32:23 +08:00
sususweet
a9e2b784b5 fix: loop error when device type not found. 2025-09-24 11:41:11 +08:00
sususweet
9141ae2758 Update readme 2025-09-17 23:31:27 +08:00
35 changed files with 5884 additions and 410 deletions

View File

@@ -14,6 +14,33 @@
- 所有设备默认可生成一个名为Status的二进制传感器其属性中列出了设备可访问的所有属性当然有些值不可设置
- Status实体前几项列出了该设备的分类信息供参考
## 目前支持的设备类型
- T0xAC 空调
- T0xB3 消毒碗柜
- T0xB8 智能扫地机器人
- T0xCA 对开门冰箱
- T0xCE 新风机
- T0xCF 中央空调暖家
- T0xD9 复式洗衣机
- T0xDB 滚筒洗衣机
- T0xDC 干衣机
- T0xE1 洗碗机
- T0xE3 恒温式燃气热水器
- T0xEA 电饭锅
- T0xED 软水机
- T0xFD 加湿器
欢迎合作开发添加更多设备支持。
合作开发方法:添加本插件后,找到未能正确识别的设备,点击对应设备`传感器`分类下的`连通性`
![img.png](img.png)
展开下面的`属性`卡片把里面这些字段复制给我或随issue提交等待适配就可以了。
![img_1.png](img_1.png)
## 实体映射
映射文件位于`device_mapping`下, 每个大的品类一个映射文件,目前支持映射的实体类型如下:

View File

@@ -1,6 +1,5 @@
import os
import base64
import voluptuous as vol
from importlib import import_module
from homeassistant.config_entries import ConfigEntry
from homeassistant.util.json import load_json
@@ -13,7 +12,6 @@ from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.core import (
HomeAssistant,
ServiceCall
)
from homeassistant.const import (
Platform,
@@ -50,12 +48,13 @@ from .const import CONF_PASSWORD as CONF_PASSWORD_KEY, CONF_SERVER as CONF_SERVE
PLATFORMS: list[Platform] = [
Platform.BINARY_SENSOR,
# Platform.SENSOR,
# Platform.SWITCH,
Platform.SENSOR,
Platform.SWITCH,
Platform.CLIMATE,
Platform.SELECT,
Platform.WATER_HEATER,
Platform.FAN
Platform.FAN,
Platform.HUMIDIFIER
]
@@ -85,16 +84,16 @@ async def load_device_config(hass: HomeAssistant, device_type, sn8):
config_file = hass.config.path(f"{CONFIG_PATH}/{sn8}.json")
raw = await hass.async_add_executor_job(_ensure_dir_and_load, config_dir, config_file)
json_data = {}
if isinstance(raw, dict) and len(raw) > 0:
# 兼容两种文件结构:
# 1) { "<sn8>": { ...mapping... } }
# 2) { ...mapping... }(直接就是映射体)
if sn8 in raw:
json_data = raw.get(sn8) or {}
else:
# 如果像映射体(包含 entities/centralized 等关键字段),直接使用
if any(k in raw for k in ["entities", "centralized", "queries", "manufacturer"]):
json_data = raw
# if isinstance(raw, dict) and len(raw) > 0:
# # 兼容两种文件结构:
# # 1) { "<sn8>": { ...mapping... } }
# # 2) { ...mapping... }(直接就是映射体)
# if sn8 in raw:
# json_data = raw.get(sn8) or {}
# else:
# # 如果像映射体(包含 entities/centralized 等关键字段),直接使用
# if any(k in raw for k in ["entities", "centralized", "queries", "manufacturer"]):
# json_data = raw
if not json_data:
device_path = f".device_mapping.{'T0x%02X' % device_type}"
try:
@@ -103,12 +102,12 @@ async def load_device_config(hass: HomeAssistant, device_type, sn8):
json_data = mapping_module.DEVICE_MAPPING[sn8]
elif "default" in mapping_module.DEVICE_MAPPING:
json_data = mapping_module.DEVICE_MAPPING["default"]
if len(json_data) > 0:
save_data = {sn8: json_data}
# offload save_json as well
await hass.async_add_executor_job(save_json, config_file, save_data)
except ModuleNotFoundError:
MideaLogger.warning(f"Can't load mapping file for type {'T0x%02X' % device_type}")
save_data = {sn8: json_data}
# offload save_json as well
await hass.async_add_executor_job(save_json, config_file, save_data)
return json_data
async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry):
@@ -164,142 +163,137 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):
return False
# 拉取家庭与设备列表
appliances = None
first_home_id = None
try:
homes = await cloud.list_home()
if homes and len(homes) > 0:
first_home_id = list(homes.keys())[0]
appliances = await cloud.list_appliances(first_home_id)
else:
appliances = await cloud.list_appliances(None)
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN].setdefault("accounts", {})
bucket = {"device_list": {}, "coordinator_map": {}}
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:
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
hass.async_create_task(hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS))
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
return True

View File

@@ -57,18 +57,17 @@ class MideaDeviceStatusSensorEntity(MideaEntity, BinarySensorEntity):
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._entity_key = entity_key
self._config = config
@property
def entity_id_suffix(self) -> str:
"""Return the suffix for entity ID."""
return "status"
@property
def device_class(self):
"""Return the device class."""
@@ -102,6 +101,11 @@ class MideaBinarySensorEntity(MideaEntity, BinarySensorEntity):
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
@@ -109,11 +113,6 @@ class MideaBinarySensorEntity(MideaEntity, BinarySensorEntity):
self._entity_key = entity_key
self._config = config
@property
def entity_id_suffix(self) -> str:
"""Return the suffix for entity ID."""
return f"binary_sensor_{self._entity_key}"
@property
def is_on(self):
"""Return if the binary sensor is on."""

View File

@@ -15,7 +15,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .core.logger import MideaLogger
from .midea_entity import MideaEntity
from .midea_entities import Rationale
from . import load_device_config
@@ -44,9 +43,6 @@ async def async_setup_entry(
coordinator = coordinator_map.get(device_id)
device = coordinator.device if coordinator else None
MideaLogger.debug(f"entities_cfg={entities_cfg} ")
for entity_key, ecfg in entities_cfg.items():
devs.append(MideaClimateEntity(
coordinator, device, manufacturer, rationale, entity_key, ecfg
@@ -64,11 +60,15 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._entity_key = entity_key
self._config = config
self._key_power = self._config.get("power")
self._key_hvac_modes = self._config.get("hvac_modes")
@@ -100,7 +100,13 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
@property
def current_temperature(self):
return self.device_attributes.get(self._key_current_temperature)
temp = self.device_attributes.get(self._key_current_temperature)
if temp is not None:
try:
return float(temp)
except (ValueError, TypeError):
return None
return None
@property
def target_temperature(self):
@@ -108,10 +114,19 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
temp_int = self.device_attributes.get(self._key_target_temperature[0])
tem_dec = self.device_attributes.get(self._key_target_temperature[1])
if temp_int is not None and tem_dec is not None:
return temp_int + tem_dec
try:
return float(temp_int) + float(tem_dec)
except (ValueError, TypeError):
return None
return None
else:
return self.device_attributes.get(self._key_target_temperature)
temp = self.device_attributes.get(self._key_target_temperature)
if temp is not None:
try:
return float(temp)
except (ValueError, TypeError):
return None
return None
@property
def min_temp(self):
@@ -149,7 +164,7 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
@property
def fan_mode(self):
return self._dict_get_selected(self._key_fan_modes, Rationale.EQUALLY)
return self._dict_get_selected(self._key_fan_modes, "EQUALLY")
@property
def swing_modes(self):
@@ -157,7 +172,7 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
@property
def swing_mode(self):
return self._dict_get_selected(self._key_swing_modes)
return self._dict_get_selected(self._key_swing_modes, "EQUALLY")
@property
def is_on(self) -> bool:
@@ -165,7 +180,7 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
@property
def hvac_mode(self):
return self._dict_get_selected(self._key_hvac_modes)
return self._dict_get_selected(self._key_hvac_modes, "EQUALLY")
@property
def hvac_modes(self):
@@ -236,7 +251,7 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
return
await self.async_set_attribute(key, value)
def _dict_get_selected(self, dict_config, rationale=Rationale.EQUALLY):
def _dict_get_selected(self, dict_config, rationale="EQUALLY"):
"""Get selected value from dictionary configuration."""
if dict_config is None:
return None
@@ -251,15 +266,15 @@ class MideaClimateEntity(MideaEntity, ClimateEntity):
if device_value is None:
match = False
break
if rationale == Rationale.EQUALLY:
if rationale == "EQUALLY":
if device_value != attr_value:
match = False
break
elif rationale == Rationale.LESS:
elif rationale == "LESS":
if device_value >= attr_value:
match = False
break
elif rationale == Rationale.GREATER:
elif rationale == "GREATER":
if device_value <= attr_value:
match = False
break

View File

@@ -60,7 +60,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
data_schema=vol.Schema({
vol.Required(CONF_ACCOUNT): str,
vol.Required(CONF_PASSWORD): str,
vol.Required(CONF_SERVER, default=1): vol.In(CONF_SERVERS)
vol.Required(CONF_SERVER, default=2): vol.In(CONF_SERVERS)
}),
errors=errors,
)

View File

@@ -3,9 +3,9 @@ import time
import datetime
import json
import base64
from threading import Lock
from aiohttp import ClientSession
from secrets import token_hex
from .logger import MideaLogger
from .security import CloudSecurity, MeijuCloudSecurity, MSmartCloudSecurity
_LOGGER = logging.getLogger(__name__)
@@ -50,7 +50,6 @@ class MideaCloud:
self._device_id = CloudSecurity.get_deviceid(account)
self._session = session
self._security = security
self._api_lock = Lock()
self._app_key = app_key
self._account = account
self._password = password
@@ -86,16 +85,15 @@ class MideaCloud:
"accesstoken": self._access_token
})
response:dict = {"code": -1}
for i in range(0, 3):
try:
with self._api_lock:
r = await self._session.request("POST", url, headers=header, data=dump_data, timeout=10)
raw = await r.read()
_LOGGER.debug(f"Midea cloud API url: {url}, data: {data}, response: {raw}")
response = json.loads(raw)
break
except Exception as e:
pass
_LOGGER.debug(f"Midea cloud API header: {header}")
_LOGGER.debug(f"Midea cloud API dump_data: {dump_data}")
try:
r = await self._session.request("POST", url, headers=header, data=dump_data, timeout=5)
raw = await r.read()
_LOGGER.debug(f"Midea cloud API url: {url}, data: {data}, response: {raw}")
response = json.loads(raw)
except Exception as e:
_LOGGER.debug(f"API request attempt failed: {e}")
if int(response["code"]) == 0 and "data" in response:
return response["data"]
@@ -251,7 +249,7 @@ class MeijuCloud(MideaCloud):
"sn": self._security.aes_decrypt(appliance.get("sn")) if appliance.get("sn") else "",
"sn8": appliance.get("sn8", "00000000"),
"model_number": appliance.get("modelNumber", "0"),
"manufacturer_code":appliance.get("enterpriseCode", "0000"),
"manufacturer_code": appliance.get("enterpriseCode", "0000"),
"model": appliance.get("productModel"),
"online": appliance.get("onlineStatus") == "1",
}
@@ -267,7 +265,7 @@ class MeijuCloud(MideaCloud):
data = {
"applianceCode": str(appliance_code),
"command": {
"query": {"query_type": "total_query"}
"query": {}
}
}
if response := await self._api_request(

View File

@@ -1,4 +1,4 @@
"""Data coordinator for Midea Auto Codec integration."""
"""Data coordinator for Midea Auto Cloud integration."""
import logging
from datetime import datetime, timedelta
@@ -10,7 +10,6 @@ from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .core.device import MiedaDevice
from .const import DOMAIN
from .core.logger import MideaLogger
_LOGGER = logging.getLogger(__name__)
@@ -31,6 +30,7 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
hass: HomeAssistant,
config_entry: ConfigEntry,
device: MiedaDevice,
cloud=None,
) -> None:
"""Initialize the coordinator."""
super().__init__(
@@ -45,6 +45,7 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
self.device = device
self.state_update_muted: CALLBACK_TYPE | None = None
self._device_id = device.device_id
self._cloud = cloud
async def _async_setup(self) -> None:
"""Set up the coordinator."""
@@ -89,9 +90,8 @@ class MideaDataUpdateCoordinator(DataUpdateCoordinator[MideaDeviceData]):
return self.data
try:
# 尝试账号模式下的云端轮询(如果 cloud 存在且支持
account_bucket = self.hass.data.get(DOMAIN, {}).get("accounts", {}).get(self.config_entry.entry_id)
cloud = account_bucket.get("cloud") if account_bucket else None
# 使用传入的 cloud 实例(若可用
cloud = self._cloud
if cloud and hasattr(cloud, "get_device_status"):
try:
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:
"""Set a device attribute."""
# 云端控制:构造 control 与 status携带当前状态作为上下文
account_bucket = self.hass.data.get(DOMAIN, {}).get("accounts", {}).get(self.config_entry.entry_id)
cloud = account_bucket.get("cloud") if account_bucket else None
cloud = self._cloud
control = {attribute: value}
status = dict(self.device.attributes)
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:
"""Set multiple device attributes."""
account_bucket = self.hass.data.get(DOMAIN, {}).get("accounts", {}).get(self.config_entry.entry_id)
cloud = account_bucket.get("cloud") if account_bucket else None
cloud = self._cloud
control = dict(attributes)
status = dict(self.device.attributes)
if cloud and hasattr(cloud, "send_device_control"):

View File

@@ -15,7 +15,6 @@ DEVICE_MAPPING = {
"entities": {
Platform.CLIMATE: {
"thermostat": {
"name": "Thermostat",
"power": "power",
"hvac_modes": {
"off": {"power": "off"},
@@ -96,7 +95,6 @@ DEVICE_MAPPING = {
"entities": {
Platform.CLIMATE: {
"thermostat": {
"name": "Thermostat",
"power": "power",
"hvac_modes": {
"off": {"power": "off"},

View File

@@ -0,0 +1,195 @@
from homeassistant.const import Platform, UnitOfTemperature, UnitOfTime
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [
"upstair_work_status", "downstair_work_status", "middlestair_work_status",
"upstair_mode", "downstair_mode", "middlestair_mode",
"upstair_temp", "downstair_temp", "middlestair_temp"
],
"entities": {
Platform.BINARY_SENSOR: {
"door_middlestair": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"door_upstair": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"door_downstair": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"downstair_ispreheat": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"upstair_ispreheat": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"downstair_iscooling": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"upstair_iscooling": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"middlestair_ispreheat": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"middlestair_iscooling": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"lock": {
"device_class": BinarySensorDeviceClass.LOCK,
},
"is_error": {
"device_class": BinarySensorDeviceClass.PROBLEM,
},
"uv_disinfect": {
"device_class": BinarySensorDeviceClass.RUNNING,
}
},
Platform.SELECT: {
"upstair_work_status": {
"options": {
"power_off": {"upstair_work_status": "power_off"},
"power_on": {"upstair_work_status": "power_on"},
"working": {"upstair_work_status": "working"},
"pause": {"upstair_work_status": "pause"},
"finish": {"upstair_work_status": "finish"},
"error": {"upstair_work_status": "error"}
}
},
"downstair_work_status": {
"options": {
"power_off": {"downstair_work_status": "power_off"},
"power_on": {"downstair_work_status": "power_on"},
"working": {"downstair_work_status": "working"},
"pause": {"downstair_work_status": "pause"},
"finish": {"downstair_work_status": "finish"},
"error": {"downstair_work_status": "error"}
}
},
"middlestair_work_status": {
"options": {
"power_off": {"middlestair_work_status": "power_off"},
"power_on": {"middlestair_work_status": "power_on"},
"working": {"middlestair_work_status": "working"},
"pause": {"middlestair_work_status": "pause"},
"finish": {"middlestair_work_status": "finish"},
"error": {"middlestair_work_status": "error"}
}
},
"upstair_mode": {
"options": {
"off": {"upstair_mode": "0"},
"bake": {"upstair_mode": "1"},
"roast": {"upstair_mode": "2"},
"grill": {"upstair_mode": "3"},
"convection": {"upstair_mode": "4"},
"defrost": {"upstair_mode": "5"}
}
},
"downstair_mode": {
"options": {
"off": {"downstair_mode": "0"},
"bake": {"downstair_mode": "1"},
"roast": {"downstair_mode": "2"},
"grill": {"downstair_mode": "3"},
"convection": {"downstair_mode": "4"},
"defrost": {"downstair_mode": "5"}
}
},
"middlestair_mode": {
"options": {
"off": {"middlestair_mode": "0"},
"bake": {"middlestair_mode": "1"},
"roast": {"middlestair_mode": "2"},
"grill": {"middlestair_mode": "3"},
"convection": {"middlestair_mode": "4"},
"defrost": {"middlestair_mode": "5"}
}
}
},
Platform.SENSOR: {
"upstair_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"downstair_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"middlestair_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"upstair_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"upstair_min": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"upstair_sec": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.SECONDS,
"state_class": SensorStateClass.MEASUREMENT
},
"middlestair_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"middlestair_min": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"middlestair_sec": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.SECONDS,
"state_class": SensorStateClass.MEASUREMENT
},
"downstair_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"downstair_min": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"downstair_sec": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.SECONDS,
"state_class": SensorStateClass.MEASUREMENT
},
"order_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"order_min": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"order_sec": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.SECONDS,
"state_class": SensorStateClass.MEASUREMENT
}
}
}
}
}

View File

@@ -0,0 +1,153 @@
from homeassistant.const import Platform, UnitOfTemperature, PRECISION_HALVES, UnitOfTime, UnitOfArea, UnitOfVolume
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [],
"entities": {
Platform.SELECT: {
"fan_level": {
"options": {
"low": {"fan_level": "low"},
"medium": {"fan_level": "medium"},
"high": {"fan_level": "high"},
"auto": {"fan_level": "auto"}
}
},
"work_mode": {
"options": {
"none": {"work_mode": "none"},
"auto": {"work_mode": "auto"},
"spot": {"work_mode": "spot"},
"edge": {"work_mode": "edge"},
"single_room": {"work_mode": "single_room"},
"custom": {"work_mode": "custom"}
}
},
"work_status": {
"options": {
"idle": {"work_status": "idle"},
"cleaning": {"work_status": "cleaning"},
"returning": {"work_status": "returning"},
"docked": {"work_status": "docked"},
"on_base": {"work_status": "on_base"},
"charging": {"work_status": "charging"},
"error": {"work_status": "error"}
}
},
"move_direction": {
"options": {
"none": {"move_direction": "none"},
"forward": {"move_direction": "forward"},
"backward": {"move_direction": "backward"},
"left": {"move_direction": "left"},
"right": {"move_direction": "right"}
}
},
"query_type": {
"options": {
"work": {"query_type": "work"},
"status": {"query_type": "status"},
"battery": {"query_type": "battery"},
"error": {"query_type": "error"}
}
},
"sub_work_status": {
"options": {
"idle": {"sub_work_status": "idle"},
"cleaning": {"sub_work_status": "cleaning"},
"charging": {"sub_work_status": "charging"},
"charge_finish": {"sub_work_status": "charge_finish"},
"error": {"sub_work_status": "error"}
}
},
"water_level": {
"options": {
"low": {"water_level": "low"},
"normal": {"water_level": "normal"},
"high": {"water_level": "high"}
}
},
"mop_status": {
"options": {
"normal": {"mop_status": "normal"},
"lack_water": {"mop_status": "lack_water"},
"full_water": {"mop_status": "full_water"}
}
},
"error_type": {
"options": {
"no_error": {"error_type": "no_error"},
"can_fix": {"error_type": "can_fix"},
"need_help": {"error_type": "need_help"}
}
},
"control_type": {
"options": {
"none": {"control_type": "none"},
"app": {"control_type": "app"},
"remote": {"control_type": "remote"},
"auto": {"control_type": "auto"}
}
}
},
Platform.BINARY_SENSOR: {
"carpet_switch": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"have_reserve_task": {
"device_class": BinarySensorDeviceClass.RUNNING,
}
},
Platform.SENSOR: {
"dust_count": {
"device_class": SensorDeviceClass.ENUM
},
"area": {
"device_class": SensorDeviceClass.AREA,
"unit_of_measurement": UnitOfArea.SQUARE_METERS,
"state_class": SensorStateClass.MEASUREMENT
},
"voice_level": {
"device_class": SensorDeviceClass.BATTERY,
"unit_of_measurement": "%",
"state_class": SensorStateClass.MEASUREMENT
},
"switch_status": {
"device_class": SensorDeviceClass.ENUM
},
"water_station_status": {
"device_class": SensorDeviceClass.ENUM
},
"work_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"battery_percent": {
"device_class": SensorDeviceClass.BATTERY,
"unit_of_measurement": "%",
"state_class": SensorStateClass.MEASUREMENT
},
"planner_status": {
"device_class": SensorDeviceClass.ENUM
},
"sweep_then_mop_mode_progress": {
"device_class": SensorDeviceClass.BATTERY,
"unit_of_measurement": "%",
"state_class": SensorStateClass.MEASUREMENT
},
"error_desc": {
"device_class": SensorDeviceClass.ENUM
},
"station_error_desc": {
"device_class": SensorDeviceClass.ENUM
}
}
}
}
}

View File

@@ -0,0 +1,309 @@
from homeassistant.const import Platform, UnitOfTemperature, UnitOfTime, PERCENTAGE, PRECISION_HALVES
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [
"freezing_mode", "intelligent_mode", "energy_saving_mode", "holiday_mode",
"moisturize_mode", "preservation_mode", "acme_freezing_mode", "variable_mode",
"storage_power", "left_flexzone_power", "right_flexzone_power", "freezing_power",
"function_zone_power", "storage_temperature", "freezing_temperature",
"left_flexzone_temperature", "right_flexzone_temperature"
],
"entities": {
Platform.SWITCH: {
"freezing_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"intelligent_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"energy_saving_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"holiday_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"moisturize_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"preservation_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"acme_freezing_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"storage_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"left_flexzone_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"right_flexzone_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"freezing_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"function_zone_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cross_peak_electricity": {
"device_class": SwitchDeviceClass.SWITCH,
},
"all_refrigeration_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"remove_dew_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"humidify_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"unfreeze_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"floodlight_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"radar_mode_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"milk_mode_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"icea_mode_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"plasma_aseptic_mode_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"acquire_icea_mode_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"brash_icea_mode_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"acquire_water_mode_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"freezing_ice_machine_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"microcrystal_fresh": {
"device_class": SwitchDeviceClass.SWITCH,
},
"dry_zone": {
"device_class": SwitchDeviceClass.SWITCH,
},
"electronic_smell": {
"device_class": SwitchDeviceClass.SWITCH,
},
"eradicate_pesticide_residue": {
"device_class": SwitchDeviceClass.SWITCH,
},
"performance_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"ice_mouth_power": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.BINARY_SENSOR: {
"storage_door_state": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"freezer_door_state": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"flexzone_door_state": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"storage_ice_home_door_state": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"bar_door_state": {
"device_class": BinarySensorDeviceClass.DOOR,
},
"is_error": {
"device_class": BinarySensorDeviceClass.PROBLEM,
}
},
Platform.CLIMATE: {
"storage_zone": {
"power": "storage_power",
"hvac_modes": {
"off": {"storage_power": "off"},
"heat": {"storage_power": "on"}
},
"target_temperature": "storage_temperature",
"current_temperature": "refrigeration_real_temperature",
"min_temp": -10,
"max_temp": 10,
"temperature_unit": UnitOfTemperature.CELSIUS,
"precision": PRECISION_HALVES,
},
"freezing_zone": {
"power": "freezing_power",
"hvac_modes": {
"off": {"freezing_power": "off"},
"heat": {"freezing_power": "on"}
},
"target_temperature": "freezing_temperature",
"current_temperature": "freezing_real_temperature",
"min_temp": -30,
"max_temp": -10,
"temperature_unit": UnitOfTemperature.CELSIUS,
"precision": PRECISION_HALVES,
},
"left_flexzone": {
"power": "left_flexzone_power",
"hvac_modes": {
"off": {"left_flexzone_power": "off"},
"heat": {"left_flexzone_power": "on"}
},
"target_temperature": "left_flexzone_temperature",
"current_temperature": "left_variable_real_temperature",
"min_temp": -30,
"max_temp": 10,
"temperature_unit": UnitOfTemperature.CELSIUS,
"precision": PRECISION_HALVES,
},
"right_flexzone": {
"power": "right_flexzone_power",
"hvac_modes": {
"off": {"right_flexzone_power": "off"},
"heat": {"right_flexzone_power": "on"}
},
"target_temperature": "right_flexzone_temperature",
"current_temperature": "right_variable_real_temperature",
"min_temp": -30,
"max_temp": 10,
"temperature_unit": UnitOfTemperature.CELSIUS,
"precision": PRECISION_HALVES,
}
},
Platform.SELECT: {
"variable_mode": {
"options": {
"none_mode": {"variable_mode": "none_mode"},
"freezing": {"variable_mode": "freezing"},
"refrigeration": {"variable_mode": "refrigeration"},
"wine": {"variable_mode": "wine"},
"vegetable": {"variable_mode": "vegetable"}
}
},
"icea_bar_function_switch": {
"options": {
"default": {"icea_bar_function_switch": "default"},
"ice": {"icea_bar_function_switch": "ice"},
"water": {"icea_bar_function_switch": "water"},
"off": {"icea_bar_function_switch": "off"}
}
},
"food_site": {
"options": {
"left_freezing_room": {"food_site": "left_freezing_room"},
"right_freezing_room": {"food_site": "right_freezing_room"},
"storage_room": {"food_site": "storage_room"},
"function_zone": {"food_site": "function_zone"}
}
},
"temperature_unit": {
"options": {
"celsius": {"temperature_unit": "celsius"},
"fahrenheit": {"temperature_unit": "fahrenheit"}
}
}
},
Platform.SENSOR: {
"storage_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"freezing_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"left_flexzone_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"right_flexzone_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"refrigeration_real_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"freezing_real_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"left_variable_real_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"right_variable_real_temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"interval_room_humidity_level": {
"device_class": SensorDeviceClass.HUMIDITY,
"unit_of_measurement": PERCENTAGE,
"state_class": SensorStateClass.MEASUREMENT
},
"normal_zone_level": {
"device_class": SensorDeviceClass.ENUM
},
"function_zone_level": {
"device_class": SensorDeviceClass.ENUM
},
"freeze_fahrenheit_level": {
"device_class": SensorDeviceClass.ENUM
},
"refrigeration_fahrenheit_level": {
"device_class": SensorDeviceClass.ENUM
},
"leach_expire_day": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.DAYS,
"state_class": SensorStateClass.MEASUREMENT
},
"power_consumption_low": {
"device_class": SensorDeviceClass.POWER,
"unit_of_measurement": "W",
"state_class": SensorStateClass.MEASUREMENT
},
"power_consumption_high": {
"device_class": SensorDeviceClass.POWER,
"unit_of_measurement": "W",
"state_class": SensorStateClass.MEASUREMENT
},
"fast_cold_minute": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"fast_freeze_minute": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
}
}
}
}
}

View File

@@ -0,0 +1,185 @@
from homeassistant.const import Platform, UnitOfTemperature, UnitOfTime
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [
"power", "mode_state", "fan_set", "room_temp_value", "humidity_set"
],
"entities": {
Platform.SWITCH: {
"lock_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"esp_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"passby_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"preheat_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"remain_able": {
"device_class": SwitchDeviceClass.SWITCH,
},
"hcho_check_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"co2_check_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"function_set_link": {
"device_class": SwitchDeviceClass.SWITCH,
},
"function_set_sleep": {
"device_class": SwitchDeviceClass.SWITCH,
},
"function_set_energy_save": {
"device_class": SwitchDeviceClass.SWITCH,
},
"function_set_prheat": {
"device_class": SwitchDeviceClass.SWITCH,
},
"function_set_ultimate": {
"device_class": SwitchDeviceClass.SWITCH,
},
"clean_net_clean_flg": {
"device_class": SwitchDeviceClass.SWITCH,
},
"change_net_change_flg": {
"device_class": SwitchDeviceClass.SWITCH,
},
"condensation_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"humidity_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"preheat_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"esp_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"pm25_check_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"timer_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"freeze_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"humidity_check_enable": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.SELECT: {
"mode_state": {
"options": {
"passby": {"mode_state": "passby"},
"auto": {"mode_state": "auto"},
"manual": {"mode_state": "manual"},
"sleep": {"mode_state": "sleep"},
"energy_save": {"mode_state": "energy_save"},
"ultimate": {"mode_state": "ultimate"}
}
},
"fan_set": {
"options": {
"off": {"fan_set": "0"},
"low": {"fan_set": "1"},
"medium": {"fan_set": "2"},
"high": {"fan_set": "3"},
"auto": {"fan_set": "4"}
}
}
},
Platform.SENSOR: {
"room_temp_value": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"clean_net_used_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"change_net_used_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"tvoc_value": {
"device_class": SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
"unit_of_measurement": "mg/m³",
"state_class": SensorStateClass.MEASUREMENT
},
"change_set_real_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"clean_set_real_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"error_code": {
"device_class": SensorDeviceClass.ENUM
},
"humidity_set": {
"device_class": SensorDeviceClass.HUMIDITY,
"unit_of_measurement": "%",
"state_class": SensorStateClass.MEASUREMENT
},
"room_aqi_value": {
"device_class": SensorDeviceClass.AQI,
"state_class": SensorStateClass.MEASUREMENT
},
"change_net_set_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"clean_net_set_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"humidity_value": {
"device_class": SensorDeviceClass.HUMIDITY,
"unit_of_measurement": "%",
"state_class": SensorStateClass.MEASUREMENT
},
"hcho_value": {
"device_class": SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
"unit_of_measurement": "mg/m³",
"state_class": SensorStateClass.MEASUREMENT
},
"pm25_value": {
"device_class": SensorDeviceClass.PM25,
"unit_of_measurement": "µg/m³",
"state_class": SensorStateClass.MEASUREMENT
},
"co2_value": {
"device_class": SensorDeviceClass.CO2,
"unit_of_measurement": "ppm",
"state_class": SensorStateClass.MEASUREMENT
},
"machine_type": {
"device_class": SensorDeviceClass.ENUM
}
}
}
}
}

View File

@@ -0,0 +1,167 @@
from homeassistant.const import Platform, UnitOfTemperature, PRECISION_HALVES
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [
"power_state", "run_mode", "temp_set", "heat_enable", "cool_enable"
],
"entities": {
Platform.CLIMATE: {
"thermostat": {
"power": "power_state",
"hvac_modes": {
"off": {"power_state": "off"},
"heat": {"power_state": "on", "run_mode": "heat", "heat_enable": "on"},
"cool": {"power_state": "on", "run_mode": "cool", "cool_enable": "on"},
"auto": {"power_state": "on", "run_mode": "auto", "heat_enable": "on", "cool_enable": "on"}
},
"target_temperature": "temp_set",
"current_temperature": "cur_temp",
"min_temp": 5,
"max_temp": 70,
"temperature_unit": UnitOfTemperature.CELSIUS,
"precision": PRECISION_HALVES,
}
},
Platform.SWITCH: {
"freeze_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"power_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"heat_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cool_enable": {
"device_class": SwitchDeviceClass.SWITCH,
},
"silence_set_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"time_set_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"silence_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"holiday_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"holiday_set_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"holiday_on_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"room_temp_ctrl": {
"device_class": SwitchDeviceClass.SWITCH,
},
"room_temp_set": {
"device_class": SwitchDeviceClass.SWITCH,
},
"comp_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"day_time_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"week_time_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"warn_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"defrost_state": {
"device_class": SwitchDeviceClass.SWITCH,
},
"pre_heat": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.SELECT: {
"run_mode": {
"options": {
"heat": {"run_mode": "heat"},
"cool": {"run_mode": "cool"},
"auto": {"run_mode": "auto"},
"fan": {"run_mode": "fan"},
"dry": {"run_mode": "dry"}
}
},
"temp_type": {
"options": {
"water_temperature": {"temp_type": "water_temperature"},
"room_temperature": {"temp_type": "room_temperature"},
"outdoor_temperature": {"temp_type": "outdoor_temperature"}
}
}
},
Platform.SENSOR: {
"cur_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"error_code": {
"device_class": SensorDeviceClass.ENUM
},
"heat_max_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"heat_min_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"cool_max_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"cool_min_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"auto_max_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"auto_min_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"preheat_on_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"preheat_max_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"preheat_min_set_temp": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"temp_set": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
}
}
}
}
}

View File

@@ -0,0 +1,181 @@
from homeassistant.const import Platform, UnitOfElectricPotential, UnitOfTemperature, UnitOfTime
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": [0, 1],
"calculate": {
"get": [
{
"lvalue": "[remaining_time]",
"rvalue": "[db_remain_time]"
}
],
"set": {
}
},
"entities": {
Platform.SWITCH: {
"db_power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_clean_notification": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_softener_needed": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_detergent_needed": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_nightly_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_baby_lock": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_light": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_steam_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_fast_clean_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"db_wash_dry_link": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.SELECT: {
"db_running_status": {
"options": {
"stop": {"db_running_status": "stop"},
"start": {"db_running_status": "start"},
"pause": {"db_running_status": "pause"},
"finish": {"db_running_status": "finish"},
"error": {"db_running_status": "error"}
}
},
"db_program": {
"options": {
"fast_wash_30": {"db_program": "fast_wash_30"},
"normal_wash": {"db_program": "normal_wash"},
"heavy_wash": {"db_program": "heavy_wash"},
"delicate_wash": {"db_program": "delicate_wash"},
"quick_wash": {"db_program": "quick_wash"},
"eco_wash": {"db_program": "eco_wash"}
}
},
"db_water_level": {
"options": {
"low": {"db_water_level": "1"},
"medium": {"db_water_level": "2"},
"high": {"db_water_level": "3"},
"extra_high": {"db_water_level": "4"}
}
},
"db_temperature": {
"options": {
"cold": {"db_temperature": "1"},
"warm": {"db_temperature": "2"},
"hot": {"db_temperature": "3"},
"extra_hot": {"db_temperature": "4"}
}
},
"dehydration_speed": {
"options": {
"low": {"dehydration_speed": "1"},
"medium": {"dehydration_speed": "2"},
"high": {"dehydration_speed": "3"},
"extra_high": {"dehydration_speed": "4"}
}
},
"db_detergent": {
"options": {
"none": {"db_detergent": "1"},
"little": {"db_detergent": "2"},
"normal": {"db_detergent": "3"},
"more": {"db_detergent": "4"}
}
},
"db_softener": {
"options": {
"none": {"db_softener": "1"},
"little": {"db_softener": "2"},
"normal": {"db_softener": "3"},
"more": {"db_softener": "4"}
}
},
"db_position": {
"options": {
"position_1": {"db_position": "1"},
"position_2": {"db_position": "2"},
"position_3": {"db_position": "3"}
}
},
"db_location": {
"options": {
"location_1": {"db_location": "1"},
"location_2": {"db_location": "2"},
"location_3": {"db_location": "3"}
}
}
},
Platform.SENSOR: {
"db_remain_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"db_progress": {
"device_class": SensorDeviceClass.BATTERY,
"unit_of_measurement": "%",
"state_class": SensorStateClass.MEASUREMENT
},
"db_error_code": {
"device_class": SensorDeviceClass.ENUM
},
"db_set_dewater_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"db_set_wash_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"db_device_software_version": {
"device_class": SensorDeviceClass.ENUM
},
"db_rinse_count": {
"device_class": SensorDeviceClass.ENUM
},
"db_wash_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"db_appointment_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"db_appointment": {
"device_class": SensorDeviceClass.ENUM
},
"db_dehydration_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"db_cycle_memory": {
"device_class": SensorDeviceClass.ENUM
}
}
}
}
}

View File

@@ -0,0 +1,381 @@
from homeassistant.const import Platform, UnitOfElectricPotential, UnitOfTemperature, UnitOfTime
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": [0, 1],
"calculate": {
"get": [
{
"lvalue": "[remaining_time]",
"rvalue": "[remain_time]"
}
],
"set": {
}
},
"entities": {
Platform.SWITCH: {
"power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"softener_lack": {
"device_class": SwitchDeviceClass.SWITCH,
},
"detergent_lack": {
"device_class": SwitchDeviceClass.SWITCH,
},
"door_opened": {
"device_class": SwitchDeviceClass.SWITCH,
},
"bucket_water_overheating": {
"device_class": SwitchDeviceClass.SWITCH,
},
"memory": {
"device_class": SwitchDeviceClass.SWITCH,
},
"appointment": {
"device_class": SwitchDeviceClass.SWITCH,
},
"spray_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"old_speedy": {
"device_class": SwitchDeviceClass.SWITCH,
},
"nightly": {
"device_class": SwitchDeviceClass.SWITCH,
},
"down_light": {
"device_class": SwitchDeviceClass.SWITCH,
},
"easy_ironing": {
"device_class": SwitchDeviceClass.SWITCH,
},
"super_clean_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"intelligent_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"strong_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"silent": {
"device_class": SwitchDeviceClass.SWITCH,
},
"speedy": {
"device_class": SwitchDeviceClass.SWITCH,
},
"lock": {
"device_class": SwitchDeviceClass.SWITCH,
},
"flocks_switcher": {
"device_class": SwitchDeviceClass.SWITCH,
},
"fresh_anion_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"dry_weighing_already": {
"device_class": SwitchDeviceClass.SWITCH,
},
"keep_fresh_status": {
"device_class": SwitchDeviceClass.SWITCH,
},
"drying_tunnel_overheating": {
"device_class": SwitchDeviceClass.SWITCH,
},
"fast_clean_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"steam_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"beforehand_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"ai_flag": {
"device_class": SwitchDeviceClass.SWITCH,
},
"water_plus": {
"device_class": SwitchDeviceClass.SWITCH,
},
"soak": {
"device_class": SwitchDeviceClass.SWITCH,
},
"ultraviolet_lamp": {
"device_class": SwitchDeviceClass.SWITCH,
},
"eye_wash": {
"device_class": SwitchDeviceClass.SWITCH,
},
"microbubble": {
"device_class": SwitchDeviceClass.SWITCH,
},
"wind_dispel": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cycle_memory": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.SELECT: {
"running_status": {
"options": {
"standby": {"running_status": "standby"},
"running": {"running_status": "running"},
"pause": {"running_status": "pause"},
"finish": {"running_status": "finish"},
"error": {"running_status": "error"}
}
},
"db_dehydration_speed": {
"options": {
"low": {"db_dehydration_speed": "1"},
"medium": {"db_dehydration_speed": "2"},
"high": {"db_dehydration_speed": "3"},
"extra_high": {"db_dehydration_speed": "4"}
}
},
"mode": {
"options": {
"normal": {"mode": "normal"},
"eco": {"mode": "eco"},
"quick": {"mode": "quick"},
"heavy": {"mode": "heavy"},
"delicate": {"mode": "delicate"}
}
},
"water_level": {
"options": {
"low": {"water_level": "low"},
"medium": {"water_level": "medium"},
"high": {"water_level": "high"},
"extra_high": {"water_level": "extra_high"}
}
},
"program": {
"options": {
"ssp": {"program": "ssp"},
"cotton": {"program": "cotton"},
"synthetic": {"program": "synthetic"},
"wool": {"program": "wool"},
"delicate": {"program": "delicate"},
"quick": {"program": "quick"}
}
},
"temperature": {
"options": {
"cold": {"temperature": "cold"},
"warm": {"temperature": "warm"},
"hot": {"temperature": "hot"},
"extra_hot": {"temperature": "extra_hot"}
}
},
"detergent_density": {
"options": {
"low": {"detergent_density": "low"},
"medium": {"detergent_density": "medium"},
"high": {"detergent_density": "high"},
"extra_high": {"detergent_density": "extra_high"}
}
},
"softener_density": {
"options": {
"low": {"softener_density": "low"},
"medium": {"softener_density": "medium"},
"high": {"softener_density": "high"},
"extra_high": {"softener_density": "extra_high"}
}
},
"detergent": {
"options": {
"none": {"detergent": "none"},
"little": {"detergent": "little"},
"normal": {"detergent": "normal"},
"more": {"detergent": "more"}
}
},
"softener": {
"options": {
"none": {"softener": "none"},
"little": {"softener": "little"},
"normal": {"softener": "normal"},
"more": {"softener": "more"}
}
},
"season": {
"options": {
"spring": {"season": "spring"},
"summer": {"season": "summer"},
"autumn": {"season": "autumn"},
"winter": {"season": "winter"}
}
},
"disinfectant": {
"options": {
"none": {"disinfectant": "none"},
"light": {"disinfectant": "light"},
"medium": {"disinfectant": "medium"},
"strong": {"disinfectant": "strong"}
}
},
"dirty_degree": {
"options": {
"light": {"dirty_degree": "light"},
"medium": {"dirty_degree": "medium"},
"heavy": {"dirty_degree": "heavy"},
"extra_heavy": {"dirty_degree": "extra_heavy"}
}
},
"stains": {
"options": {
"none": {"stains": "none"},
"light": {"stains": "light"},
"medium": {"stains": "medium"},
"heavy": {"stains": "heavy"}
}
},
"add_rinse": {
"options": {
"none": {"add_rinse": "none"},
"one": {"add_rinse": "one"},
"two": {"add_rinse": "two"},
"three": {"add_rinse": "three"}
}
},
"soak_count": {
"options": {
"none": {"soak_count": "none"},
"one": {"soak_count": "one"},
"two": {"soak_count": "two"},
"three": {"soak_count": "three"}
}
}
},
Platform.SENSOR: {
"wash_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"appointment_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"remain_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"dryer": {
"device_class": SensorDeviceClass.ENUM
},
"remote_control_flag": {
"device_class": SensorDeviceClass.ENUM
},
"progress": {
"device_class": SensorDeviceClass.BATTERY,
"unit_of_measurement": "%",
"state_class": SensorStateClass.MEASUREMENT
},
"cloud_cycle_low": {
"device_class": SensorDeviceClass.ENUM
},
"cloud_cycle_high": {
"device_class": SensorDeviceClass.ENUM
},
"cloud_cycle_jiepai1": {
"device_class": SensorDeviceClass.ENUM
},
"cloud_cycle_jiepai2": {
"device_class": SensorDeviceClass.ENUM
},
"cloud_cycle_jiepai3": {
"device_class": SensorDeviceClass.ENUM
},
"cloud_cycle_jiepai4": {
"device_class": SensorDeviceClass.ENUM
},
"cloud_cycle_jiepai_time1": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"dehydration_time_value": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"cloud_cycle_jiepai_time3": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"cloud_cycle_jiepai_time4": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"customize_machine_cycle": {
"device_class": SensorDeviceClass.ENUM
},
"detergent_global": {
"device_class": SensorDeviceClass.ENUM
},
"softener_global": {
"device_class": SensorDeviceClass.ENUM
},
"detergent_density_global": {
"device_class": SensorDeviceClass.ENUM
},
"softener_density_global": {
"device_class": SensorDeviceClass.ENUM
},
"fresh_air_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"flocks_remind_period": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"device_software_version": {
"device_class": SensorDeviceClass.ENUM
},
"expert_step": {
"device_class": SensorDeviceClass.ENUM
},
"error_code": {
"device_class": SensorDeviceClass.ENUM
},
"flocks_wash_count": {
"device_class": SensorDeviceClass.ENUM
},
"active_oxygen": {
"device_class": SensorDeviceClass.ENUM
},
"dehydration_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"cloud_cycle_jiepai_time2": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"wash_time_value": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
}
}
}
}
}

View File

@@ -0,0 +1,147 @@
from homeassistant.const import Platform, UnitOfTime
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [
"power", "ai_switch", "light", "appointment", "prevent_wrinkle_switch",
"steam_switch", "damp_dry_signal", "eco_dry_switch", "bucket_clean_switch",
"water_box", "baby_lock", "remind_sound", "steam", "prevent_wrinkle",
"material", "sterilize", "dryness_level", "dry_temp", "intensity", "program"
],
"entities": {
Platform.SWITCH: {
"ai_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"light": {
"device_class": SwitchDeviceClass.SWITCH,
},
"appointment": {
"device_class": SwitchDeviceClass.SWITCH,
},
"prevent_wrinkle_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"steam_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"damp_dry_signal": {
"device_class": SwitchDeviceClass.SWITCH,
},
"eco_dry_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"bucket_clean_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"water_box": {
"device_class": SwitchDeviceClass.SWITCH,
},
"baby_lock": {
"device_class": SwitchDeviceClass.SWITCH,
},
"remind_sound": {
"device_class": SwitchDeviceClass.SWITCH,
},
"steam": {
"device_class": SwitchDeviceClass.SWITCH,
},
"power": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.BINARY_SENSOR: {
"door_warn": {
"device_class": BinarySensorDeviceClass.PROBLEM,
}
},
Platform.SELECT: {
"prevent_wrinkle": {
"options": {
"off": {"prevent_wrinkle": "0"},
"low": {"prevent_wrinkle": "1"},
"medium": {"prevent_wrinkle": "2"},
"high": {"prevent_wrinkle": "3"}
}
},
"material": {
"options": {
"cotton": {"material": "0"},
"synthetic": {"material": "1"},
"wool": {"material": "2"},
"delicate": {"material": "3"},
"mixed": {"material": "4"}
}
},
"sterilize": {
"options": {
"off": {"sterilize": "0"},
"on": {"sterilize": "1"}
}
},
"dryness_level": {
"options": {
"extra_dry": {"dryness_level": "0"},
"dry": {"dryness_level": "1"},
"normal": {"dryness_level": "2"},
"damp": {"dryness_level": "3"}
}
},
"dry_temp": {
"options": {
"low": {"dry_temp": "0"},
"medium": {"dry_temp": "1"},
"high": {"dry_temp": "2"},
"extra_high": {"dry_temp": "3"}
}
},
"intensity": {
"options": {
"low": {"intensity": "0"},
"medium": {"intensity": "1"},
"high": {"intensity": "2"}
}
},
"program": {
"options": {
"mixed_wash": {"program": "mixed_wash"},
"cotton": {"program": "cotton"},
"synthetic": {"program": "synthetic"},
"wool": {"program": "wool"},
"delicate": {"program": "delicate"},
"quick": {"program": "quick"},
"eco": {"program": "eco"}
}
}
},
Platform.SENSOR: {
"appointment_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"remain_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"progress": {
"device_class": SensorDeviceClass.ENUM
},
"error_code": {
"device_class": SensorDeviceClass.ENUM
},
"dry_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
}
}
}
}
}

View File

@@ -0,0 +1,103 @@
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.const import Platform, UnitOfTemperature, PRECISION_HALVES, UnitOfTime
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [],
"entities": {
Platform.SWITCH: {
"airswitch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"waterswitch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"uvswitch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"doorswitch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"dryswitch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"dry_step_switch": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.BINARY_SENSOR: {
"air_status": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"water_lack": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"softwater_lack": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"wash_stage":{
"device_class": BinarySensorDeviceClass.RUNNING,
},
"bright_lack": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"diy_flag": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"diy_main_wash": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"diy_piao_wash": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
"diy_times": {
"device_class": BinarySensorDeviceClass.RUNNING,
},
},
Platform.SELECT: {
"work_status": {
"options": {
"power_off": {"work_status": "power_off" },
"power_on": {"work_status": "power_on" },
}
},
},
Platform.SENSOR: {
"bright": {
"device_class": SensorDeviceClass.ILLUMINANCE,
"unit_of_measurement": "lx",
"state_class": SensorStateClass.MEASUREMENT
},
"temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"softwater": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"left_time": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"air_set_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"air_left_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
}
}
}
}

View File

@@ -0,0 +1,182 @@
from homeassistant.const import Platform, UnitOfTemperature, UnitOfVolume, UnitOfTime, PERCENTAGE, PRECISION_HALVES
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [
"power", "bubble", "cold_water", "bathtub", "safe", "cold_water_dot",
"change_litre_switch", "cold_water_ai", "cold_water_pressure",
"person_mode_one", "person_mode_two", "person_mode_three", "gesture_function",
"mode", "power_level", "type_machine", "capacity", "temperature"
],
"entities": {
Platform.SWITCH: {
"bubble": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cold_water": {
"device_class": SwitchDeviceClass.SWITCH,
},
"bathtub": {
"device_class": SwitchDeviceClass.SWITCH,
},
"safe": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cold_water_dot": {
"device_class": SwitchDeviceClass.SWITCH,
},
"change_litre_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cold_water_ai": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cold_water_pressure": {
"device_class": SwitchDeviceClass.SWITCH,
},
"person_mode_one": {
"device_class": SwitchDeviceClass.SWITCH,
},
"person_mode_two": {
"device_class": SwitchDeviceClass.SWITCH,
},
"person_mode_three": {
"device_class": SwitchDeviceClass.SWITCH,
},
"gesture_function": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.CLIMATE: {
"water_heater": {
"power": "power",
"hvac_modes": {
"off": {"power": "off"},
"heat": {"power": "on", "mode": "shower"}
},
"target_temperature": "temperature",
"current_temperature": "out_water_tem",
"min_temp": 20,
"max_temp": 60,
"temperature_unit": UnitOfTemperature.CELSIUS,
"precision": PRECISION_HALVES,
}
},
Platform.SELECT: {
"mode": {
"options": {
"shower": {"mode": "shower"},
"bath": {"mode": "bath"},
"mixed": {"mode": "mixed"},
"eco": {"mode": "eco"}
}
},
"power_level": {
"options": {
"low": {"power_level": "0"},
"medium": {"power_level": "1"},
"high": {"power_level": "2"},
"max": {"power_level": "3"}
}
},
"type_machine": {
"options": {
"standard": {"type_machine": "20"},
"premium": {"type_machine": "21"},
"deluxe": {"type_machine": "22"}
}
},
"capacity": {
"options": {
"small": {"capacity": "1"},
"medium": {"capacity": "2"},
"large": {"capacity": "3"}
}
},
"gesture_function_type": {
"options": {
"none": {"gesture_function_type": "0"},
"wave": {"gesture_function_type": "1"},
"touch": {"gesture_function_type": "2"},
"proximity": {"gesture_function_type": "3"}
}
}
},
Platform.SENSOR: {
"out_water_tem": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"water_volume": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"zero_cold_tem": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"bath_out_volume": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"return_water_tem": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"change_litre": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"bathtub_water_level": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"temperature": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"gas_lift_percent": {
"device_class": SensorDeviceClass.POWER_FACTOR,
"unit_of_measurement": PERCENTAGE,
"state_class": SensorStateClass.MEASUREMENT
},
"person_tem_one": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"person_tem_two": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"person_tem_three": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"in_water_tem": {
"device_class": SensorDeviceClass.TEMPERATURE,
"unit_of_measurement": UnitOfTemperature.CELSIUS,
"state_class": SensorStateClass.MEASUREMENT
},
"error_code": {
"device_class": SensorDeviceClass.ENUM
}
}
}
}
}

View File

@@ -0,0 +1,228 @@
from homeassistant.const import Platform, UnitOfTemperature, PRECISION_HALVES, UnitOfTime, UnitOfElectricPotential, UnitOfVolume, UnitOfMass
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [],
"entities": {
Platform.SWITCH: {
"holiday_mode": {
"device_class": SwitchDeviceClass.SWITCH,
},
"water_way": {
"device_class": SwitchDeviceClass.SWITCH,
},
"soften": {
"device_class": SwitchDeviceClass.SWITCH,
},
"leak_water_protection": {
"device_class": SwitchDeviceClass.SWITCH,
},
"cl_sterilization": {
"device_class": SwitchDeviceClass.SWITCH,
},
"micro_leak": {
"device_class": SwitchDeviceClass.SWITCH,
},
"low_salt": {
"device_class": SwitchDeviceClass.SWITCH,
},
"no_salt": {
"device_class": SwitchDeviceClass.SWITCH,
},
"low_battery": {
"device_class": SwitchDeviceClass.SWITCH,
},
"salt_level_sensor_error": {
"device_class": SwitchDeviceClass.SWITCH,
},
"flowmeter_error": {
"device_class": SwitchDeviceClass.SWITCH,
},
"leak_water": {
"device_class": SwitchDeviceClass.SWITCH,
},
"micro_leak_protection": {
"device_class": SwitchDeviceClass.SWITCH,
},
"maintenance_reminder_switch": {
"device_class": SwitchDeviceClass.SWITCH,
},
"rsj_stand_by": {
"device_class": SwitchDeviceClass.SWITCH,
},
"regeneration": {
"device_class": SwitchDeviceClass.SWITCH,
},
"pre_regeneration": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.BINARY_SENSOR: {
"maintenance_remind": {
"device_class": BinarySensorDeviceClass.PROBLEM,
},
"chlorine_sterilization_error": {
"device_class": BinarySensorDeviceClass.PROBLEM,
},
"rtc_error": {
"device_class": BinarySensorDeviceClass.PROBLEM,
}
},
Platform.SENSOR: {
"micro_leak_protection_value": {
"device_class": SensorDeviceClass.PRESSURE,
"unit_of_measurement": "kPa",
"state_class": SensorStateClass.MEASUREMENT
},
"regeneration_current_stages": {
"device_class": SensorDeviceClass.ENUM
},
"water_hardness": {
"device_class": SensorDeviceClass.WATER,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"timing_regeneration_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"real_time_setting_hour": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.HOURS,
"state_class": SensorStateClass.MEASUREMENT
},
"timing_regeneration_min": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"regeneration_left_seconds": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.SECONDS,
"state_class": SensorStateClass.MEASUREMENT
},
"maintenance_reminder_setting": {
"device_class": SensorDeviceClass.ENUM
},
"mixed_water_gear": {
"device_class": SensorDeviceClass.ENUM
},
"use_days": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.DAYS,
"state_class": SensorStateClass.MEASUREMENT
},
"days_since_last_regeneration": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.DAYS,
"state_class": SensorStateClass.MEASUREMENT
},
"velocity": {
"device_class": SensorDeviceClass.SPEED,
"unit_of_measurement": "m/s",
"state_class": SensorStateClass.MEASUREMENT
},
"supply_voltage": {
"device_class": SensorDeviceClass.VOLTAGE,
"unit_of_measurement": UnitOfElectricPotential.VOLT,
"state_class": SensorStateClass.MEASUREMENT
},
"left_salt": {
"device_class": SensorDeviceClass.WEIGHT,
"unit_of_measurement": UnitOfMass.KILOGRAMS,
"state_class": SensorStateClass.MEASUREMENT
},
"pre_regeneration_days": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.DAYS,
"state_class": SensorStateClass.MEASUREMENT
},
"flushing_days": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.DAYS,
"state_class": SensorStateClass.MEASUREMENT
},
"salt_setting": {
"device_class": SensorDeviceClass.ENUM
},
"regeneration_count": {
"device_class": SensorDeviceClass.ENUM
},
"battery_voltage": {
"device_class": SensorDeviceClass.VOLTAGE,
"unit_of_measurement": UnitOfElectricPotential.VOLT,
"state_class": SensorStateClass.MEASUREMENT
},
"error": {
"device_class": SensorDeviceClass.ENUM
},
"days_since_last_two_regeneration": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.DAYS,
"state_class": SensorStateClass.MEASUREMENT
},
"remind_maintenance_days": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.DAYS,
"state_class": SensorStateClass.MEASUREMENT
},
"real_date_setting_year": {
"device_class": SensorDeviceClass.ENUM
},
"real_date_setting_month": {
"device_class": SensorDeviceClass.ENUM
},
"real_date_setting_day": {
"device_class": SensorDeviceClass.ENUM
},
"category": {
"device_class": SensorDeviceClass.ENUM
},
"real_time_setting_min": {
"device_class": SensorDeviceClass.DURATION,
"unit_of_measurement": UnitOfTime.MINUTES,
"state_class": SensorStateClass.MEASUREMENT
},
"regeneration_stages": {
"device_class": SensorDeviceClass.ENUM
},
"soft_available_big": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"water_consumption_big": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"water_consumption_today": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"water_consumption_average": {
"device_class": SensorDeviceClass.VOLUME,
"unit_of_measurement": UnitOfVolume.LITERS,
"state_class": SensorStateClass.TOTAL_INCREASING
},
"salt_alarm_threshold": {
"device_class": SensorDeviceClass.WEIGHT,
"unit_of_measurement": UnitOfMass.KILOGRAMS,
"state_class": SensorStateClass.MEASUREMENT
},
"leak_water_protection_value": {
"device_class": SensorDeviceClass.PRESSURE,
"unit_of_measurement": "kPa",
"state_class": SensorStateClass.MEASUREMENT
}
}
}
}
}

View File

@@ -0,0 +1,157 @@
from homeassistant.const import Platform, UnitOfTemperature, UnitOfTime, PERCENTAGE
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass
from homeassistant.components.humidifier import HumidifierDeviceClass
DEVICE_MAPPING = {
"default": {
"rationale": ["off", "on"],
"queries": [{}],
"centralized": [
"power", "disinfect_on_off", "netions_on_off", "airdry_on_off",
"wind_gear", "wind_speed", "light_color", "bright_led",
"humidity_mode", "tank_status", "humidity", "cur_humidity"
],
"entities": {
Platform.SWITCH: {
"disinfect_on_off": {
"device_class": SwitchDeviceClass.SWITCH,
},
"netions_on_off": {
"device_class": SwitchDeviceClass.SWITCH,
},
"airdry_on_off": {
"device_class": SwitchDeviceClass.SWITCH,
},
"power": {
"device_class": SwitchDeviceClass.SWITCH,
},
"buzzer": {
"device_class": SwitchDeviceClass.SWITCH,
},
"power_on_timer": {
"device_class": SwitchDeviceClass.SWITCH,
},
"power_off_timer": {
"device_class": SwitchDeviceClass.SWITCH,
},
"display_on_off": {
"device_class": SwitchDeviceClass.SWITCH,
}
},
Platform.BINARY_SENSOR: {
"add_water_flag": {
"device_class": BinarySensorDeviceClass.PROBLEM,
}
},
Platform.HUMIDIFIER: {
"humidifier": {
"device_class": HumidifierDeviceClass.HUMIDIFIER,
"power": "power",
"target_humidity": "humidity",
"current_humidity": "cur_humidity",
"min_humidity": 30,
"max_humidity": 80,
"mode": "humidity_mode",
"modes": {
"manual": {"humidity_mode": "manual"},
"auto": {"humidity_mode": "auto"},
"sleep": {"humidity_mode": "sleep"},
"baby": {"humidity_mode": "baby"}
}
}
},
Platform.SELECT: {
"wind_gear": {
"options": {
"low": {"wind_gear": "low"},
"medium": {"wind_gear": "medium"},
"high": {"wind_gear": "high"},
"auto": {"wind_gear": "auto"},
"invalid": {"wind_gear": "invalid"}
}
},
"wind_speed": {
"options": {
"low": {"wind_speed": "low"},
"medium": {"wind_speed": "medium"},
"high": {"wind_speed": "high"},
"auto": {"wind_speed": "auto"}
}
},
"light_color": {
"options": {
"warm": {"light_color": "warm"},
"cool": {"light_color": "cool"},
"white": {"light_color": "white"},
"blue": {"light_color": "blue"},
"green": {"light_color": "green"},
"red": {"light_color": "red"},
"off": {"light_color": "off"}
}
},
"bright_led": {
"options": {
"light": {"bright_led": "light"},
"dim": {"bright_led": "dim"},
"off": {"bright_led": "off"}
}
},
"tank_status": {
"options": {
"normal": {"tank_status": "0"},
"low": {"tank_status": "1"},
"empty": {"tank_status": "2"},
"error": {"tank_status": "3"}
}
}
},
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
},
"sensor_battery": {
"device_class": SensorDeviceClass.BATTERY,
"unit_of_measurement": PERCENTAGE,
"state_class": SensorStateClass.MEASUREMENT
},
"sensor_humidify": {
"device_class": SensorDeviceClass.HUMIDITY,
"unit_of_measurement": PERCENTAGE,
"state_class": SensorStateClass.MEASUREMENT
},
"sensor_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
}
}
}
}
}

View File

@@ -1,6 +1,5 @@
from homeassistant.const import Platform, UnitOfTemperature
from homeassistant.const import Platform, UnitOfTemperature, PRECISION_HALVES
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
from homeassistant.components.climate.const import PRECISION_HALVES
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.switch import SwitchDeviceClass

View File

@@ -1,7 +1,7 @@
from homeassistant.components.fan import FanEntity, FanEntityFeature
from homeassistant.const import Platform
from .const import DOMAIN
from .midea_entities import MideaEntity
from .midea_entity import MideaEntity
from . import load_device_config
@@ -24,13 +24,30 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
coordinator = coordinator_map.get(device_id)
device = coordinator.device if coordinator else None
for entity_key, ecfg in entities_cfg.items():
devs.append(MideaFanEntity(device, manufacturer, rationale, entity_key, ecfg))
devs.append(MideaFanEntity(coordinator, device, manufacturer, rationale, entity_key, ecfg))
async_add_entities(devs)
class MideaFanEntity(MideaEntity, FanEntity):
def __init__(self, device, manufacturer, rationale, entity_key, config):
super().__init__(device, manufacturer, rationale, entity_key, config)
def __init__(self, coordinator, device, manufacturer, rationale, entity_key, config):
super().__init__(
coordinator,
device.device_id,
device.device_name,
f"T0x{device.device_type:02X}",
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._config = config
self._key_power = self._config.get("power")
self._key_preset_modes = self._config.get("preset_modes")
self._key_speeds = self._config.get("speeds")
@@ -74,41 +91,48 @@ class MideaFanEntity(MideaEntity, FanEntity):
def oscillating(self):
return self._get_status_on_off(self._key_oscillate)
def turn_on(
async def async_turn_on(
self,
percentage: int | None = None,
preset_mode: str | None = None,
**kwargs,
):
if preset_mode is not None:
new_status = self._key_preset_modes.get(preset_mode)
else:
new_status = {}
if percentage is not None:
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])
new_status[self._key_power] = self._rationale[1]
self._device.set_attributes(new_status)
if self._key_power is not None:
new_status[self._key_power] = True
if new_status:
await self.async_set_attributes(new_status)
def turn_off(self):
self._set_status_on_off(self._key_power, False)
async def async_turn_off(self):
await self._async_set_status_on_off(self._key_power, False)
def set_percentage(self, percentage: int):
async def async_set_percentage(self, percentage: int):
if not self._key_speeds:
return
index = round(percentage * self._attr_speed_count / 100)
if 0 < index < len(self._key_speeds):
if 0 < index <= len(self._key_speeds):
new_status = self._key_speeds[index - 1]
self._device.set_attributes(new_status)
await self.async_set_attributes(new_status)
def set_preset_mode(self, preset_mode: str):
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)
self._device.set_attributes(new_status)
if new_status:
await self.async_set_attributes(new_status)
def oscillate(self, oscillating: bool):
async def async_oscillate(self, oscillating: bool):
if self.oscillating != oscillating:
self._set_status_on_off(self._key_oscillate, oscillating)
await self._async_set_status_on_off(self._key_oscillate, oscillating)
def update_state(self, status):
try:
self.schedule_update_ha_state()
except Exception as e:
except Exception:
pass

View File

@@ -0,0 +1,151 @@
from homeassistant.components.humidifier import (
HumidifierEntity,
HumidifierDeviceClass
)
from homeassistant.const import Platform
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .midea_entity import MideaEntity
from . import load_device_config
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up humidifier entities for Midea devices."""
account_bucket = hass.data.get(DOMAIN, {}).get("accounts", {}).get(config_entry.entry_id)
if not account_bucket:
async_add_entities([])
return
device_list = account_bucket.get("device_list", {})
coordinator_map = account_bucket.get("coordinator_map", {})
devs = []
for device_id, info in device_list.items():
device_type = info.get("type")
sn8 = info.get("sn8")
config = await load_device_config(hass, device_type, sn8) or {}
entities_cfg = (config.get("entities") or {}).get(Platform.HUMIDIFIER, {})
manufacturer = config.get("manufacturer")
rationale = config.get("rationale")
coordinator = coordinator_map.get(device_id)
device = coordinator.device if coordinator else None
for entity_key, ecfg in entities_cfg.items():
devs.append(MideaHumidifierEntity(
coordinator, device, manufacturer, rationale, entity_key, ecfg
))
async_add_entities(devs)
class MideaHumidifierEntity(MideaEntity, HumidifierEntity):
"""Generic humidifier entity."""
def __init__(self, coordinator, device, manufacturer, rationale, entity_key, config):
super().__init__(
coordinator,
device.device_id,
device.device_name,
f"T0x{device.device_type:02X}",
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._entity_key = entity_key
self._config = config
@property
def device_class(self):
"""Return the device class."""
return self._config.get("device_class", HumidifierDeviceClass.HUMIDIFIER)
@property
def is_on(self):
"""Return if the humidifier is on."""
power_key = self._config.get("power")
if power_key:
value = self.device_attributes.get(power_key)
if isinstance(value, bool):
return value
return value == 1 or value == "on" or value == "true"
return False
@property
def target_humidity(self):
"""Return the target humidity."""
target_humidity_key = self._config.get("target_humidity")
if target_humidity_key:
return self.device_attributes.get(target_humidity_key, 0)
return 0
@property
def current_humidity(self):
"""Return the current humidity."""
current_humidity_key = self._config.get("current_humidity")
if current_humidity_key:
return self.device_attributes.get(current_humidity_key, 0)
return 0
@property
def min_humidity(self):
"""Return the minimum humidity."""
return self._config.get("min_humidity", 30)
@property
def max_humidity(self):
"""Return the maximum humidity."""
return self._config.get("max_humidity", 80)
@property
def mode(self):
"""Return the current mode."""
mode_key = self._config.get("mode")
if mode_key:
return self.device_attributes.get(mode_key, "manual")
return "manual"
@property
def available_modes(self):
"""Return the available modes."""
modes = self._config.get("modes", {})
return list(modes.keys())
async def async_turn_on(self, **kwargs):
"""Turn the humidifier on."""
power_key = self._config.get("power")
if power_key:
await self._device.set_attribute(power_key, True)
async def async_turn_off(self, **kwargs):
"""Turn the humidifier off."""
power_key = self._config.get("power")
if power_key:
await self._device.set_attribute(power_key, False)
async def async_set_humidity(self, humidity: int):
"""Set the target humidity."""
target_humidity_key = self._config.get("target_humidity")
if target_humidity_key:
await self._device.set_attribute(target_humidity_key, humidity)
async def async_set_mode(self, mode: str):
"""Set the mode."""
mode_key = self._config.get("mode")
modes = self._config.get("modes", {})
if mode_key and mode in modes:
mode_config = modes[mode]
for attr_key, attr_value in mode_config.items():
await self._device.set_attribute(attr_key, attr_value)

View File

@@ -7,5 +7,5 @@
"iot_class": "cloud_push",
"issue_tracker": "https://github.com/sususweet/midea-meiju-codec/issues",
"requirements": [],
"version": "v0.0.1"
"version": "v0.0.5"
}

View File

@@ -1,130 +0,0 @@
from enum import IntEnum
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
STATE_ON,
STATE_OFF
)
from .const import DOMAIN
from .core.logger import MideaLogger
class Rationale(IntEnum):
EQUALLY = 0
GREATER = 1
LESS = 2
class MideaEntity(Entity):
def __init__(self, device, manufacturer: str | None, rationale: list | None, entity_key: str, config: dict):
self._device = device
self._device.register_update(self.update_state)
self._entity_key = entity_key
self._config = config
self._device_name = self._device.device_name
self._rationale = rationale
if rationale_local := config.get("rationale"):
self._rationale = rationale_local
if self._rationale is None:
self._rationale = ["off", "on"]
self._attr_native_unit_of_measurement = self._config.get("unit_of_measurement")
self._attr_device_class = self._config.get("device_class")
self._attr_state_class = self._config.get("state_class")
self._attr_icon = self._config.get("icon")
self._attr_unique_id = f"{DOMAIN}.{self._device.device_id}_{self._entity_key}"
self._attr_device_info = {
"manufacturer": "Midea" if manufacturer is None else manufacturer,
"model": f"{self._device.model}",
"identifiers": {(DOMAIN, self._device.device_id)},
"name": self._device_name
}
name = self._config.get("name")
if name is None:
name = self._entity_key.replace("_", " ").title()
self._attr_name = f"{self._device_name} {name}"
self.entity_id = self._attr_unique_id
@property
def device(self):
return self._device
@property
def should_poll(self):
return False
@property
def available(self):
return self._device.connected
def _get_status_on_off(self, status_key: str):
result = False
status = self._device.get_attribute(status_key)
if status is not None:
try:
result = bool(self._rationale.index(status))
except ValueError:
MideaLogger.error(f"The value of attribute {status_key} ('{status}') "
f"is not in rationale {self._rationale}")
return result
def _set_status_on_off(self, status_key: str, turn_on: bool):
self._device.set_attribute(status_key, self._rationale[int(turn_on)])
def _list_get_selected(self, key_of_list: list, rationale: Rationale = Rationale.EQUALLY):
for index in range(0, len(key_of_list)):
match = True
for attr, value in key_of_list[index].items():
state_value = self._device.get_attribute(attr)
if state_value is None:
match = False
break
if rationale is Rationale.EQUALLY and state_value != value:
match = False
break
if rationale is Rationale.GREATER and state_value < value:
match = False
break
if rationale is Rationale.LESS and state_value > value:
match = False
break
if match:
return index
return None
def _dict_get_selected(self, key_of_dict: dict, rationale: Rationale = Rationale.EQUALLY):
for mode, status in key_of_dict.items():
match = True
for attr, value in status.items():
state_value = self._device.get_attribute(attr)
if state_value is None:
match = False
break
if rationale is Rationale.EQUALLY and state_value != value:
match = False
break
if rationale is Rationale.GREATER and state_value < value:
match = False
break
if rationale is Rationale.LESS and state_value > value:
match = False
break
if match:
return mode
return None
def update_state(self, status):
if self._entity_key in status or "connected" in status:
try:
self.schedule_update_ha_state()
except Exception as e:
pass
class MideaBinaryBaseEntity(MideaEntity):
@property
def state(self):
return STATE_ON if self.is_on else STATE_OFF
@property
def is_on(self):
return self._get_status_on_off(self._entity_key)

View File

@@ -1,4 +1,4 @@
"""Base entity class for Midea Auto Codec integration."""
"""Base entity class for Midea Auto Cloud integration."""
from __future__ import annotations
@@ -29,27 +29,72 @@ class MideaEntity(CoordinatorEntity[MideaDataUpdateCoordinator], Entity):
sn: str,
sn8: str,
model: str,
entity_key: str,
*,
device: Any | None = None,
manufacturer: str | None = None,
rationale: list | None = None,
config: dict | None = None,
) -> None:
"""Initialize the entity."""
super().__init__(coordinator)
self._device_id = device_id
self._device_name = device_name
self._device_type = device_type
self._entity_key = entity_key
self._sn = sn
self._sn8 = sn8
self._model = model
# Legacy/extended fields
self._device = device
self._config = config or {}
self._rationale = rationale
if (self._config.get("rationale")) is not None:
self._rationale = self._config.get("rationale")
if self._rationale is None:
self._rationale = ["off", "on"]
# Display and identification
self._attr_has_entity_name = True
self._attr_unique_id = f"{sn8}_{self.entity_id_suffix}"
self.entity_id_base = f"midea_{sn8.lower()}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, sn8)},
model=model,
serial_number=sn,
manufacturer="Midea",
name=device_name,
)
# Prefer legacy unique_id scheme if device object is available (device_id based)
if self._device is not None:
self._attr_unique_id = f"{DOMAIN}.{self._device_id}_{self._entity_key}"
self.entity_id_base = f"midea_{self._device_id}"
manu = "Midea" if manufacturer is None else manufacturer
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, str(self._device_id))},
model=self._model,
serial_number=sn,
manufacturer=manu,
name=device_name,
)
# Presentation attributes from config
self._attr_native_unit_of_measurement = self._config.get("unit_of_measurement")
self._attr_device_class = self._config.get("device_class")
self._attr_state_class = self._config.get("state_class")
self._attr_icon = self._config.get("icon")
# Prefer translated name; allow explicit override via config.name
self._attr_translation_key = self._config.get("translation_key") or self._entity_key
name_cfg = self._config.get("name")
if name_cfg is not None:
self._attr_name = f"{name_cfg}"
self.entity_id = self._attr_unique_id
# Register device updates for HA state refresh
try:
self._device.register_update(self.update_state) # type: ignore[attr-defined]
except Exception:
pass
else:
# Fallback to sn8-based unique id/device info
self._attr_unique_id = f"{sn8}_{self.entity_id_suffix}"
self.entity_id_base = f"midea_{sn8.lower()}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, sn8)},
model=model,
serial_number=sn,
manufacturer="Midea",
name=device_name,
)
# Debounced command publishing
self._debounced_publish_command = Debouncer(
@@ -79,14 +124,96 @@ class MideaEntity(CoordinatorEntity[MideaDataUpdateCoordinator], Entity):
@property
def available(self) -> bool:
"""Return if entity is available."""
MideaLogger.debug(f"available available={self.coordinator.data} ")
return self.coordinator.data.available
if self.coordinator.data:
return self.coordinator.data.available
else:
return False
async def _publish_command(self) -> None:
"""Publish commands to the device."""
# This will be implemented by subclasses
pass
# ===== Unified helpers migrated from legacy entity base =====
def _get_status_on_off(self, attribute_key: str | None) -> bool:
"""Return boolean value from device attributes for given key.
Accepts common truthy representations: True/1/"on"/"true".
"""
if attribute_key is None:
return False
value = self.device_attributes.get(attribute_key)
if isinstance(value, bool):
return value
return value in (1, "1", "on", "ON", "true", "TRUE")
async def _async_set_status_on_off(self, attribute_key: str | None, turn_on: bool) -> None:
"""Set boolean attribute via coordinator, no-op if key is None."""
if attribute_key is None:
return
await self.async_set_attribute(attribute_key, bool(turn_on))
def _list_get_selected(self, options: list[dict] | None, rationale: object = None) -> int | None:
"""Select index from a list of dict conditions matched against attributes.
The optional rationale supports equality/greater/less matching. It can be
a string name ("EQUALLY"/"GREATER"/"LESS") or an Enum with .name.
"""
if not options:
return None
rationale_name = getattr(rationale, "name", None) or rationale or "EQUALLY"
for index in range(0, len(options)):
match = True
for attr, expected in options[index].items():
current = self.device_attributes.get(attr)
if current is None:
match = False
break
if rationale_name == "EQUALLY" and current != expected:
match = False
break
if rationale_name == "GREATER" and current < expected:
match = False
break
if rationale_name == "LESS" and current > expected:
match = False
break
if match:
return index
return None
def _dict_get_selected(self, mapping: dict | None, rationale: object = None):
"""Return key from a dict whose value (a condition dict) matches attributes.
The optional rationale supports equality/greater/less matching. It can be
a string name ("EQUALLY"/"GREATER"/"LESS") or an Enum with .name.
"""
if not mapping:
return None
rationale_name = getattr(rationale, "name", None) or rationale or "EQUALLY"
for key, conditions in mapping.items():
if not isinstance(conditions, dict):
continue
match = True
for attr, expected in conditions.items():
current = self.device_attributes.get(attr)
if current is None:
match = False
break
if rationale_name == "EQUALLY" and current != expected:
match = False
break
if rationale_name == "GREATER" and current <= expected:
match = False
break
if rationale_name == "LESS" and current >= expected:
match = False
break
if match:
return key
return None
async def publish_command_from_current_state(self) -> None:
"""Publish commands to the device from current state."""
self.coordinator.mute_state_update_for_a_while()

View File

@@ -1,7 +1,7 @@
from homeassistant.components.select import SelectEntity
from homeassistant.const import Platform
from .const import DOMAIN
from .midea_entities import MideaEntity
from .midea_entity import MideaEntity
from . import load_device_config
@@ -24,13 +24,30 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
coordinator = coordinator_map.get(device_id)
device = coordinator.device if coordinator else None
for entity_key, ecfg in entities_cfg.items():
devs.append(MideaSelectEntity(device, manufacturer, rationale, entity_key, ecfg))
devs.append(MideaSelectEntity(coordinator, device, manufacturer, rationale, entity_key, ecfg))
async_add_entities(devs)
class MideaSelectEntity(MideaEntity, SelectEntity):
def __init__(self, device, manufacturer, rationale, entity_key, config):
super().__init__(device, manufacturer, rationale, entity_key, config)
def __init__(self, coordinator, device, manufacturer, rationale, entity_key, config):
super().__init__(
coordinator,
device.device_id,
device.device_name,
f"T0x{device.device_type:02X}",
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._config = config
self._key_options = self._config.get("options")
@property
@@ -41,13 +58,14 @@ class MideaSelectEntity(MideaEntity, SelectEntity):
def current_option(self):
return self._dict_get_selected(self._key_options)
def select_option(self, option: str):
async def async_select_option(self, option: str):
new_status = self._key_options.get(option)
self._device.set_attributes(new_status)
if new_status:
await self.async_set_attributes(new_status)
def update_state(self, status):
try:
self.schedule_update_ha_state()
except Exception as e:
except Exception:
pass

View File

@@ -5,6 +5,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .core.logger import MideaLogger
from .midea_entity import MideaEntity
from . import load_device_config
@@ -51,19 +52,40 @@ class MideaSensorEntity(MideaEntity, SensorEntity):
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._entity_key = entity_key
self._config = config
@property
def entity_id_suffix(self) -> str:
"""Return the suffix for entity ID."""
return f"sensor_{self._entity_key}"
@property
def native_value(self):
"""Return the native value of the sensor."""
return self.device_attributes.get(self._entity_key)
value = self.device_attributes.get(self._entity_key)
# Handle invalid string values
if isinstance(value, str) and value.lower() in ['invalid', 'none', 'null', '']:
return None
# Try to convert to number if it's a string that looks like a number
if isinstance(value, str):
try:
# Try integer first
if '.' not in value:
return int(value)
# Then float
return float(value)
except (ValueError, TypeError):
# If conversion fails, return None for numeric sensors
# or return the original string for enum sensors
device_class = self._config.get("device_class")
if device_class and "enum" not in device_class.lower():
return None
return value
return value

View File

@@ -27,7 +27,7 @@ async def async_setup_entry(
for device_id, info in device_list.items():
device_type = info.get("type")
sn8 = info.get("sn8")
config = load_device_config(hass, device_type, sn8) or {}
config = await load_device_config(hass, device_type, sn8) or {}
entities_cfg = (config.get("entities") or {}).get(Platform.SWITCH, {})
manufacturer = config.get("manufacturer")
rationale = config.get("rationale")
@@ -52,17 +52,17 @@ class MideaSwitchEntity(MideaEntity, SwitchEntity):
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._entity_key = entity_key
self._config = config
@property
def entity_id_suffix(self) -> str:
"""Return the suffix for entity ID."""
return f"switch_{self._entity_key}"
@property
def is_on(self) -> bool:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ from homeassistant.const import (
ATTR_TEMPERATURE
)
from .const import DOMAIN
from .midea_entities import MideaEntity
from .midea_entity import MideaEntity
from . import load_device_config
@@ -27,13 +27,54 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
coordinator = coordinator_map.get(device_id)
device = coordinator.device if coordinator else None
for entity_key, ecfg in entities_cfg.items():
devs.append(MideaWaterHeaterEntityEntity(device, manufacturer, rationale, entity_key, ecfg))
devs.append(MideaWaterHeaterEntityEntity(coordinator, device, manufacturer, rationale, entity_key, ecfg))
async_add_entities(devs)
class MideaWaterHeaterEntityEntity(MideaEntity, WaterHeaterEntity):
def __init__(self, device, manufacturer, rationale, entity_key, config):
super().__init__(device, manufacturer, rationale, entity_key, config)
def __init__(self, coordinator, device, manufacturer, rationale, entity_key, config):
super().__init__(
coordinator,
device.device_id,
device.device_name,
f"T0x{device.device_type:02X}",
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._device = device
self._manufacturer = manufacturer
self._rationale = rationale
self._config = config
# Legacy compatibility: register update and restore display attributes
if self._device:
self._device.register_update(self.update_state)
if (rationale_local := self._config.get("rationale")) is not None:
self._rationale = rationale_local
if self._rationale is None:
self._rationale = ["off", "on"]
self._attr_native_unit_of_measurement = self._config.get("unit_of_measurement")
self._attr_device_class = self._config.get("device_class")
self._attr_state_class = self._config.get("state_class")
self._attr_icon = self._config.get("icon")
from .const import DOMAIN as _DOMAIN
self._attr_unique_id = f"{_DOMAIN}.{self._device.device_id}_{self._entity_key}"
self._attr_device_info = {
"manufacturer": "Midea" if self._manufacturer is None else self._manufacturer,
"model": f"{self._device.model}",
"identifiers": {( _DOMAIN, self._device.device_id)},
"name": self._device.device_name
}
name = self._config.get("name")
if name is None:
name = self._entity_key.replace("_", " ").title()
self._attr_name = f"{self._device.device_name} {name}"
self.entity_id = self._attr_unique_id
self._key_power = self._config.get("power")
self._key_operation_list = self._config.get("operation_list")
self._key_min_temp = self._config.get("min_temp")
@@ -62,30 +103,30 @@ class MideaWaterHeaterEntityEntity(MideaEntity, WaterHeaterEntity):
@property
def current_temperature(self):
return self._device.get_attribute(self._key_current_temperature)
return self.device_attributes.get(self._key_current_temperature)
@property
def target_temperature(self):
if isinstance(self._key_target_temperature, list):
temp_int = self._device.get_attribute(self._key_target_temperature[0])
tem_dec = self._device.get_attribute(self._key_target_temperature[1])
temp_int = self.device_attributes.get(self._key_target_temperature[0])
tem_dec = self.device_attributes.get(self._key_target_temperature[1])
if temp_int is not None and tem_dec is not None:
return temp_int + tem_dec
return None
else:
return self._device.get_attribute(self._key_target_temperature)
return self.device_attributes.get(self._key_target_temperature)
@property
def min_temp(self):
if isinstance(self._key_min_temp, str):
return float(self._device.get_attribute(self._key_min_temp))
return float(self.device_attributes.get(self._key_min_temp))
else:
return float(self._key_min_temp)
@property
def max_temp(self):
if isinstance(self._key_max_temp, str):
return float(self._device.get_attribute(self._key_max_temp))
return float(self.device_attributes.get(self._key_max_temp))
else:
return float(self._key_max_temp)
@@ -101,13 +142,13 @@ class MideaWaterHeaterEntityEntity(MideaEntity, WaterHeaterEntity):
def is_on(self) -> bool:
return self._get_status_on_off(self._key_power)
def turn_on(self):
self._set_status_on_off(self._key_power, True)
async def async_turn_on(self):
await self._async_set_status_on_off(self._key_power, True)
def turn_off(self):
self._set_status_on_off(self._key_power, False)
async def async_turn_off(self):
await self._async_set_status_on_off(self._key_power, False)
def set_temperature(self, **kwargs):
async def async_set_temperature(self, **kwargs):
if ATTR_TEMPERATURE not in kwargs:
return
temperature = kwargs.get(ATTR_TEMPERATURE)
@@ -119,15 +160,16 @@ class MideaWaterHeaterEntityEntity(MideaEntity, WaterHeaterEntity):
new_status[self._key_target_temperature[1]] = temp_dec
else:
new_status[self._key_target_temperature] = temperature
self._device.set_attributes(new_status)
await self.async_set_attributes(new_status)
def set_operation_mode(self, operation_mode: str) -> None:
async def async_set_operation_mode(self, operation_mode: str) -> None:
new_status = self._key_operation_list.get(operation_mode)
self._device.set_attributes(new_status)
if new_status:
await self.async_set_attributes(new_status)
def update_state(self, status):
try:
self.schedule_update_ha_state()
except Exception as e:
except Exception:
pass

View File

@@ -1,5 +1,5 @@
{
"name": "Midea Auto Codec",
"name": "Midea Auto Cloud",
"render_readme": true,
"homeassistant": "2024.11.0"
}

BIN
img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
img_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB