Initial Home Assistant commit
This commit is contained in:
@@ -0,0 +1,346 @@
|
||||
"""Init for Midea LAN.
|
||||
|
||||
integration load process:
|
||||
1. component setup: `async_setup`
|
||||
1.1 use `hass.services.async_register` to register service
|
||||
2. config entry setup: `async_setup_entry`
|
||||
2.1 forward the Config Entry to the platform `async_forward_entry_setups`
|
||||
2.2 register listener `update_listener`
|
||||
3. unloading a config entry: `async_unload_entry`
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import homeassistant.helpers.device_registry as dr
|
||||
import voluptuous as vol
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_CUSTOMIZE,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_IP_ADDRESS,
|
||||
CONF_NAME,
|
||||
CONF_PORT,
|
||||
CONF_PROTOCOL,
|
||||
CONF_TOKEN,
|
||||
CONF_TYPE,
|
||||
MAJOR_VERSION,
|
||||
MINOR_VERSION,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from midealocal.device import DeviceType, MideaDevice, ProtocolVersion
|
||||
from midealocal.devices import device_selector
|
||||
|
||||
from .const import (
|
||||
ALL_PLATFORM,
|
||||
CONF_ACCOUNT,
|
||||
CONF_KEY,
|
||||
CONF_MODEL,
|
||||
CONF_REFRESH_INTERVAL,
|
||||
CONF_SUBTYPE,
|
||||
DEVICES,
|
||||
DOMAIN,
|
||||
EXTRA_SWITCH,
|
||||
)
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
|
||||
"""Option flow signal update.
|
||||
|
||||
register update listener for config entry that will be called when entry is updated.
|
||||
A listener is registered by adding the following to the `async_setup_entry`:
|
||||
`config_entry.async_on_unload(config_entry.add_update_listener(update_listener))`
|
||||
means the Listener is attached when the entry is loaded and detached at unload
|
||||
"""
|
||||
# Forward the unloading of an entry to platforms.
|
||||
await hass.config_entries.async_unload_platforms(config_entry, ALL_PLATFORM)
|
||||
# forward the Config Entry to the platforms
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setups(config_entry, ALL_PLATFORM),
|
||||
)
|
||||
device_id: int = cast("int", config_entry.data.get(CONF_DEVICE_ID))
|
||||
customize = config_entry.options.get(CONF_CUSTOMIZE, "")
|
||||
ip_address = config_entry.options.get(CONF_IP_ADDRESS, None)
|
||||
refresh_interval = config_entry.options.get(CONF_REFRESH_INTERVAL, None)
|
||||
dev: MideaDevice = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
if dev:
|
||||
dev.set_customize(customize)
|
||||
if ip_address is not None:
|
||||
dev.set_ip_address(ip_address)
|
||||
if refresh_interval is not None:
|
||||
dev.set_refresh_interval(refresh_interval)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: ARG001
|
||||
"""Set up midea_lan component when load this integration.
|
||||
|
||||
Returns
|
||||
-------
|
||||
True if entry is configured.
|
||||
|
||||
"""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
attributes = []
|
||||
for device_entities in MIDEA_DEVICES.values():
|
||||
for attribute_name, attribute in cast(
|
||||
"dict",
|
||||
device_entities["entities"],
|
||||
).items():
|
||||
if (
|
||||
attribute.get("type") in EXTRA_SWITCH
|
||||
and attribute_name.value not in attributes
|
||||
):
|
||||
attributes.append(attribute_name.value)
|
||||
|
||||
def service_set_attribute(service: Any) -> None: # noqa: ANN401
|
||||
"""Set service attribute func."""
|
||||
device_id: int = service.data["device_id"]
|
||||
attr = service.data["attribute"]
|
||||
value = service.data["value"]
|
||||
dev: MideaDevice = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
if dev:
|
||||
if attr == "fan_speed" and value == "auto":
|
||||
value = 102
|
||||
item = None
|
||||
if dev_ := MIDEA_DEVICES.get(dev.device_type):
|
||||
item = cast("dict", dev_["entities"]).get(attr)
|
||||
if (
|
||||
item
|
||||
and (item.get("type") in EXTRA_SWITCH)
|
||||
or (
|
||||
dev.device_type == DeviceType.AC
|
||||
and attr == "fan_speed"
|
||||
and value in range(103)
|
||||
)
|
||||
):
|
||||
dev.set_attribute(attr=attr, value=value)
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"Appliance [%s] has no attribute %s or value is invalid",
|
||||
device_id,
|
||||
attr,
|
||||
)
|
||||
|
||||
def service_send_command(service: Any) -> None: # noqa: ANN401
|
||||
"""Send command to service func."""
|
||||
device_id = service.data.get("device_id")
|
||||
cmd_type = service.data.get("cmd_type")
|
||||
cmd_body = service.data.get("cmd_body")
|
||||
try:
|
||||
cmd_body = bytearray.fromhex(cmd_body)
|
||||
except ValueError:
|
||||
_LOGGER.exception(
|
||||
"Appliance [%s] invalid cmd_body, a hexadecimal string required",
|
||||
device_id,
|
||||
)
|
||||
return
|
||||
dev = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
if dev:
|
||||
dev.send_command(cmd_type, cmd_body)
|
||||
|
||||
# register service func calls:
|
||||
# `service_set_attribute`, service.yaml key: `set_attribute`
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
"set_attribute",
|
||||
service_set_attribute,
|
||||
schema=vol.Schema(
|
||||
{
|
||||
vol.Required("device_id"): vol.Coerce(int),
|
||||
vol.Required("attribute"): vol.In(attributes),
|
||||
vol.Required("value"): vol.Any(int, cv.boolean, str),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
# register service func calls:
|
||||
# `service_send_command`, service.yaml key: `send_command`
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
"send_command",
|
||||
service_send_command,
|
||||
schema=vol.Schema(
|
||||
{
|
||||
vol.Required("device_id"): vol.Coerce(int),
|
||||
vol.Required("cmd_type"): vol.In([2, 3]),
|
||||
vol.Required("cmd_body"): str,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Set up platform for current integration.
|
||||
|
||||
Returns
|
||||
-------
|
||||
True if entry is configured.
|
||||
|
||||
"""
|
||||
device_type = config_entry.data.get(CONF_TYPE)
|
||||
if device_type == CONF_ACCOUNT:
|
||||
return True
|
||||
name = config_entry.data.get(CONF_NAME)
|
||||
device_id: int = config_entry.data[CONF_DEVICE_ID]
|
||||
if name is None:
|
||||
name = f"{device_id}"
|
||||
if device_type is None:
|
||||
device_type = 0xAC
|
||||
token: str = config_entry.data.get(CONF_TOKEN) or ""
|
||||
key: str = config_entry.data.get(CONF_KEY) or ""
|
||||
ip_address = config_entry.options.get(CONF_IP_ADDRESS, None)
|
||||
if ip_address is None:
|
||||
ip_address = config_entry.data.get(CONF_IP_ADDRESS)
|
||||
refresh_interval = config_entry.options.get(CONF_REFRESH_INTERVAL)
|
||||
port: int = config_entry.data[CONF_PORT]
|
||||
model: str = config_entry.data[CONF_MODEL]
|
||||
subtype = config_entry.data.get(CONF_SUBTYPE, 0)
|
||||
protocol: ProtocolVersion = ProtocolVersion(config_entry.data[CONF_PROTOCOL])
|
||||
customize: str = config_entry.options.get(CONF_CUSTOMIZE, "")
|
||||
if protocol == ProtocolVersion.V3 and (key == "" or token == ""):
|
||||
_LOGGER.error("For V3 devices, the key and the token is required")
|
||||
return False
|
||||
# device_selector in `midealocal/devices/__init__.py`
|
||||
# hass core version >= 2024.3
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 3):
|
||||
device = await hass.async_add_import_executor_job(
|
||||
device_selector,
|
||||
name,
|
||||
device_id,
|
||||
device_type,
|
||||
ip_address,
|
||||
port,
|
||||
token,
|
||||
key,
|
||||
protocol,
|
||||
model,
|
||||
subtype,
|
||||
customize,
|
||||
)
|
||||
# hass core version < 2024.3
|
||||
else:
|
||||
device = device_selector(
|
||||
name=name,
|
||||
device_id=device_id,
|
||||
device_type=device_type,
|
||||
ip_address=ip_address,
|
||||
port=port,
|
||||
token=token,
|
||||
key=key,
|
||||
device_protocol=protocol,
|
||||
model=model,
|
||||
subtype=subtype,
|
||||
customize=customize,
|
||||
)
|
||||
if device:
|
||||
if refresh_interval is not None:
|
||||
device.set_refresh_interval(refresh_interval)
|
||||
device.open()
|
||||
if DOMAIN not in hass.data:
|
||||
hass.data[DOMAIN] = {}
|
||||
if DEVICES not in hass.data[DOMAIN]:
|
||||
hass.data[DOMAIN][DEVICES] = {}
|
||||
hass.data[DOMAIN][DEVICES][device_id] = device
|
||||
# Forward the setup of an entry to all platforms
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, ALL_PLATFORM)
|
||||
# Listener `update_listener` is
|
||||
# attached when the entry is loaded
|
||||
# and detached when it's unloaded
|
||||
config_entry.async_on_unload(config_entry.add_update_listener(update_listener))
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Clean up entities, unsubscribe event listener and close all connections.
|
||||
|
||||
Returns
|
||||
-------
|
||||
True if entry is unloaded.
|
||||
|
||||
"""
|
||||
device_type = config_entry.data.get(CONF_TYPE)
|
||||
if device_type == CONF_ACCOUNT:
|
||||
return True
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
if device_id is not None:
|
||||
dm = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
if dm is not None:
|
||||
try:
|
||||
dm.close()
|
||||
except (OSError, ConnectionError, AttributeError) as e:
|
||||
_LOGGER.warning("Failed to close Midea socket cleanly: %s", e)
|
||||
hass.data[DOMAIN][DEVICES].pop(device_id)
|
||||
# Forward the unloading of an entry to platforms
|
||||
await hass.config_entries.async_unload_platforms(config_entry, ALL_PLATFORM)
|
||||
return True
|
||||
|
||||
|
||||
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Migrate old entry.
|
||||
|
||||
Returns
|
||||
-------
|
||||
True if entry is migrated.
|
||||
|
||||
"""
|
||||
# 1 -> 2: convert device identifiers from int to str
|
||||
if config_entry.version == 1:
|
||||
_LOGGER.debug("Migrating configuration from version 1")
|
||||
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 3):
|
||||
hass.config_entries.async_update_entry(config_entry, version=2)
|
||||
else:
|
||||
config_entry.version = 2
|
||||
hass.config_entries.async_update_entry(config_entry)
|
||||
|
||||
# Migrate device.
|
||||
await _async_migrate_device_identifiers(hass, config_entry)
|
||||
|
||||
_LOGGER.debug("Migration to configuration version 2 successful")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def _async_migrate_device_identifiers(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
) -> None:
|
||||
"""Migrate the device identifiers to the new format."""
|
||||
device_registry = dr.async_get(hass)
|
||||
device_entry_found = False
|
||||
for device_entry in dr.async_entries_for_config_entry(
|
||||
device_registry,
|
||||
config_entry.entry_id,
|
||||
):
|
||||
for identifier in device_entry.identifiers:
|
||||
# Device found in registry. Update identifiers.
|
||||
new_identifiers = {
|
||||
(
|
||||
DOMAIN,
|
||||
str(identifier[1]),
|
||||
),
|
||||
}
|
||||
_LOGGER.debug(
|
||||
"Migrating device identifiers from %s to %s",
|
||||
device_entry.identifiers,
|
||||
new_identifiers,
|
||||
)
|
||||
device_registry.async_update_device(
|
||||
device_id=device_entry.id,
|
||||
new_identifiers=new_identifiers,
|
||||
)
|
||||
# Device entry found. Leave inner for loop.
|
||||
device_entry_found = True
|
||||
break
|
||||
|
||||
# Leave outer for loop if device entry is already found.
|
||||
if device_entry_found:
|
||||
break
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,50 @@
|
||||
"""Binary sensor for Midea Lan."""
|
||||
|
||||
from typing import cast
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SENSORS, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up sensors for device."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_sensors = config_entry.options.get(CONF_SENSORS, [])
|
||||
binary_sensors = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.BINARY_SENSOR and entity_key in extra_sensors:
|
||||
sensor = MideaBinarySensor(device, entity_key)
|
||||
binary_sensors.append(sensor)
|
||||
async_add_entities(binary_sensors)
|
||||
|
||||
|
||||
class MideaBinarySensor(MideaEntity, BinarySensorEntity):
|
||||
"""Represent a Midea binary sensor."""
|
||||
|
||||
@property
|
||||
def device_class(self) -> BinarySensorDeviceClass | None:
|
||||
"""Return device class."""
|
||||
return cast("BinarySensorDeviceClass", self._config.get("device_class"))
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if sensor state is on."""
|
||||
return cast("bool", self._device.get_attribute(self._entity_key))
|
||||
@@ -0,0 +1,707 @@
|
||||
"""Midea Climate entries."""
|
||||
|
||||
import logging
|
||||
from typing import Any, ClassVar, TypeAlias, cast
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ATTR_HVAC_MODE,
|
||||
FAN_AUTO,
|
||||
FAN_HIGH,
|
||||
FAN_LOW,
|
||||
FAN_MEDIUM,
|
||||
PRESET_AWAY,
|
||||
PRESET_BOOST,
|
||||
PRESET_COMFORT,
|
||||
PRESET_ECO,
|
||||
PRESET_NONE,
|
||||
PRESET_SLEEP,
|
||||
SWING_BOTH,
|
||||
SWING_HORIZONTAL,
|
||||
SWING_OFF,
|
||||
SWING_ON,
|
||||
SWING_VERTICAL,
|
||||
ClimateEntity,
|
||||
ClimateEntityFeature,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_TEMPERATURE,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_SWITCHES,
|
||||
MAJOR_VERSION,
|
||||
MINOR_VERSION,
|
||||
PRECISION_HALVES,
|
||||
PRECISION_WHOLE,
|
||||
Platform,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealocal.device import DeviceType
|
||||
from midealocal.devices.ac import DeviceAttributes as ACAttributes
|
||||
from midealocal.devices.ac import MideaACDevice
|
||||
from midealocal.devices.c3 import DeviceAttributes as C3Attributes
|
||||
from midealocal.devices.c3 import MideaC3Device
|
||||
from midealocal.devices.cc import DeviceAttributes as CCAttributes
|
||||
from midealocal.devices.cc import MideaCCDevice
|
||||
from midealocal.devices.cf import DeviceAttributes as CFAttributes
|
||||
from midealocal.devices.cf import MideaCFDevice
|
||||
from midealocal.devices.fb import DeviceAttributes as FBAttributes
|
||||
from midealocal.devices.fb import MideaFBDevice
|
||||
|
||||
from .const import DEVICES, DOMAIN, FanSpeed
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
TEMPERATURE_MAX = 30
|
||||
TEMPERATURE_MIN = 16
|
||||
|
||||
FAN_SILENT = "silent"
|
||||
FAN_FULL_SPEED = "full"
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up climate entries."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
devs: list[
|
||||
MideaACClimate
|
||||
| MideaCCClimate
|
||||
| MideaCFClimate
|
||||
| MideaC3Climate
|
||||
| MideaFBClimate
|
||||
] = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.CLIMATE and (
|
||||
config.get("default") or entity_key in extra_switches
|
||||
):
|
||||
if device.device_type == DeviceType.AC:
|
||||
# add config_entry args to fix indoor_humidity error bug
|
||||
devs.append(MideaACClimate(device, entity_key, config_entry))
|
||||
elif device.device_type == DeviceType.CC:
|
||||
devs.append(MideaCCClimate(device, entity_key))
|
||||
elif device.device_type == DeviceType.CF:
|
||||
devs.append(MideaCFClimate(device, entity_key))
|
||||
elif device.device_type == DeviceType.C3:
|
||||
devs.append(MideaC3Climate(device, entity_key, config["zone"]))
|
||||
elif device.device_type == DeviceType.FB:
|
||||
devs.append(MideaFBClimate(device, entity_key))
|
||||
async_add_entities(devs)
|
||||
|
||||
|
||||
MideaClimateDevice: TypeAlias = (
|
||||
MideaACDevice | MideaCCDevice | MideaCFDevice | MideaC3Device | MideaFBDevice
|
||||
)
|
||||
|
||||
|
||||
class MideaClimate(MideaEntity, ClimateEntity):
|
||||
"""Midea Climate Entries Base Class."""
|
||||
|
||||
# https://developers.home-assistant.io/blog/2024/01/24/climate-climateentityfeatures-expanded
|
||||
_enable_turn_on_off_backwards_compatibility: bool = (
|
||||
False # maybe remove after 2025.1
|
||||
)
|
||||
|
||||
_device: MideaClimateDevice
|
||||
|
||||
_attr_max_temp: float = TEMPERATURE_MAX
|
||||
_attr_min_temp: float = TEMPERATURE_MIN
|
||||
_attr_target_temperature_high: float | None = TEMPERATURE_MAX
|
||||
_attr_target_temperature_low: float | None = TEMPERATURE_MIN
|
||||
_attr_temperature_unit: str = UnitOfTemperature.CELSIUS
|
||||
|
||||
def __init__(self, device: MideaClimateDevice, entity_key: str) -> None:
|
||||
"""Midea Climate entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
|
||||
@property
|
||||
def supported_features(self) -> ClimateEntityFeature:
|
||||
"""Midea Climate supported features."""
|
||||
features = (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.FAN_MODE
|
||||
| ClimateEntityFeature.PRESET_MODE
|
||||
| ClimateEntityFeature.SWING_MODE
|
||||
)
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
|
||||
features |= ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
|
||||
return features
|
||||
|
||||
@property
|
||||
def hvac_mode(self) -> HVACMode:
|
||||
"""Midea Climate hvac mode."""
|
||||
if self._device.get_attribute("power"):
|
||||
mode = cast("int", self._device.get_attribute("mode"))
|
||||
return self.hvac_modes[mode]
|
||||
return HVACMode.OFF
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float:
|
||||
"""Midea Climate target temperature."""
|
||||
return cast("float", self._device.get_attribute("target_temperature"))
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Midea Climate current temperature."""
|
||||
return cast("float | None", self._device.get_attribute("indoor_temperature"))
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str:
|
||||
"""Midea Climate preset mode."""
|
||||
if self._device.get_attribute("comfort_mode"):
|
||||
mode = PRESET_COMFORT
|
||||
elif self._device.get_attribute("eco_mode"):
|
||||
mode = PRESET_ECO
|
||||
elif self._device.get_attribute("boost_mode"):
|
||||
mode = PRESET_BOOST
|
||||
elif self._device.get_attribute("sleep_mode"):
|
||||
mode = PRESET_SLEEP
|
||||
elif self._device.get_attribute("frost_protect"):
|
||||
mode = PRESET_AWAY
|
||||
else:
|
||||
mode = PRESET_NONE
|
||||
return str(mode)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict:
|
||||
"""Midea Climate extra state attributes."""
|
||||
return cast("dict", self._device.attributes)
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Climate turn on."""
|
||||
self._device.set_attribute(attr="power", value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Climate turn off."""
|
||||
self._device.set_attribute(attr="power", value=False)
|
||||
|
||||
def set_temperature(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea Climate set temperature."""
|
||||
if ATTR_TEMPERATURE not in kwargs:
|
||||
return
|
||||
temperature = float(int((float(kwargs[ATTR_TEMPERATURE]) * 2) + 0.5)) / 2
|
||||
hvac_mode = kwargs.get(ATTR_HVAC_MODE)
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
self.turn_off()
|
||||
else:
|
||||
try:
|
||||
mode = self.hvac_modes.index(hvac_mode.lower()) if hvac_mode else None
|
||||
self._device.set_target_temperature(
|
||||
target_temperature=temperature,
|
||||
mode=mode,
|
||||
zone=None,
|
||||
)
|
||||
except ValueError:
|
||||
_LOGGER.exception("Error setting temperature with: %s", kwargs)
|
||||
|
||||
def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Midea Climate set hvac mode."""
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
self.turn_off()
|
||||
else:
|
||||
self._device.set_attribute(
|
||||
attr="mode",
|
||||
value=self.hvac_modes.index(hvac_mode),
|
||||
)
|
||||
|
||||
def set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Midea Climate set preset mode."""
|
||||
old_mode = self.preset_mode
|
||||
preset_mode = preset_mode.lower()
|
||||
if preset_mode == PRESET_AWAY:
|
||||
self._device.set_attribute(attr="frost_protect", value=True)
|
||||
elif preset_mode == PRESET_COMFORT:
|
||||
self._device.set_attribute(attr="comfort_mode", value=True)
|
||||
elif preset_mode == PRESET_SLEEP:
|
||||
self._device.set_attribute(attr="sleep_mode", value=True)
|
||||
elif preset_mode == PRESET_ECO:
|
||||
self._device.set_attribute(attr="eco_mode", value=True)
|
||||
elif preset_mode == PRESET_BOOST:
|
||||
self._device.set_attribute(attr="boost_mode", value=True)
|
||||
elif old_mode == PRESET_AWAY:
|
||||
self._device.set_attribute(attr="frost_protect", value=False)
|
||||
elif old_mode == PRESET_COMFORT:
|
||||
self._device.set_attribute(attr="comfort_mode", value=False)
|
||||
elif old_mode == PRESET_SLEEP:
|
||||
self._device.set_attribute(attr="sleep_mode", value=False)
|
||||
elif old_mode == PRESET_ECO:
|
||||
self._device.set_attribute(attr="eco_mode", value=False)
|
||||
elif old_mode == PRESET_BOOST:
|
||||
self._device.set_attribute(attr="boost_mode", value=False)
|
||||
|
||||
def update_state(self, status: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Climate update state."""
|
||||
if not self.hass:
|
||||
_LOGGER.warning(
|
||||
"Climate update_state skipped for %s [%s]: HASS is None",
|
||||
self.name,
|
||||
type(self),
|
||||
)
|
||||
return
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
|
||||
class MideaACClimate(MideaClimate):
|
||||
"""Midea AC Climate Entries."""
|
||||
|
||||
_device: MideaACDevice
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
device: MideaACDevice,
|
||||
entity_key: str,
|
||||
config_entry: ConfigEntry,
|
||||
) -> None:
|
||||
"""Midea AC Climate entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_hvac_modes = [
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
HVACMode.COOL,
|
||||
HVACMode.DRY,
|
||||
HVACMode.HEAT,
|
||||
HVACMode.FAN_ONLY,
|
||||
]
|
||||
self._fan_speeds: dict[str, int] = {
|
||||
FAN_SILENT: 20,
|
||||
FAN_LOW: 40,
|
||||
FAN_MEDIUM: 60,
|
||||
FAN_HIGH: 80,
|
||||
FAN_FULL_SPEED: 100,
|
||||
FAN_AUTO: 102,
|
||||
}
|
||||
self._attr_swing_modes: list[str] = [
|
||||
SWING_OFF,
|
||||
SWING_VERTICAL,
|
||||
SWING_HORIZONTAL,
|
||||
SWING_BOTH,
|
||||
]
|
||||
self._attr_preset_modes = [
|
||||
PRESET_NONE,
|
||||
PRESET_COMFORT,
|
||||
PRESET_ECO,
|
||||
PRESET_BOOST,
|
||||
PRESET_SLEEP,
|
||||
PRESET_AWAY,
|
||||
]
|
||||
self._attr_fan_modes = list(self._fan_speeds.keys())
|
||||
# fix error humidity value, disable indoor_humidity
|
||||
# add config_entry args to fix indoor_humidity error bug
|
||||
self._indoor_humidity_enabled = (
|
||||
"sensors" in config_entry.options
|
||||
and "indoor_humidity" in config_entry.options["sensors"]
|
||||
)
|
||||
|
||||
@property
|
||||
def fan_mode(self) -> str:
|
||||
"""Midea AC Climate fan mode."""
|
||||
fan_speed = cast("int", self._device.get_attribute(ACAttributes.fan_speed))
|
||||
if fan_speed > FanSpeed.AUTO:
|
||||
return str(FAN_AUTO)
|
||||
if fan_speed > FanSpeed.FULL_SPEED:
|
||||
return str(FAN_FULL_SPEED)
|
||||
if fan_speed > FanSpeed.HIGH:
|
||||
return str(FAN_HIGH)
|
||||
if fan_speed > FanSpeed.MEDIUM:
|
||||
return str(FAN_MEDIUM)
|
||||
if fan_speed > FanSpeed.LOW:
|
||||
return str(FAN_LOW)
|
||||
return str(FAN_SILENT)
|
||||
|
||||
@property
|
||||
def target_temperature_step(self) -> float:
|
||||
"""Midea AC Climate target temperature step."""
|
||||
return float(
|
||||
PRECISION_WHOLE if self._device.temperature_step == 1 else PRECISION_HALVES,
|
||||
)
|
||||
|
||||
@property
|
||||
def swing_mode(self) -> str:
|
||||
"""Midea AC Climate swing mode."""
|
||||
swing_mode = (
|
||||
1 if self._device.get_attribute(ACAttributes.swing_vertical) else 0
|
||||
) + (2 if self._device.get_attribute(ACAttributes.swing_horizontal) else 0)
|
||||
return self._attr_swing_modes[swing_mode]
|
||||
|
||||
@property
|
||||
def current_humidity(self) -> float | None:
|
||||
"""Return the current indoor humidity, or None if unavailable."""
|
||||
# fix error humidity, disable indoor_humidity in web UI
|
||||
# https://github.com/wuwentao/midea_ac_lan/pull/641
|
||||
if not self._indoor_humidity_enabled:
|
||||
return None
|
||||
raw = self._device.get_attribute("indoor_humidity")
|
||||
if isinstance(raw, (int, float)) and raw not in {0, 0xFF}:
|
||||
return float(raw)
|
||||
# indoor_humidity is 0 or 255, return None
|
||||
# https://github.com/wuwentao/midea_ac_lan/pull/614
|
||||
return None
|
||||
|
||||
@property
|
||||
def outdoor_temperature(self) -> float:
|
||||
"""Midea AC Climate outdoor temperature."""
|
||||
return cast(
|
||||
"float",
|
||||
self._device.get_attribute(ACAttributes.outdoor_temperature),
|
||||
)
|
||||
|
||||
def set_fan_mode(self, fan_mode: str) -> None:
|
||||
"""Midea AC Climate set fan mode."""
|
||||
fan_speed = self._fan_speeds.get(fan_mode)
|
||||
if fan_speed:
|
||||
self._device.set_attribute(attr=ACAttributes.fan_speed, value=fan_speed)
|
||||
|
||||
def set_swing_mode(self, swing_mode: str) -> None:
|
||||
"""Midea AC Climate set swing mode."""
|
||||
swing = self._attr_swing_modes.index(swing_mode)
|
||||
swing_vertical = swing & 1 > 0
|
||||
swing_horizontal = swing & 2 > 0
|
||||
self._device.set_swing(
|
||||
swing_vertical=swing_vertical,
|
||||
swing_horizontal=swing_horizontal,
|
||||
)
|
||||
|
||||
|
||||
class MideaCCClimate(MideaClimate):
|
||||
"""Midea CC Climate Entries Base Class."""
|
||||
|
||||
_device: MideaCCDevice
|
||||
|
||||
def __init__(self, device: MideaCCDevice, entity_key: str) -> None:
|
||||
"""Midea CC Climate entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_hvac_modes = [
|
||||
HVACMode.OFF,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.DRY,
|
||||
HVACMode.HEAT,
|
||||
HVACMode.COOL,
|
||||
HVACMode.AUTO,
|
||||
]
|
||||
self._attr_swing_modes = [SWING_OFF, SWING_ON]
|
||||
self._attr_preset_modes = [PRESET_NONE, PRESET_SLEEP, PRESET_ECO]
|
||||
|
||||
@property
|
||||
def fan_modes(self) -> list[str] | None:
|
||||
"""Midea CC Climate fan modes."""
|
||||
return cast("list", self._device.fan_modes)
|
||||
|
||||
@property
|
||||
def fan_mode(self) -> str:
|
||||
"""Midea CC Climate fan mode."""
|
||||
return cast("str", self._device.get_attribute(CCAttributes.fan_speed))
|
||||
|
||||
@property
|
||||
def target_temperature_step(self) -> float:
|
||||
"""Midea CC Climate target temperature step."""
|
||||
return cast(
|
||||
"float",
|
||||
self._device.get_attribute(CCAttributes.temperature_precision),
|
||||
)
|
||||
|
||||
@property
|
||||
def swing_mode(self) -> str:
|
||||
"""Midea CC Climate swing mode."""
|
||||
return str(
|
||||
SWING_ON if self._device.get_attribute(CCAttributes.swing) else SWING_OFF,
|
||||
)
|
||||
|
||||
def set_fan_mode(self, fan_mode: str) -> None:
|
||||
"""Midea CC Climate set fan mode."""
|
||||
self._device.set_attribute(attr=CCAttributes.fan_speed, value=fan_mode)
|
||||
|
||||
def set_swing_mode(self, swing_mode: str) -> None:
|
||||
"""Midea CC Climate set swing mode."""
|
||||
self._device.set_attribute(
|
||||
attr=CCAttributes.swing,
|
||||
value=swing_mode == SWING_ON,
|
||||
)
|
||||
|
||||
|
||||
class MideaCFClimate(MideaClimate):
|
||||
"""Midea CF Climate Entries."""
|
||||
|
||||
_device: MideaCFDevice
|
||||
|
||||
_attr_target_temperature_step: float | None = PRECISION_WHOLE
|
||||
|
||||
def __init__(self, device: MideaCFDevice, entity_key: str) -> None:
|
||||
"""Midea CF Climate entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_hvac_modes = [
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
HVACMode.COOL,
|
||||
HVACMode.HEAT,
|
||||
]
|
||||
|
||||
@property
|
||||
def supported_features(self) -> ClimateEntityFeature:
|
||||
"""Midea CF Climate supported features."""
|
||||
features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
|
||||
features |= ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
|
||||
return features
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea CF Climate min temperature."""
|
||||
return cast("float", self._device.get_attribute(CFAttributes.min_temperature))
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea CF Climate max temperature."""
|
||||
return cast("float", self._device.get_attribute(CFAttributes.max_temperature))
|
||||
|
||||
@property
|
||||
def target_temperature_low(self) -> float:
|
||||
"""Midea CF Climate target temperature."""
|
||||
return cast("float", self._device.get_attribute(CFAttributes.min_temperature))
|
||||
|
||||
@property
|
||||
def target_temperature_high(self) -> float:
|
||||
"""Midea CF Climate target temperature high."""
|
||||
return cast("float", self._device.get_attribute(CFAttributes.max_temperature))
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float:
|
||||
"""Midea CF Climate current temperature."""
|
||||
return cast(
|
||||
"float",
|
||||
self._device.get_attribute(CFAttributes.current_temperature),
|
||||
)
|
||||
|
||||
|
||||
class MideaC3Climate(MideaClimate):
|
||||
"""Midea C3 Climate Entries."""
|
||||
|
||||
_device: MideaC3Device
|
||||
|
||||
_powers: ClassVar[list[C3Attributes]] = [
|
||||
C3Attributes.zone1_power,
|
||||
C3Attributes.zone2_power,
|
||||
]
|
||||
|
||||
def __init__(self, device: MideaC3Device, entity_key: str, zone: int) -> None:
|
||||
"""Midea C3 Climate entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._zone = zone
|
||||
self._attr_hvac_modes = [
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
HVACMode.COOL,
|
||||
HVACMode.HEAT,
|
||||
]
|
||||
self._power_attr = MideaC3Climate._powers[zone]
|
||||
|
||||
def _temperature(self, minimum: bool) -> list[str]:
|
||||
"""Midea C3 Climate temperature.
|
||||
|
||||
Returns
|
||||
-------
|
||||
List of temperatures
|
||||
|
||||
"""
|
||||
# fmt: off
|
||||
value = (C3Attributes.temperature_min
|
||||
if minimum
|
||||
else C3Attributes.temperature_max)
|
||||
# fmt: on
|
||||
return cast("list[str]", self._device.get_attribute(value))
|
||||
|
||||
@property
|
||||
def supported_features(self) -> ClimateEntityFeature:
|
||||
"""Midea C3 Climate supported features."""
|
||||
features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
|
||||
features |= ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
|
||||
return features
|
||||
|
||||
@property
|
||||
def target_temperature_step(self) -> float:
|
||||
"""Midea C3 Climate target temperature step."""
|
||||
zone_temp_type = cast(
|
||||
"list[str]",
|
||||
self._device.get_attribute(C3Attributes.zone_temp_type),
|
||||
)
|
||||
return float(
|
||||
PRECISION_WHOLE if zone_temp_type[self._zone] else PRECISION_HALVES,
|
||||
)
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea C3 Climate min temperature."""
|
||||
return cast(
|
||||
"float",
|
||||
self._temperature(True)[self._zone],
|
||||
)
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea C3 Climate max temperature."""
|
||||
return cast(
|
||||
"float",
|
||||
self._temperature(False)[self._zone],
|
||||
)
|
||||
|
||||
@property
|
||||
def target_temperature_low(self) -> float:
|
||||
"""Midea C3 Climate target temperature low."""
|
||||
return cast(
|
||||
"float",
|
||||
self._temperature(True)[self._zone],
|
||||
)
|
||||
|
||||
@property
|
||||
def target_temperature_high(self) -> float:
|
||||
"""Midea C3 Climate target temperature high."""
|
||||
return cast(
|
||||
"float",
|
||||
self._temperature(False)[self._zone],
|
||||
)
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea C3 Climate turn on."""
|
||||
self._device.set_attribute(attr=self._power_attr, value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea C3 Climate turn off."""
|
||||
self._device.set_attribute(attr=self._power_attr, value=False)
|
||||
|
||||
@property
|
||||
def hvac_mode(self) -> HVACMode:
|
||||
"""Midea C3 Climate hvac mode."""
|
||||
mode = self._device.get_attribute(C3Attributes.mode)
|
||||
if self._device.get_attribute(self._power_attr) and isinstance(mode, int):
|
||||
return self.hvac_modes[mode]
|
||||
return HVACMode.OFF
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float:
|
||||
"""Midea C3 Climate target temperature."""
|
||||
target_temperature = cast(
|
||||
"list[str]",
|
||||
self._device.get_attribute(C3Attributes.target_temperature),
|
||||
)
|
||||
return cast(
|
||||
"float",
|
||||
target_temperature[self._zone],
|
||||
)
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Midea C3 Climate current temperature."""
|
||||
return None
|
||||
|
||||
def set_temperature(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea C3 Climate set temperature."""
|
||||
if ATTR_TEMPERATURE not in kwargs:
|
||||
return
|
||||
temperature = float(int((float(kwargs[ATTR_TEMPERATURE]) * 2) + 0.5)) / 2
|
||||
hvac_mode = kwargs.get(ATTR_HVAC_MODE)
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
self.turn_off()
|
||||
else:
|
||||
try:
|
||||
mode = self.hvac_modes.index(hvac_mode.lower()) if hvac_mode else None
|
||||
self._device.set_target_temperature(
|
||||
target_temperature=temperature,
|
||||
mode=mode,
|
||||
zone=self._zone,
|
||||
)
|
||||
except ValueError:
|
||||
_LOGGER.exception("Error setting temperature with: %s", kwargs)
|
||||
|
||||
def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Midea C3 Climate set hvac mode."""
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
self.turn_off()
|
||||
else:
|
||||
self._device.set_mode(self._zone, self.hvac_modes.index(hvac_mode))
|
||||
|
||||
|
||||
class MideaFBClimate(MideaClimate):
|
||||
"""Midea FB Climate Entries."""
|
||||
|
||||
_device: MideaFBDevice
|
||||
|
||||
_attr_max_temp: float = 35
|
||||
_attr_min_temp: float = 5
|
||||
_attr_target_temperature_high: float | None = 35
|
||||
_attr_target_temperature_low: float | None = 5
|
||||
_attr_target_temperature_step: float | None = PRECISION_WHOLE
|
||||
|
||||
def __init__(self, device: MideaFBDevice, entity_key: str) -> None:
|
||||
"""Midea FB Climate entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT]
|
||||
self._attr_preset_modes: list[str] = self._device.modes
|
||||
|
||||
@property
|
||||
def supported_features(self) -> ClimateEntityFeature:
|
||||
"""Midea FB Climate supported features."""
|
||||
features = (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
|
||||
)
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
|
||||
features |= ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
|
||||
return features
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str:
|
||||
"""Midea FB Climate preset mode."""
|
||||
return cast("str", self._device.get_attribute(attr=FBAttributes.mode))
|
||||
|
||||
@property
|
||||
def hvac_mode(self) -> HVACMode:
|
||||
"""Midea FB Climate hvac mode."""
|
||||
return (
|
||||
HVACMode.HEAT
|
||||
if self._device.get_attribute(attr=FBAttributes.power)
|
||||
else HVACMode.OFF
|
||||
)
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float:
|
||||
"""Midea FB Climate current temperature."""
|
||||
return cast(
|
||||
"float",
|
||||
self._device.get_attribute(FBAttributes.current_temperature),
|
||||
)
|
||||
|
||||
def set_temperature(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea FB Climate set temperature."""
|
||||
if ATTR_TEMPERATURE not in kwargs:
|
||||
return
|
||||
temperature = float(int((float(kwargs[ATTR_TEMPERATURE]) * 2) + 0.5)) / 2
|
||||
hvac_mode = kwargs.get(ATTR_HVAC_MODE)
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
self.turn_off()
|
||||
else:
|
||||
self._device.set_target_temperature(
|
||||
target_temperature=temperature,
|
||||
mode=None,
|
||||
)
|
||||
|
||||
def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Midea FB Climate set hvac mode."""
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
self.turn_off()
|
||||
else:
|
||||
self.turn_on()
|
||||
|
||||
def set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Midea FB Climate set preset mode."""
|
||||
self._device.set_attribute(attr=FBAttributes.mode, value=preset_mode)
|
||||
@@ -0,0 +1,998 @@
|
||||
"""Config flow for Midea LAN.
|
||||
|
||||
Setup current integration and add device entry via the web UI
|
||||
enable by adding `config_flow: true` in `manifest.json`
|
||||
|
||||
`MideaLanConfigFlow`: add device entry
|
||||
`MideaLanOptionsFlowHandler`: update the options of a config entry
|
||||
|
||||
job process:
|
||||
1. run `async_step_user` when select `Add Device` from web UI
|
||||
2. default auto discovery action run `async_step_discovery`
|
||||
3. device available, run `async_step_auto` to show available device list in web UI
|
||||
3.1 check local device json with `_load_device_config`
|
||||
3.1.1 device exist with `_check_storage_device`,
|
||||
send json data to `async_step_manually`
|
||||
3.1.2 device NOT exist, get device data from cloud,
|
||||
send to `async_step_manually`
|
||||
- check login with `async_step_login`
|
||||
4. add selected device detail with `async_step_manually`
|
||||
5. run `_save_device_config` and `async_create_entry`
|
||||
"""
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import voluptuous as vol
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow
|
||||
from homeassistant.const import (
|
||||
CONF_CUSTOMIZE,
|
||||
CONF_DEVICE,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_IP_ADDRESS,
|
||||
CONF_NAME,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_PROTOCOL,
|
||||
CONF_SENSORS,
|
||||
CONF_SWITCHES,
|
||||
CONF_TOKEN,
|
||||
CONF_TYPE,
|
||||
MAJOR_VERSION,
|
||||
MINOR_VERSION,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.aiohttp_client import async_create_clientsession
|
||||
from homeassistant.helpers.json import save_json
|
||||
from homeassistant.util.json import load_json
|
||||
from midealocal.cloud import (
|
||||
PRESET_ACCOUNT_DATA,
|
||||
SUPPORTED_CLOUDS,
|
||||
MideaCloud,
|
||||
get_midea_cloud,
|
||||
)
|
||||
from midealocal.device import AuthException, MideaDevice, ProtocolVersion
|
||||
from midealocal.discover import discover
|
||||
from midealocal.exceptions import SocketException
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aiohttp import ClientSession
|
||||
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 4):
|
||||
from homeassistant.config_entries import ConfigFlowResult # pylint: disable=E0611
|
||||
else:
|
||||
from homeassistant.data_entry_flow import ( # type: ignore[assignment]
|
||||
FlowResult as ConfigFlowResult,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
CONF_ACCOUNT,
|
||||
CONF_KEY,
|
||||
CONF_MODEL,
|
||||
CONF_REFRESH_INTERVAL,
|
||||
CONF_SERVER,
|
||||
CONF_SUBTYPE,
|
||||
DOMAIN,
|
||||
EXTRA_CONTROL,
|
||||
EXTRA_SENSOR,
|
||||
)
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ADD_WAY = {
|
||||
"discovery": "Discover automatically",
|
||||
"manually": "Configure manually",
|
||||
"list": "List all appliances only",
|
||||
"cache": "Remove login cache",
|
||||
}
|
||||
|
||||
# Select DEFAULT_CLOUD from the list of supported cloud
|
||||
DEFAULT_CLOUD: str = list(SUPPORTED_CLOUDS)[3]
|
||||
|
||||
STORAGE_PATH = f".storage/{DOMAIN}"
|
||||
|
||||
SKIP_LOGIN = "Skip Login (input any user/password)"
|
||||
|
||||
|
||||
class MideaLanConfigFlow(ConfigFlow, domain=DOMAIN): # type: ignore[call-arg]
|
||||
"""Define current integration setup steps.
|
||||
|
||||
Use ConfigFlow handle to support config entries
|
||||
ConfigFlow will manage the creation of entries from user input, discovery
|
||||
"""
|
||||
|
||||
VERSION = 2
|
||||
MINOR_VERSION = 1
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""MideaLanConfigFlow class."""
|
||||
self.available_device: dict = {}
|
||||
self.devices: dict = {}
|
||||
self.found_device: dict[str, Any] = {}
|
||||
self.supports: dict = {}
|
||||
self.unsorted: dict[int, Any] = {}
|
||||
self.account: dict = {}
|
||||
self.cloud: MideaCloud | None = None
|
||||
self.session: ClientSession | None = None
|
||||
for device_type, device_info in MIDEA_DEVICES.items():
|
||||
self.unsorted[device_type] = device_info["name"]
|
||||
|
||||
sorted_device_names = sorted(self.unsorted.items(), key=lambda x: x[1])
|
||||
for item in sorted_device_names:
|
||||
self.supports[item[0]] = item[1]
|
||||
# preset account
|
||||
self.preset_account: str = bytes.fromhex(
|
||||
format((PRESET_ACCOUNT_DATA[0] ^ PRESET_ACCOUNT_DATA[1]), "X"),
|
||||
).decode("utf-8", errors="ignore")
|
||||
# preset password
|
||||
self.preset_password: str = bytes.fromhex(
|
||||
format((PRESET_ACCOUNT_DATA[0] ^ PRESET_ACCOUNT_DATA[2]), "X"),
|
||||
).decode("utf-8", errors="ignore")
|
||||
self.preset_cloud_name: str = DEFAULT_CLOUD
|
||||
|
||||
def _save_device_config(self, data: dict[str, Any]) -> None:
|
||||
"""Save device config to json file with device id."""
|
||||
storage_path = Path(self.hass.config.path(STORAGE_PATH))
|
||||
storage_path.mkdir(parents=True, exist_ok=True)
|
||||
record_file = storage_path.joinpath(f"{data[CONF_DEVICE_ID]!s}.json")
|
||||
save_json(str(record_file), data)
|
||||
|
||||
def _load_device_config(self, device_id: str) -> Any: # noqa: ANN401
|
||||
"""Load device config from json file with device id.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Device configuration (json)
|
||||
|
||||
"""
|
||||
record_file = Path(
|
||||
self.hass.config.path(f"{STORAGE_PATH}", f"{device_id}.json"),
|
||||
)
|
||||
if record_file.exists():
|
||||
with record_file.open(encoding="utf-8") as f:
|
||||
return load_json(f.name, default={})
|
||||
return {}
|
||||
|
||||
@staticmethod
|
||||
def _check_storage_device(device: dict, storage_device: dict) -> bool:
|
||||
"""Check input device with storage_device.
|
||||
|
||||
Returns
|
||||
-------
|
||||
True if storage device exist
|
||||
|
||||
"""
|
||||
if storage_device.get(CONF_SUBTYPE) is None:
|
||||
return False
|
||||
return not (
|
||||
device.get(CONF_PROTOCOL) == ProtocolVersion.V3
|
||||
and (
|
||||
storage_device.get(CONF_TOKEN) is None
|
||||
or storage_device.get(CONF_KEY) is None
|
||||
)
|
||||
)
|
||||
|
||||
def _already_configured(self, device_id: str, ip_address: str) -> bool:
|
||||
"""Check device from json with device_id or ip address.
|
||||
|
||||
Returns
|
||||
-------
|
||||
True if device is already configured
|
||||
|
||||
"""
|
||||
for entry in self._async_current_entries():
|
||||
if device_id == entry.data.get(
|
||||
CONF_DEVICE_ID,
|
||||
) or ip_address == entry.data.get(CONF_IP_ADDRESS):
|
||||
return True
|
||||
return False
|
||||
|
||||
async def async_step_user(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
error: str | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""Define config flow steps.
|
||||
|
||||
Using `async_step_<step_id>` and `async_step_user` will be the first step,
|
||||
then select discovery mode
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
# user select a device discovery mode
|
||||
if user_input is not None:
|
||||
# default is auto discovery mode
|
||||
if user_input["action"] == "discovery":
|
||||
return await self.async_step_discovery()
|
||||
# manual input device detail
|
||||
if user_input["action"] == "manually":
|
||||
self.found_device = {}
|
||||
return await self.async_step_manually()
|
||||
# remove cached login data and input new one
|
||||
if user_input["action"] == "cache":
|
||||
return await self.async_step_cache()
|
||||
# only list all devices
|
||||
return await self.async_step_list()
|
||||
# user not input, show device discovery select form in UI
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(
|
||||
{vol.Required("action", default="discovery"): vol.In(ADD_WAY)},
|
||||
),
|
||||
errors={"base": error} if error else None,
|
||||
)
|
||||
|
||||
async def async_step_cache(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
error: str | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""Remove cached login data and can input a new one.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
# user input data exist
|
||||
if user_input is not None:
|
||||
# key is not None
|
||||
if self.hass.data.get(DOMAIN):
|
||||
self.hass.data[DOMAIN].pop("login_data", None)
|
||||
self.hass.data[DOMAIN].pop("login_mode", None)
|
||||
return await self.async_step_user()
|
||||
# show cache info form in UI
|
||||
return self.async_show_form(
|
||||
step_id="cache",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required("action", default="remove"): vol.In(
|
||||
{"action": "remove"},
|
||||
),
|
||||
},
|
||||
),
|
||||
errors={"base": error} if error else None,
|
||||
)
|
||||
|
||||
async def async_step_login(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
error: str | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""User login steps.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
# get cloud servers configs
|
||||
cloud_servers = await MideaCloud.get_cloud_servers()
|
||||
default_keys = await MideaCloud.get_default_keys()
|
||||
# add skip login option to web UI with key 99
|
||||
cloud_servers[next(iter(default_keys))] = SKIP_LOGIN
|
||||
# user input data exist
|
||||
if user_input is not None:
|
||||
if not self.hass.data.get(DOMAIN):
|
||||
self.hass.data[DOMAIN] = {}
|
||||
# check skip login option
|
||||
if user_input[CONF_SERVER] == next(iter(default_keys)):
|
||||
# use preset account and DEFAULT_CLOUD cloud
|
||||
_LOGGER.debug("skip login matched, cloud_servers: %s", cloud_servers)
|
||||
# get DEFAULT_CLOUD key from dict
|
||||
key = next(
|
||||
key
|
||||
for key, value in cloud_servers.items()
|
||||
if value == DEFAULT_CLOUD
|
||||
)
|
||||
cloud_server = cloud_servers[key]
|
||||
account = self.preset_account
|
||||
password = self.preset_password
|
||||
# set a login_mode flag
|
||||
self.hass.data[DOMAIN]["login_mode"] = "preset"
|
||||
# use input data
|
||||
else:
|
||||
_LOGGER.debug("user input login matched")
|
||||
cloud_server = cloud_servers[user_input[CONF_SERVER]]
|
||||
account = user_input[CONF_ACCOUNT]
|
||||
password = user_input[CONF_PASSWORD]
|
||||
# set a login_mode flag
|
||||
self.hass.data[DOMAIN]["login_mode"] = "input"
|
||||
|
||||
# cloud login MUST pass with user input or perset account
|
||||
if await self._check_cloud_login(
|
||||
cloud_name=cloud_server,
|
||||
account=account,
|
||||
password=password,
|
||||
force_login=True,
|
||||
):
|
||||
# save passed account to cache, available before HA reboot
|
||||
self.hass.data[DOMAIN]["login_data"] = {
|
||||
CONF_ACCOUNT: account,
|
||||
CONF_PASSWORD: password,
|
||||
CONF_SERVER: cloud_server,
|
||||
}
|
||||
# return to next step after login pass
|
||||
return await self.async_step_auto()
|
||||
# return error with login failed
|
||||
_LOGGER.debug(
|
||||
"ERROR: Failed to login with %s account in %s server",
|
||||
self.hass.data[DOMAIN]["login_mode"],
|
||||
cloud_server,
|
||||
)
|
||||
return await self.async_step_login(error="login_failed")
|
||||
# user not login, show login form in UI
|
||||
return self.async_show_form(
|
||||
step_id="login",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_ACCOUNT): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Required(CONF_SERVER, default=1): vol.In(cloud_servers),
|
||||
},
|
||||
),
|
||||
errors={"base": error} if error else None,
|
||||
)
|
||||
|
||||
async def async_step_list(
|
||||
self,
|
||||
error: str | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""List all devices and show device info in web UI.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
# get all devices list
|
||||
all_devices = discover()
|
||||
# available devices exist
|
||||
if len(all_devices) > 0:
|
||||
table = (
|
||||
"Appliance code|Type|IP address|SN|Supported\n:--:|:--:|:--:|:--:|:--:"
|
||||
)
|
||||
green = "<font color=gree>YES</font>"
|
||||
red = "<font color=red>NO</font>"
|
||||
for device_id, device in all_devices.items():
|
||||
supported = device.get(CONF_TYPE) in self.supports
|
||||
table += (
|
||||
f"\n{device_id}|{f'{device.get(CONF_TYPE):02X}'}|"
|
||||
f"{device.get(CONF_IP_ADDRESS)}|"
|
||||
f"{device.get('sn')}|"
|
||||
f"{green if supported else red}"
|
||||
)
|
||||
# no available device
|
||||
else:
|
||||
table = "Not found"
|
||||
# show devices list result in UI
|
||||
return self.async_show_form(
|
||||
step_id="list",
|
||||
description_placeholders={"table": table},
|
||||
errors={"base": error} if error else None,
|
||||
)
|
||||
|
||||
async def async_step_discovery(
|
||||
self,
|
||||
discovery_info: dict[str, Any] | None = None,
|
||||
error: str | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""Discovery device with auto mode or ip address.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
# input is not None, using ip_address to discovery device
|
||||
if discovery_info is not None:
|
||||
# auto mode, ip_address is None
|
||||
if discovery_info[CONF_IP_ADDRESS].lower() == "auto":
|
||||
ip_address = None
|
||||
# ip exist
|
||||
else:
|
||||
ip_address = discovery_info[CONF_IP_ADDRESS]
|
||||
# use midea-local discover() to get devices list with ip_address
|
||||
self.devices = discover(list(self.supports.keys()), ip_address=ip_address)
|
||||
self.available_device = {}
|
||||
for device_id, device in self.devices.items():
|
||||
# remove exist devices and only return new devices
|
||||
if not self._already_configured(
|
||||
str(device_id),
|
||||
device[CONF_IP_ADDRESS],
|
||||
):
|
||||
# fmt: off
|
||||
self.available_device[device_id] = (
|
||||
f"{device_id} ({self.supports.get(device.get(CONF_TYPE))})"
|
||||
)
|
||||
# fmt: on
|
||||
if len(self.available_device) > 0:
|
||||
return await self.async_step_auto()
|
||||
return await self.async_step_discovery(error="no_devices")
|
||||
# show discovery device input form with auto or ip address in web UI
|
||||
return self.async_show_form(
|
||||
step_id="discovery",
|
||||
data_schema=vol.Schema(
|
||||
{vol.Required(CONF_IP_ADDRESS, default="auto"): str},
|
||||
),
|
||||
errors={"base": error} if error else None,
|
||||
)
|
||||
|
||||
async def _check_cloud_login(
|
||||
self,
|
||||
cloud_name: str | None = None,
|
||||
account: str | None = None,
|
||||
password: str | None = None,
|
||||
force_login: bool = False,
|
||||
) -> bool:
|
||||
"""Check cloud login.
|
||||
|
||||
Returns
|
||||
-------
|
||||
True if cloud login succeeded
|
||||
|
||||
"""
|
||||
# set default args with perset account
|
||||
if cloud_name is None or account is None or password is None:
|
||||
cloud_name = self.preset_cloud_name
|
||||
account = self.preset_account
|
||||
password = self.preset_password
|
||||
|
||||
if self.session is None:
|
||||
self.session = async_create_clientsession(self.hass)
|
||||
|
||||
# init cloud object or force reinit with new one
|
||||
if self.cloud is None or force_login:
|
||||
self.cloud = get_midea_cloud(
|
||||
cloud_name,
|
||||
self.session,
|
||||
account,
|
||||
password,
|
||||
)
|
||||
# check cloud login after self.cloud exist
|
||||
if await self.cloud.login():
|
||||
_LOGGER.debug(
|
||||
"Using account %s login to %s cloud pass",
|
||||
account,
|
||||
cloud_name,
|
||||
)
|
||||
return True
|
||||
_LOGGER.debug(
|
||||
"ERROR: unable to use account %s login to %s cloud",
|
||||
account,
|
||||
cloud_name,
|
||||
)
|
||||
return False
|
||||
|
||||
async def _check_key_from_cloud(
|
||||
self,
|
||||
appliance_id: int,
|
||||
default_key: bool = True,
|
||||
) -> dict[str, Any]:
|
||||
"""Use perset DEFAULT_CLOUD account to get v3 device token and key.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Dictionary of keys
|
||||
|
||||
"""
|
||||
device = self.devices[appliance_id]
|
||||
|
||||
if self.cloud is None:
|
||||
return {"error": "cloud_none"}
|
||||
|
||||
# get device token/key from cloud
|
||||
keys = await self.cloud.get_cloud_keys(appliance_id)
|
||||
default_keys = await MideaCloud.get_default_keys()
|
||||
# use token/key to connect device and confirm token result
|
||||
for k, value in keys.items():
|
||||
# skip default_key
|
||||
if not default_key and k == next(iter(default_keys)):
|
||||
continue
|
||||
dm = MideaDevice(
|
||||
name="",
|
||||
device_id=appliance_id,
|
||||
device_type=device.get(CONF_TYPE),
|
||||
ip_address=device.get(CONF_IP_ADDRESS),
|
||||
port=device.get(CONF_PORT),
|
||||
token=value["token"],
|
||||
key=value["key"],
|
||||
device_protocol=ProtocolVersion.V3,
|
||||
model=device.get(CONF_MODEL),
|
||||
subtype=0,
|
||||
attributes={},
|
||||
)
|
||||
if dm.connect():
|
||||
try:
|
||||
dm.authenticate()
|
||||
except AuthException:
|
||||
_LOGGER.debug("Unable to authenticate.")
|
||||
dm.close_socket()
|
||||
except SocketException:
|
||||
_LOGGER.debug("Socket closed.")
|
||||
else:
|
||||
dm.close_socket()
|
||||
return value
|
||||
# return debug log with failed key
|
||||
_LOGGER.debug(
|
||||
"connect device using method %s token/key failed",
|
||||
k,
|
||||
)
|
||||
_LOGGER.debug(
|
||||
"Unable to connect device with all the token/key",
|
||||
)
|
||||
return {"error": "connect_error"}
|
||||
|
||||
async def async_step_auto(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
error: str | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""Discovery device detail info.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
# input device exist
|
||||
if user_input is not None:
|
||||
device_id = user_input[CONF_DEVICE]
|
||||
device = self.devices[device_id]
|
||||
# set device args with protocol decode data
|
||||
# then get subtype from cloud, get v3 device token/key from cloud
|
||||
self.found_device = {
|
||||
CONF_DEVICE_ID: device_id,
|
||||
CONF_TYPE: device.get(CONF_TYPE),
|
||||
CONF_PROTOCOL: device.get(CONF_PROTOCOL),
|
||||
CONF_IP_ADDRESS: device.get(CONF_IP_ADDRESS),
|
||||
CONF_PORT: device.get(CONF_PORT),
|
||||
CONF_MODEL: device.get(CONF_MODEL),
|
||||
}
|
||||
storage_device = self._load_device_config(device_id)
|
||||
# device config already exist, load from local json without cloud
|
||||
if self._check_storage_device(device, storage_device):
|
||||
self.found_device = {
|
||||
CONF_DEVICE_ID: device_id,
|
||||
CONF_TYPE: device.get(CONF_TYPE),
|
||||
CONF_PROTOCOL: device.get(CONF_PROTOCOL),
|
||||
CONF_IP_ADDRESS: device.get(CONF_IP_ADDRESS),
|
||||
CONF_PORT: device.get(CONF_PORT),
|
||||
CONF_MODEL: device.get(CONF_MODEL),
|
||||
CONF_NAME: storage_device.get(CONF_NAME),
|
||||
CONF_SUBTYPE: storage_device.get(CONF_SUBTYPE),
|
||||
CONF_TOKEN: storage_device.get(CONF_TOKEN),
|
||||
CONF_KEY: storage_device.get(CONF_KEY),
|
||||
}
|
||||
_LOGGER.debug(
|
||||
"Loaded configuration for device %s from storage",
|
||||
device_id,
|
||||
)
|
||||
return await self.async_step_manually()
|
||||
# device config not exist in local
|
||||
# check login cache, show login web if no cache
|
||||
if not self.hass.data.get(DOMAIN) or not self.hass.data[DOMAIN].get(
|
||||
"login_data",
|
||||
):
|
||||
return await self.async_step_login()
|
||||
# login cached exist, cloud is None, reinit and login
|
||||
if self.cloud is None and not await self._check_cloud_login(
|
||||
cloud_name=self.hass.data[DOMAIN]["login_data"][CONF_SERVER],
|
||||
account=self.hass.data[DOMAIN]["login_data"][CONF_ACCOUNT],
|
||||
password=self.hass.data[DOMAIN]["login_data"][CONF_PASSWORD],
|
||||
):
|
||||
# print error in debug log and show login web
|
||||
_LOGGER.debug(
|
||||
"Login with cached %s account %s failed in %s server",
|
||||
self.hass.data[DOMAIN].get("login_mode"),
|
||||
self.hass.data[DOMAIN]["login_data"][CONF_ACCOUNT],
|
||||
self.hass.data[DOMAIN]["login_data"][CONF_SERVER],
|
||||
)
|
||||
# remove error cache and relogin
|
||||
self.hass.data[DOMAIN].pop("login_data", None)
|
||||
self.hass.data[DOMAIN].pop("login_mode", None)
|
||||
return await self.async_step_login()
|
||||
|
||||
# get subtype from cloud
|
||||
if self.cloud is not None and (
|
||||
device_info := await self.cloud.get_device_info(device_id)
|
||||
):
|
||||
# set subtype with model_number
|
||||
self.found_device[CONF_NAME] = device_info.get("name")
|
||||
self.found_device[CONF_SUBTYPE] = device_info.get("model_number")
|
||||
|
||||
# MUST get a auth passed token/key for v3 device, disable add before pass
|
||||
if device.get(CONF_PROTOCOL) == ProtocolVersion.V3:
|
||||
# phase 1, try with user input login data
|
||||
keys = await self._check_key_from_cloud(device_id)
|
||||
|
||||
# no available key, continue the phase 2
|
||||
if not keys.get("token") or not keys.get("key"):
|
||||
_LOGGER.debug(
|
||||
"Can't get valid token with %s account in %s server",
|
||||
self.hass.data[DOMAIN]["login_mode"],
|
||||
self.hass.data[DOMAIN]["login_data"][CONF_SERVER],
|
||||
)
|
||||
|
||||
# exclude: user selected not login and phase 1 is preset account
|
||||
if self.hass.data[DOMAIN]["login_mode"] == "preset":
|
||||
return await self.async_step_auto(
|
||||
error="can't get valid token from Midea server",
|
||||
)
|
||||
|
||||
# get key phase 2: reinit cloud with preset account
|
||||
if not await self._check_cloud_login(force_login=True):
|
||||
return await self.async_step_auto(
|
||||
error="Perset account login failed!",
|
||||
)
|
||||
# try to get a passed key, without default_key
|
||||
keys = await self._check_key_from_cloud(
|
||||
device_id,
|
||||
default_key=False,
|
||||
)
|
||||
|
||||
# phase 2 got no available token/key, disable device add
|
||||
if not keys.get("token") or not keys.get("key"):
|
||||
_LOGGER.debug(
|
||||
"Can't get available token from Midea server for device %s",
|
||||
device_id,
|
||||
)
|
||||
return await self.async_step_auto(
|
||||
error=(
|
||||
f"Can't get available token from Midea server"
|
||||
f" for device {device_id}"
|
||||
),
|
||||
)
|
||||
# get key pass
|
||||
self.found_device[CONF_TOKEN] = keys["token"]
|
||||
self.found_device[CONF_KEY] = keys["key"]
|
||||
return await self.async_step_manually()
|
||||
# v1/v2 device add without token/key
|
||||
return await self.async_step_manually()
|
||||
# show available device list in UI
|
||||
return self.async_show_form(
|
||||
step_id="auto",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(
|
||||
CONF_DEVICE,
|
||||
default=next(iter(self.available_device.keys())),
|
||||
): vol.In(self.available_device),
|
||||
},
|
||||
),
|
||||
errors={"base": error} if error else None,
|
||||
)
|
||||
|
||||
async def async_step_manually(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
error: str | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""Add device with device detail info.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
if user_input is not None:
|
||||
try:
|
||||
bytearray.fromhex(user_input[CONF_TOKEN])
|
||||
bytearray.fromhex(user_input[CONF_KEY])
|
||||
except ValueError:
|
||||
return await self.async_step_manually(error="invalid_token")
|
||||
|
||||
device_id = user_input[CONF_DEVICE_ID]
|
||||
# check device, discover already done or only manual add
|
||||
if len(self.devices) < 1:
|
||||
ip = user_input[CONF_IP_ADDRESS]
|
||||
# discover device
|
||||
self.devices = discover(
|
||||
list(self.supports.keys()),
|
||||
ip_address=ip,
|
||||
)
|
||||
# discover result MUST exist
|
||||
if len(self.devices) != 1:
|
||||
return await self.async_step_manually(error="invalid_device_ip")
|
||||
# check all the input, disable error add
|
||||
device_id = next(iter(self.devices.keys()))
|
||||
|
||||
# check if device_id is correctly set for that IP
|
||||
if user_input[CONF_DEVICE_ID] != device_id:
|
||||
return await self.async_step_manually(
|
||||
error=f"For ip {ip} the device_id MUST be {device_id}",
|
||||
)
|
||||
|
||||
device = self.devices[device_id]
|
||||
if user_input[CONF_IP_ADDRESS] != device.get(CONF_IP_ADDRESS):
|
||||
return await self.async_step_manually(
|
||||
error=f"ip_address MUST be {device.get(CONF_IP_ADDRESS)}",
|
||||
)
|
||||
if user_input[CONF_PROTOCOL] != device.get(CONF_PROTOCOL):
|
||||
return await self.async_step_manually(
|
||||
error=f"protocol MUST be {device.get(CONF_PROTOCOL)}",
|
||||
)
|
||||
|
||||
# try to get token/key with preset account
|
||||
if user_input[CONF_PROTOCOL] == ProtocolVersion.V3 and (
|
||||
len(user_input[CONF_TOKEN]) == 0 or len(user_input[CONF_KEY]) == 0
|
||||
):
|
||||
# init cloud with preset account
|
||||
result = await self._check_cloud_login()
|
||||
if not result:
|
||||
return await self.async_step_manually(
|
||||
error="Perset account login failed!",
|
||||
)
|
||||
# try to get a passed key
|
||||
keys = await self._check_key_from_cloud(int(user_input[CONF_DEVICE_ID]))
|
||||
|
||||
# no available token/key, disable device add
|
||||
if not keys.get("token") or not keys.get("key"):
|
||||
_LOGGER.debug(
|
||||
"Can't get a valid token from Midea server for device %s",
|
||||
user_input[CONF_DEVICE_ID],
|
||||
)
|
||||
return await self.async_step_manually(
|
||||
error=(
|
||||
f"Can't get a valid token from Midea server"
|
||||
f" for device {user_input[CONF_DEVICE_ID]}"
|
||||
),
|
||||
)
|
||||
|
||||
# set token/key from preset account
|
||||
user_input[CONF_KEY] = keys["key"]
|
||||
user_input[CONF_TOKEN] = keys["token"]
|
||||
|
||||
self.found_device = {
|
||||
CONF_DEVICE_ID: user_input[CONF_DEVICE_ID],
|
||||
CONF_TYPE: user_input[CONF_TYPE],
|
||||
CONF_PROTOCOL: user_input[CONF_PROTOCOL],
|
||||
CONF_IP_ADDRESS: user_input[CONF_IP_ADDRESS],
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
CONF_MODEL: user_input[CONF_MODEL],
|
||||
CONF_TOKEN: user_input[CONF_TOKEN],
|
||||
CONF_KEY: user_input[CONF_KEY],
|
||||
}
|
||||
|
||||
# check device connection with all the input
|
||||
dm = MideaDevice(
|
||||
name="",
|
||||
device_id=user_input[CONF_DEVICE_ID],
|
||||
device_type=user_input[CONF_TYPE],
|
||||
ip_address=user_input[CONF_IP_ADDRESS],
|
||||
port=user_input[CONF_PORT],
|
||||
token=user_input[CONF_TOKEN],
|
||||
key=user_input[CONF_KEY],
|
||||
device_protocol=user_input[CONF_PROTOCOL],
|
||||
model=user_input[CONF_MODEL],
|
||||
subtype=0,
|
||||
attributes={},
|
||||
)
|
||||
if dm.connect():
|
||||
try:
|
||||
if user_input[CONF_PROTOCOL] == ProtocolVersion.V3:
|
||||
dm.authenticate()
|
||||
except SocketException:
|
||||
_LOGGER.exception("Socket closed.")
|
||||
except AuthException:
|
||||
_LOGGER.exception(
|
||||
"Unable to authenticate with provided key and token.",
|
||||
)
|
||||
dm.close_socket()
|
||||
else:
|
||||
dm.close_socket()
|
||||
data = {
|
||||
CONF_NAME: user_input[CONF_NAME],
|
||||
CONF_DEVICE_ID: user_input[CONF_DEVICE_ID],
|
||||
CONF_TYPE: user_input[CONF_TYPE],
|
||||
CONF_PROTOCOL: user_input[CONF_PROTOCOL],
|
||||
CONF_IP_ADDRESS: user_input[CONF_IP_ADDRESS],
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
CONF_MODEL: user_input[CONF_MODEL],
|
||||
CONF_SUBTYPE: user_input[CONF_SUBTYPE],
|
||||
CONF_TOKEN: user_input[CONF_TOKEN],
|
||||
CONF_KEY: user_input[CONF_KEY],
|
||||
}
|
||||
# save device json config when adding new device
|
||||
self._save_device_config(data)
|
||||
# finish add device entry
|
||||
return self.async_create_entry(
|
||||
title=f"{user_input[CONF_NAME]}",
|
||||
data=data,
|
||||
)
|
||||
return await self.async_step_manually(
|
||||
error="Device auth failed with input config",
|
||||
)
|
||||
protocol = self.found_device.get(CONF_PROTOCOL)
|
||||
return self.async_show_form(
|
||||
step_id="manually",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(
|
||||
CONF_NAME,
|
||||
default=(
|
||||
self.found_device.get(CONF_NAME)
|
||||
if self.found_device.get(CONF_NAME)
|
||||
else self.supports.get(self.found_device.get(CONF_TYPE))
|
||||
),
|
||||
): str,
|
||||
vol.Required(
|
||||
CONF_DEVICE_ID,
|
||||
default=self.found_device.get(CONF_DEVICE_ID),
|
||||
): int,
|
||||
vol.Required(
|
||||
CONF_TYPE,
|
||||
default=(
|
||||
self.found_device.get(CONF_TYPE)
|
||||
if self.found_device.get(CONF_TYPE)
|
||||
else 0xAC
|
||||
),
|
||||
): vol.In(self.supports),
|
||||
vol.Required(
|
||||
CONF_IP_ADDRESS,
|
||||
default=self.found_device.get(CONF_IP_ADDRESS),
|
||||
): str,
|
||||
vol.Required(
|
||||
CONF_PORT,
|
||||
default=(
|
||||
self.found_device.get(CONF_PORT)
|
||||
if self.found_device.get(CONF_PORT)
|
||||
else 6444
|
||||
),
|
||||
): int,
|
||||
vol.Required(
|
||||
CONF_PROTOCOL,
|
||||
default=protocol or ProtocolVersion.V3,
|
||||
): vol.In(
|
||||
[protocol] if protocol else ProtocolVersion,
|
||||
),
|
||||
vol.Required(
|
||||
CONF_MODEL,
|
||||
default=(
|
||||
self.found_device.get(CONF_MODEL)
|
||||
if self.found_device.get(CONF_MODEL)
|
||||
else "Unknown"
|
||||
),
|
||||
): str,
|
||||
vol.Required(
|
||||
CONF_SUBTYPE,
|
||||
default=(
|
||||
self.found_device.get(CONF_SUBTYPE)
|
||||
if self.found_device.get(CONF_SUBTYPE)
|
||||
else 0
|
||||
),
|
||||
): int,
|
||||
vol.Optional(
|
||||
CONF_TOKEN,
|
||||
default=(
|
||||
self.found_device.get(CONF_TOKEN)
|
||||
if self.found_device.get(CONF_TOKEN)
|
||||
else ""
|
||||
),
|
||||
): str,
|
||||
vol.Optional(
|
||||
CONF_KEY,
|
||||
default=(
|
||||
self.found_device.get(CONF_KEY)
|
||||
if self.found_device.get(CONF_KEY)
|
||||
else ""
|
||||
),
|
||||
): str,
|
||||
},
|
||||
),
|
||||
errors={"base": error} if error else None,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlow:
|
||||
"""Create the options flow with MideaLanOptionsFlowHandler.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow options handler
|
||||
|
||||
"""
|
||||
return MideaLanOptionsFlowHandler(config_entry)
|
||||
|
||||
|
||||
class MideaLanOptionsFlowHandler(OptionsFlow):
|
||||
"""define an Options Flow Handler to update the options of a config entry."""
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Initialize options flow."""
|
||||
self._config_entry = config_entry
|
||||
self._device_type = config_entry.data.get(CONF_TYPE)
|
||||
if self._device_type is None:
|
||||
self._device_type = 0xAC
|
||||
if CONF_SENSORS in self._config_entry.options:
|
||||
for key in self._config_entry.options[CONF_SENSORS]:
|
||||
if key not in MIDEA_DEVICES[self._device_type]["entities"]:
|
||||
self._config_entry.options[CONF_SENSORS].remove(key)
|
||||
if CONF_SWITCHES in self._config_entry.options:
|
||||
for key in self._config_entry.options[CONF_SWITCHES]:
|
||||
if key not in MIDEA_DEVICES[self._device_type]["entities"]:
|
||||
self._config_entry.options[CONF_SWITCHES].remove(key)
|
||||
|
||||
async def async_step_init(
|
||||
self,
|
||||
user_input: dict[str, Any] | None = None,
|
||||
) -> ConfigFlowResult:
|
||||
"""Manage the options.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Config flow result
|
||||
|
||||
"""
|
||||
if self._device_type == CONF_ACCOUNT:
|
||||
return self.async_abort(reason="account_option")
|
||||
if user_input is not None:
|
||||
return self.async_create_entry(title="", data=user_input)
|
||||
sensors = {}
|
||||
switches = {}
|
||||
for attribute, attribute_config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[cast("int", self._device_type)]["entities"],
|
||||
).items():
|
||||
attribute_name = (
|
||||
attribute if isinstance(attribute, str) else attribute.value
|
||||
)
|
||||
if attribute_config.get("type") in EXTRA_SENSOR:
|
||||
sensors[attribute_name] = attribute_config.get("name")
|
||||
elif attribute_config.get(
|
||||
"type",
|
||||
) in EXTRA_CONTROL and not attribute_config.get("default"):
|
||||
switches[attribute_name] = attribute_config.get("name")
|
||||
ip_address = self._config_entry.options.get(CONF_IP_ADDRESS, None)
|
||||
if ip_address is None:
|
||||
ip_address = self._config_entry.data.get(CONF_IP_ADDRESS, None)
|
||||
refresh_interval = self._config_entry.options.get(CONF_REFRESH_INTERVAL, 30)
|
||||
extra_sensors = list(
|
||||
set(sensors.keys()) & set(self._config_entry.options.get(CONF_SENSORS, [])),
|
||||
)
|
||||
extra_switches = list(
|
||||
set(switches.keys())
|
||||
& set(self._config_entry.options.get(CONF_SWITCHES, [])),
|
||||
)
|
||||
customize = self._config_entry.options.get(CONF_CUSTOMIZE, "")
|
||||
data_schema = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_IP_ADDRESS, default=ip_address): str,
|
||||
vol.Required(CONF_REFRESH_INTERVAL, default=refresh_interval): int,
|
||||
},
|
||||
)
|
||||
if len(sensors) > 0:
|
||||
data_schema = data_schema.extend(
|
||||
{
|
||||
vol.Required(
|
||||
CONF_SENSORS,
|
||||
default=extra_sensors,
|
||||
): cv.multi_select(sensors),
|
||||
},
|
||||
)
|
||||
if len(switches) > 0:
|
||||
data_schema = data_schema.extend(
|
||||
{
|
||||
vol.Required(
|
||||
CONF_SWITCHES,
|
||||
default=extra_switches,
|
||||
): cv.multi_select(switches),
|
||||
},
|
||||
)
|
||||
data_schema = data_schema.extend(
|
||||
{
|
||||
vol.Optional(
|
||||
CONF_CUSTOMIZE,
|
||||
default=customize,
|
||||
): str,
|
||||
},
|
||||
)
|
||||
|
||||
return self.async_show_form(step_id="init", data_schema=data_schema)
|
||||
@@ -0,0 +1,38 @@
|
||||
"""Const for Midea Lan."""
|
||||
|
||||
from enum import IntEnum
|
||||
|
||||
from homeassistant.const import Platform
|
||||
|
||||
DOMAIN = "midea_ac_lan"
|
||||
COMPONENT = "component"
|
||||
DEVICES = "devices"
|
||||
|
||||
CONF_KEY = "key"
|
||||
CONF_MODEL = "model"
|
||||
CONF_SUBTYPE = "subtype"
|
||||
CONF_ACCOUNT = "account"
|
||||
CONF_SERVER = "server"
|
||||
CONF_REFRESH_INTERVAL = "refresh_interval"
|
||||
|
||||
EXTRA_SENSOR = [Platform.SENSOR, Platform.BINARY_SENSOR]
|
||||
EXTRA_SWITCH = [Platform.SWITCH, Platform.LOCK, Platform.SELECT, Platform.NUMBER]
|
||||
EXTRA_CONTROL = [
|
||||
Platform.CLIMATE,
|
||||
Platform.WATER_HEATER,
|
||||
Platform.FAN,
|
||||
Platform.HUMIDIFIER,
|
||||
Platform.LIGHT,
|
||||
*EXTRA_SWITCH,
|
||||
]
|
||||
ALL_PLATFORM = EXTRA_SENSOR + EXTRA_CONTROL
|
||||
|
||||
|
||||
class FanSpeed(IntEnum):
|
||||
"""FanSpeed reference values."""
|
||||
|
||||
LOW = 20
|
||||
MEDIUM = 40
|
||||
HIGH = 60
|
||||
FULL_SPEED = 80
|
||||
AUTO = 100
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Diagnostics support for Midea AC LAN."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.const import (
|
||||
CONF_TOKEN,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import CONF_KEY
|
||||
|
||||
TO_REDACT = {CONF_TOKEN, CONF_KEY}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, # noqa: ARG001
|
||||
entry: ConfigEntry,
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a config entry.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Dictionary of config
|
||||
|
||||
"""
|
||||
return {"entry": async_redact_data(entry.as_dict(), TO_REDACT)}
|
||||
@@ -0,0 +1,320 @@
|
||||
"""Midea Fan entries."""
|
||||
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.components.fan import FanEntity, FanEntityFeature
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_SWITCHES,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealocal.device import DeviceType
|
||||
from midealocal.devices.ac import DeviceAttributes as ACAttributes
|
||||
from midealocal.devices.ac import MideaACDevice
|
||||
from midealocal.devices.b6 import MideaB6Device
|
||||
from midealocal.devices.ce import DeviceAttributes as CEAttributes
|
||||
from midealocal.devices.ce import MideaCEDevice
|
||||
from midealocal.devices.fa import MideaFADevice
|
||||
from midealocal.devices.x40 import DeviceAttributes as X40Attributes
|
||||
from midealocal.devices.x40 import MideaX40Device
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up fan entries."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
devs: list[
|
||||
MideaFAFan | MideaB6Fan | MideaACFreshAirFan | MideaCEFan | MideaX40Fan
|
||||
] = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.FAN and (
|
||||
config.get("default") or entity_key in extra_switches
|
||||
):
|
||||
if device.device_type == DeviceType.FA:
|
||||
devs.append(MideaFAFan(device, entity_key))
|
||||
elif device.device_type == DeviceType.B6:
|
||||
devs.append(MideaB6Fan(device, entity_key))
|
||||
elif device.device_type == DeviceType.AC:
|
||||
devs.append(MideaACFreshAirFan(device, entity_key))
|
||||
elif device.device_type == DeviceType.CE:
|
||||
devs.append(MideaCEFan(device, entity_key))
|
||||
elif device.device_type == DeviceType.X40:
|
||||
devs.append(MideaX40Fan(device, entity_key))
|
||||
async_add_entities(devs)
|
||||
|
||||
|
||||
# HA version >= 2024,8 support TURN_ON | TURN_OFF,for future changes, ref PR #285
|
||||
try:
|
||||
FAN_FEATURE_TURN_ON_OFF = FanEntityFeature["TURN_ON"] | FanEntityFeature["TURN_OFF"]
|
||||
except KeyError:
|
||||
FAN_FEATURE_TURN_ON_OFF = FanEntityFeature(0)
|
||||
|
||||
|
||||
class MideaFan(MideaEntity, FanEntity):
|
||||
"""Midea Fan Entries Base Class."""
|
||||
|
||||
_enable_turn_on_off_backwards_compatibility = False # 2024.8~2025.1
|
||||
|
||||
@property
|
||||
def preset_modes(self) -> list[str] | None:
|
||||
"""Midea Fan preset modes."""
|
||||
return (
|
||||
self._device.preset_modes if hasattr(self._device, "preset_modes") else None
|
||||
)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Midea Fan is on."""
|
||||
return cast("bool", self._device.get_attribute("power"))
|
||||
|
||||
@property
|
||||
def oscillating(self) -> bool:
|
||||
"""Midea Fan oscillating."""
|
||||
return cast("bool", self._device.get_attribute("oscillate"))
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str | None:
|
||||
"""Midea Fan preset mode."""
|
||||
return cast("str", self._device.get_attribute("mode"))
|
||||
|
||||
@property
|
||||
def fan_speed(self) -> int | None:
|
||||
"""Midea Fan fan speed."""
|
||||
return cast("int", self._device.get_attribute("fan_speed"))
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Fan turn off."""
|
||||
self._device.set_attribute(attr="power", value=False)
|
||||
|
||||
def oscillate(self, oscillating: bool) -> None:
|
||||
"""Midea Fan oscillate."""
|
||||
self._device.set_attribute(attr="oscillate", value=oscillating)
|
||||
|
||||
def set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Midea Fan set preset mode."""
|
||||
self._device.set_attribute(attr="mode", value=preset_mode.capitalize())
|
||||
|
||||
@property
|
||||
def percentage(self) -> int | None:
|
||||
"""Midea Fan percentage."""
|
||||
if not self.fan_speed:
|
||||
return None
|
||||
return int(round(self.fan_speed * self.percentage_step)) # noqa: RUF046
|
||||
|
||||
def set_percentage(self, percentage: int) -> None:
|
||||
"""Midea Fan set percentage."""
|
||||
fan_speed = round(percentage / self.percentage_step)
|
||||
self._device.set_attribute(attr="fan_speed", value=fan_speed)
|
||||
|
||||
async def async_set_percentage(self, percentage: int) -> None:
|
||||
"""Midea Fan async set percentage."""
|
||||
if percentage == 0:
|
||||
await self.async_turn_off()
|
||||
else:
|
||||
await self.hass.async_add_executor_job(self.set_percentage, percentage)
|
||||
|
||||
def update_state(self, status: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Fan update state."""
|
||||
if not self.hass:
|
||||
_LOGGER.warning(
|
||||
"Fan update_state skipped for %s [%s]: HASS is None",
|
||||
self.name,
|
||||
type(self),
|
||||
)
|
||||
return
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
|
||||
class MideaFAFan(MideaFan):
|
||||
"""Midea FA Fan Entries."""
|
||||
|
||||
_device: MideaFADevice
|
||||
|
||||
def __init__(self, device: MideaFADevice, entity_key: str) -> None:
|
||||
"""Midea FA Fan entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_supported_features = (
|
||||
FanEntityFeature.SET_SPEED
|
||||
| FanEntityFeature.OSCILLATE
|
||||
| FanEntityFeature.PRESET_MODE
|
||||
| FAN_FEATURE_TURN_ON_OFF
|
||||
)
|
||||
self._attr_speed_count = self._device.speed_count
|
||||
|
||||
def turn_on(
|
||||
self,
|
||||
percentage: int | None = None,
|
||||
preset_mode: str | None = None,
|
||||
**kwargs: Any, # noqa: ANN401, ARG002
|
||||
) -> None:
|
||||
"""Midea FA Fan turn on."""
|
||||
fan_speed = int(percentage / self.percentage_step + 0.5) if percentage else None
|
||||
self._device.turn_on(fan_speed=fan_speed, mode=preset_mode)
|
||||
|
||||
|
||||
class MideaB6Fan(MideaFan):
|
||||
"""Midea B6 Fan Entries."""
|
||||
|
||||
_device: MideaB6Device
|
||||
|
||||
def __init__(self, device: MideaB6Device, entity_key: str) -> None:
|
||||
"""Midea B6 Fan entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_supported_features = (
|
||||
FanEntityFeature.SET_SPEED
|
||||
| FanEntityFeature.PRESET_MODE
|
||||
| FAN_FEATURE_TURN_ON_OFF
|
||||
)
|
||||
self._attr_speed_count = self._device.speed_count
|
||||
|
||||
def turn_on(
|
||||
self,
|
||||
percentage: int | None = None,
|
||||
preset_mode: str | None = None,
|
||||
**kwargs: Any, # noqa: ANN401, ARG002
|
||||
) -> None:
|
||||
"""Midea B6 Fan turn on."""
|
||||
fan_speed = int(percentage / self.percentage_step + 0.5) if percentage else None
|
||||
self._device.turn_on(fan_speed=fan_speed, mode=preset_mode)
|
||||
|
||||
|
||||
class MideaACFreshAirFan(MideaFan):
|
||||
"""Midea AC Fresh Air Fan Entries."""
|
||||
|
||||
_device: MideaACDevice
|
||||
|
||||
def __init__(self, device: MideaACDevice, entity_key: str) -> None:
|
||||
"""Midea AC Fresh Air Fan entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_supported_features = (
|
||||
FanEntityFeature.SET_SPEED
|
||||
| FanEntityFeature.PRESET_MODE
|
||||
| FAN_FEATURE_TURN_ON_OFF
|
||||
)
|
||||
self._attr_speed_count = 100
|
||||
|
||||
@property
|
||||
def preset_modes(self) -> list[str] | None:
|
||||
"""Midea AC Fan preset modes."""
|
||||
return cast("list", self._device.fresh_air_fan_speeds)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Midea AC Fan is on."""
|
||||
return cast("bool", self._device.get_attribute(ACAttributes.fresh_air_power))
|
||||
|
||||
@property
|
||||
def fan_speed(self) -> int:
|
||||
"""Midea AC Fan fan speed."""
|
||||
return cast("int", self._device.get_attribute(ACAttributes.fresh_air_fan_speed))
|
||||
|
||||
def turn_on(
|
||||
self,
|
||||
percentage: int | None = None, # noqa: ARG002
|
||||
preset_mode: str | None = None, # noqa: ARG002
|
||||
**kwargs: Any, # noqa: ANN401, ARG002
|
||||
) -> None:
|
||||
"""Midea AC Fan tun on."""
|
||||
self._device.set_attribute(attr=ACAttributes.fresh_air_power, value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea AC Fan turn off."""
|
||||
self._device.set_attribute(attr=ACAttributes.fresh_air_power, value=False)
|
||||
|
||||
def set_percentage(self, percentage: int) -> None:
|
||||
"""Midea AC Fan set percentage."""
|
||||
fan_speed = int(percentage / self.percentage_step + 0.5)
|
||||
self._device.set_attribute(
|
||||
attr=ACAttributes.fresh_air_fan_speed,
|
||||
value=fan_speed,
|
||||
)
|
||||
|
||||
def set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Midea AC Fan set preset mode."""
|
||||
self._device.set_attribute(attr=ACAttributes.fresh_air_mode, value=preset_mode)
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str | None:
|
||||
"""Midea AC Fan preset mode."""
|
||||
return cast("str", self._device.get_attribute(attr=ACAttributes.fresh_air_mode))
|
||||
|
||||
|
||||
class MideaCEFan(MideaFan):
|
||||
"""Midea CE Fan Entries."""
|
||||
|
||||
_device: MideaCEDevice
|
||||
|
||||
def __init__(self, device: MideaCEDevice, entity_key: str) -> None:
|
||||
"""Midea CE Fan entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_supported_features = (
|
||||
FanEntityFeature.SET_SPEED
|
||||
| FanEntityFeature.PRESET_MODE
|
||||
| FAN_FEATURE_TURN_ON_OFF
|
||||
)
|
||||
self._attr_speed_count = self._device.speed_count
|
||||
|
||||
def turn_on(
|
||||
self,
|
||||
percentage: int | None = None, # noqa: ARG002
|
||||
preset_mode: str | None = None, # noqa: ARG002
|
||||
**kwargs: Any, # noqa: ANN401, ARG002
|
||||
) -> None:
|
||||
"""Midea CE Fan turn on."""
|
||||
self._device.set_attribute(attr=CEAttributes.power, value=True)
|
||||
|
||||
async def async_set_percentage(self, percentage: int) -> None:
|
||||
"""Midea CE Fan async set percentage."""
|
||||
await self.hass.async_add_executor_job(self.set_percentage, percentage)
|
||||
|
||||
|
||||
class MideaX40Fan(MideaFan):
|
||||
"""Midea X40 Fan Entries."""
|
||||
|
||||
_device: MideaX40Device
|
||||
|
||||
def __init__(self, device: MideaX40Device, entity_key: str) -> None:
|
||||
"""Midea X40 Fan entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_supported_features = (
|
||||
FanEntityFeature.SET_SPEED
|
||||
| FanEntityFeature.OSCILLATE
|
||||
| FAN_FEATURE_TURN_ON_OFF
|
||||
)
|
||||
self._attr_speed_count = 2
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Midea X40 Fan is on."""
|
||||
return cast("int", self._device.get_attribute(attr=X40Attributes.fan_speed)) > 0
|
||||
|
||||
def turn_on(
|
||||
self,
|
||||
percentage: int | None = None, # noqa: ARG002
|
||||
preset_mode: str | None = None, # noqa: ARG002
|
||||
**kwargs: Any, # noqa: ANN401, ARG002
|
||||
) -> None:
|
||||
"""Midea X40 Fan turn on."""
|
||||
self._device.set_attribute(attr=X40Attributes.fan_speed, value=1)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea X40 Fan turn off."""
|
||||
self._device.set_attribute(attr=X40Attributes.fan_speed, value=0)
|
||||
@@ -0,0 +1,140 @@
|
||||
"""Midea Humidifier entries."""
|
||||
|
||||
import logging
|
||||
from typing import Any, TypeAlias, cast
|
||||
|
||||
from homeassistant.components.humidifier import (
|
||||
HumidifierDeviceClass,
|
||||
HumidifierEntity,
|
||||
HumidifierEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SWITCHES, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealocal.device import DeviceType
|
||||
from midealocal.devices.a1 import MideaA1Device
|
||||
from midealocal.devices.fd import MideaFDDevice
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up humidifier entries."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
devs: list[MideaA1Humidifier | MideaFDHumidifier] = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.HUMIDIFIER and (
|
||||
config.get("default") or entity_key in extra_switches
|
||||
):
|
||||
if device.device_type == DeviceType.A1:
|
||||
devs.append(MideaA1Humidifier(device, entity_key))
|
||||
if device.device_type == DeviceType.FD:
|
||||
devs.append(MideaFDHumidifier(device, entity_key))
|
||||
async_add_entities(devs)
|
||||
|
||||
|
||||
MideaHumidifierDevice: TypeAlias = MideaFDDevice | MideaA1Device
|
||||
|
||||
|
||||
class MideaHumidifier(MideaEntity, HumidifierEntity):
|
||||
"""Midea Humidifier Entries Base Class."""
|
||||
|
||||
_device: MideaHumidifierDevice
|
||||
|
||||
def __init__(self, device: MideaHumidifierDevice, entity_key: str) -> None:
|
||||
"""Midea Humidifier entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
|
||||
@property
|
||||
def current_humidity(self) -> float | None:
|
||||
"""Midea Humidifier current humidity."""
|
||||
return cast("float", self._device.get_attribute("current_humidity"))
|
||||
|
||||
@property
|
||||
def target_humidity(self) -> float:
|
||||
"""Midea Humidifier target humidity."""
|
||||
return cast("float", self._device.get_attribute("target_humidity"))
|
||||
|
||||
@property
|
||||
def mode(self) -> str:
|
||||
"""Midea Humidifier mode."""
|
||||
return cast("str", self._device.get_attribute("mode"))
|
||||
|
||||
@property
|
||||
def available_modes(self) -> list[str] | None:
|
||||
"""Midea Humidifier available modes."""
|
||||
return cast("list", self._device.modes)
|
||||
|
||||
def set_humidity(self, humidity: int) -> None:
|
||||
"""Midea Humidifier set humidity."""
|
||||
self._device.set_attribute("target_humidity", humidity)
|
||||
|
||||
def set_mode(self, mode: str) -> None:
|
||||
"""Midea Humidifier set mode."""
|
||||
self._device.set_attribute("mode", mode)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Midea Humidifier is on."""
|
||||
return cast("bool", self._device.get_attribute(attr="power"))
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Humidifier turn on."""
|
||||
self._device.set_attribute(attr="power", value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Humidifier turn off."""
|
||||
self._device.set_attribute(attr="power", value=False)
|
||||
|
||||
def update_state(self, status: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Humidifier update state."""
|
||||
if not self.hass:
|
||||
_LOGGER.warning(
|
||||
"Humidifier update_state skipped for %s [%s]: HASS is None",
|
||||
self.name,
|
||||
type(self),
|
||||
)
|
||||
return
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
|
||||
class MideaA1Humidifier(MideaHumidifier):
|
||||
"""Midea A1 Humidifier Entries."""
|
||||
|
||||
_device: MideaA1Device
|
||||
|
||||
def __init__(self, device: MideaA1Device, entity_key: str) -> None:
|
||||
"""Midea A1 Humidifier entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_min_humidity: float = 35
|
||||
self._attr_max_humidity: float = 85
|
||||
self._attr_device_class = HumidifierDeviceClass.DEHUMIDIFIER
|
||||
self._attr_supported_features = HumidifierEntityFeature.MODES
|
||||
|
||||
|
||||
class MideaFDHumidifier(MideaHumidifier):
|
||||
"""Midea FD Humidifier Entries."""
|
||||
|
||||
_device: MideaFDDevice
|
||||
|
||||
def __init__(self, device: MideaFDDevice, entity_key: str) -> None:
|
||||
"""Midea FD Humidifier entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_min_humidity: float = 35
|
||||
self._attr_max_humidity: float = 85
|
||||
self._attr_device_class = HumidifierDeviceClass.HUMIDIFIER
|
||||
self._attr_supported_features = HumidifierEntityFeature.MODES
|
||||
@@ -0,0 +1,184 @@
|
||||
"""Midea Light entries."""
|
||||
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP_KELVIN,
|
||||
ATTR_EFFECT,
|
||||
ColorMode,
|
||||
LightEntity,
|
||||
LightEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SWITCHES, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealocal.devices.x13 import DeviceAttributes as X13Attributes
|
||||
from midealocal.devices.x13 import Midea13Device
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up light entries."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
devs = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.LIGHT and (
|
||||
config.get("default") or entity_key in extra_switches
|
||||
):
|
||||
devs.append(MideaLight(device, entity_key))
|
||||
async_add_entities(devs)
|
||||
|
||||
|
||||
def _calc_supported_features(device: Midea13Device) -> LightEntityFeature:
|
||||
supported_features = LightEntityFeature(0)
|
||||
if device.get_attribute(X13Attributes.effect):
|
||||
supported_features |= LightEntityFeature.EFFECT
|
||||
return supported_features
|
||||
|
||||
|
||||
def _calc_supported_color_modes(device: Midea13Device) -> set[ColorMode]:
|
||||
# https://github.com/home-assistant/core/blob/c34731185164aaf44419977c4086e9a7dd6c0a7f/homeassistant/components/light/__init__.py#L1278
|
||||
supported = set[ColorMode]()
|
||||
|
||||
if device.get_attribute(X13Attributes.color_temperature) is not None:
|
||||
supported.add(ColorMode.COLOR_TEMP)
|
||||
if device.get_attribute(X13Attributes.rgb_color) is not None:
|
||||
supported.add(ColorMode.HS)
|
||||
if not supported and device.get_attribute(X13Attributes.brightness) is not None:
|
||||
supported = {ColorMode.BRIGHTNESS}
|
||||
|
||||
if not supported:
|
||||
supported = {ColorMode.ONOFF}
|
||||
|
||||
return supported
|
||||
|
||||
|
||||
class MideaLight(MideaEntity, LightEntity):
|
||||
"""Midea Light Entries."""
|
||||
|
||||
_attr_color_mode: ColorMode | str | None = None
|
||||
_attr_supported_color_modes: set[ColorMode] | set[str] | None = None
|
||||
_attr_supported_features: LightEntityFeature = LightEntityFeature(0)
|
||||
|
||||
_device: Midea13Device
|
||||
|
||||
def __init__(self, device: Midea13Device, entity_key: str) -> None:
|
||||
"""Midea Light entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_supported_features = _calc_supported_features(device)
|
||||
self._attr_supported_color_modes = _calc_supported_color_modes(device)
|
||||
self._attr_color_mode = self._calc_color_mode(self._attr_supported_color_modes)
|
||||
|
||||
def _calc_color_mode(self, supported: set[ColorMode]) -> ColorMode:
|
||||
"""Midea Light calculate color mode.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Calculated color mode
|
||||
|
||||
"""
|
||||
# https://github.com/home-assistant/core/blob/c34731185164aaf44419977c4086e9a7dd6c0a7f/homeassistant/components/light/__init__.py#L925
|
||||
if ColorMode.HS in supported and self.hs_color is not None:
|
||||
return ColorMode.HS
|
||||
if ColorMode.COLOR_TEMP in supported and self.color_temp_kelvin is not None:
|
||||
return ColorMode.COLOR_TEMP
|
||||
if ColorMode.BRIGHTNESS in supported and self.brightness is not None:
|
||||
return ColorMode.BRIGHTNESS
|
||||
if ColorMode.ONOFF in supported:
|
||||
return ColorMode.ONOFF
|
||||
return ColorMode.UNKNOWN
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Midea Light is on."""
|
||||
return cast("bool", self._device.get_attribute(X13Attributes.power))
|
||||
|
||||
@property
|
||||
def brightness(self) -> int | None:
|
||||
"""Midea Light brightness."""
|
||||
return cast("int", self._device.get_attribute(X13Attributes.brightness))
|
||||
|
||||
@property
|
||||
def rgb_color(self) -> tuple[int, int, int] | None:
|
||||
"""Midea Light rgb color."""
|
||||
return cast("tuple", self._device.get_attribute(X13Attributes.rgb_color))
|
||||
|
||||
@property
|
||||
def color_temp(self) -> int | None:
|
||||
"""Midea Light color temperature."""
|
||||
if not self.color_temp_kelvin:
|
||||
return None
|
||||
return round(1000000 / self.color_temp_kelvin)
|
||||
|
||||
# https://developers.home-assistant.io/blog/2024/12/14/kelvin-preferred-color-temperature-unit
|
||||
@property
|
||||
def color_temp_kelvin(self) -> int | None:
|
||||
"""Midea Light color temperature kelvin."""
|
||||
return cast("int", self._device.get_attribute(X13Attributes.color_temperature))
|
||||
|
||||
@property
|
||||
def min_color_temp_kelvin(self) -> int:
|
||||
"""Midea Light min color temperature kelvin."""
|
||||
return self._device.color_temp_range[0]
|
||||
|
||||
@property
|
||||
def max_color_temp_kelvin(self) -> int:
|
||||
"""Midea Light max color temperature kelvin."""
|
||||
return self._device.color_temp_range[1]
|
||||
|
||||
@property
|
||||
def effect_list(self) -> list[str] | None:
|
||||
"""Midea Light effect list."""
|
||||
return cast("list", self._device.effects)
|
||||
|
||||
@property
|
||||
def effect(self) -> str | None:
|
||||
"""Midea Light effect."""
|
||||
return cast("str", self._device.get_attribute(X13Attributes.effect))
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea Light turn on."""
|
||||
if not self.is_on:
|
||||
self._device.set_attribute(attr=X13Attributes.power, value=True)
|
||||
for key, value in kwargs.items():
|
||||
if key == ATTR_BRIGHTNESS:
|
||||
self._device.set_attribute(attr=X13Attributes.brightness, value=value)
|
||||
if key == ATTR_COLOR_TEMP_KELVIN:
|
||||
self._device.set_attribute(
|
||||
attr=X13Attributes.color_temperature,
|
||||
value=value,
|
||||
)
|
||||
if key == ATTR_EFFECT:
|
||||
self._device.set_attribute(attr=X13Attributes.effect, value=value)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Light turn off."""
|
||||
self._device.set_attribute(attr=X13Attributes.power, value=False)
|
||||
|
||||
def update_state(self, status: Any) -> None: # noqa: ANN401,ARG002
|
||||
"""Midea Light update state."""
|
||||
if not self.hass:
|
||||
_LOGGER.warning(
|
||||
"Light update_state skipped for %s [%s]: HASS is None",
|
||||
self.name,
|
||||
type(self),
|
||||
)
|
||||
return
|
||||
self.schedule_update_ha_state()
|
||||
@@ -0,0 +1,54 @@
|
||||
"""Lock entities for Midea Lan."""
|
||||
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.components.lock import LockEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SWITCHES, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up entities for device."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
locks = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.LOCK and entity_key in extra_switches:
|
||||
dev = MideaLock(device, entity_key)
|
||||
locks.append(dev)
|
||||
async_add_entities(locks)
|
||||
|
||||
|
||||
class MideaLock(MideaEntity, LockEntity):
|
||||
"""Represent a Midea lock entity."""
|
||||
|
||||
@property
|
||||
def is_locked(self) -> bool:
|
||||
"""Return true if state is locked."""
|
||||
return cast("bool", self._device.get_attribute(self._entity_key))
|
||||
|
||||
def lock(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Lock the lock."""
|
||||
self._device.set_attribute(attr=self._entity_key, value=True)
|
||||
|
||||
def unlock(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Unlock the lock."""
|
||||
self._device.set_attribute(attr=self._entity_key, value=False)
|
||||
|
||||
def open(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Open the lock."""
|
||||
self.unlock()
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"domain": "midea_ac_lan",
|
||||
"name": "Midea AC LAN",
|
||||
"codeowners": ["@wuwentao", "@rokam", "@chemelli74", "@Necroneco"],
|
||||
"config_flow": true,
|
||||
"dependencies": [],
|
||||
"documentation": "https://github.com/wuwentao/midea_ac_lan#readme",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"issue_tracker": "https://github.com/wuwentao/midea_ac_lan/issues",
|
||||
"loggers": ["midealocal"],
|
||||
"requirements": ["midea-local==6.6.0"],
|
||||
"version": "v0.6.11"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
||||
"""Base entity for Midea Lan."""
|
||||
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.const import MAJOR_VERSION, MINOR_VERSION
|
||||
from homeassistant.core import callback
|
||||
|
||||
if (MAJOR_VERSION, MINOR_VERSION) >= (2023, 9):
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
else:
|
||||
from homeassistant.helpers.entity import ( # type: ignore[attr-defined]
|
||||
DeviceInfo,
|
||||
)
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from midealocal.device import MideaDevice
|
||||
|
||||
from .const import DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MideaEntity(Entity):
|
||||
"""Base Midea entity."""
|
||||
|
||||
def __init__(self, device: MideaDevice, entity_key: str) -> None:
|
||||
"""Initialize Midea base entity."""
|
||||
self._device = device
|
||||
self._device.register_update(self.update_state)
|
||||
self._config = cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[self._device.device_type]["entities"],
|
||||
)[entity_key]
|
||||
self._entity_key = entity_key
|
||||
self._unique_id = f"{DOMAIN}.{self._device.device_id}_{entity_key}"
|
||||
self.entity_id = self._unique_id
|
||||
self._device_name = self._device.name
|
||||
|
||||
# HA language setting:
|
||||
# 1. hass.config.language: Settings / System / General settings
|
||||
# 2. user language setting in user profile setting
|
||||
# Entity name translation based on hass.config.language
|
||||
# add language in /config/configuration.yaml will disable web UI setting
|
||||
# homeassistant:
|
||||
# language: zh-Hans # noqa: ERA001
|
||||
|
||||
# Translating the name and attributes of entities:
|
||||
# https://developers.home-assistant.io/blog/2023/03/27/entity_name_translations/#translating-entity-name
|
||||
# https://developers.home-assistant.io/docs/internationalization/core
|
||||
# translation_key: if defined, Home Assistant will try to find a
|
||||
# translation in translations/<lang>.json.
|
||||
# If translation exists -> UI shows the translated string.
|
||||
# If translation not found -> fallback to "name" / device_class / entity_id.
|
||||
self._attr_translation_key = self._config.get("translation_key")
|
||||
|
||||
# has_entity_name: MUST be True in modern HA (old False behavior is deprecated).
|
||||
self._attr_has_entity_name = True
|
||||
|
||||
# Step 1: translation_key is defined
|
||||
# - If translation is found in the current language:
|
||||
# -> UI displays the translated string.
|
||||
if self._attr_translation_key is not None:
|
||||
# skip set attr_name and use translation_key
|
||||
pass
|
||||
# set attr_name to None will only show device name without translaion_key
|
||||
# Step 2: No translation_key
|
||||
# but english "name" is explicitly set in config:
|
||||
# -> UI displays this name directly (highest priority).
|
||||
elif self._config.get("name") is not None:
|
||||
self._attr_name = self._config["name"]
|
||||
# Step 3: No translation_key, no name,
|
||||
# fallback to device_class default label.
|
||||
# Example: device_class = temperature -> "Temperature".
|
||||
elif "device_class" in self._config:
|
||||
self._attr_name = None # Let HA generate from device_class
|
||||
# Step 4: Nothing available,
|
||||
else:
|
||||
self._attr_name = (
|
||||
f"{self._device_name} {self._config.get('name')}"
|
||||
if "name" in self._config
|
||||
else f"{self._device_name}"
|
||||
)
|
||||
|
||||
@property
|
||||
def device(self) -> MideaDevice:
|
||||
"""Return device structure."""
|
||||
return self._device
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device info."""
|
||||
return {
|
||||
"manufacturer": "Midea",
|
||||
"model": f"{MIDEA_DEVICES[self._device.device_type]['name']} "
|
||||
f"{self._device.model}"
|
||||
f" ({self._device.subtype})",
|
||||
"identifiers": {(DOMAIN, str(self._device.device_id))},
|
||||
"name": self._device_name,
|
||||
}
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return entity unique id."""
|
||||
return self._unique_id
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
"""Return true is integration should poll."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return entity availability."""
|
||||
return bool(self._device.available)
|
||||
|
||||
@property
|
||||
def icon(self) -> str:
|
||||
"""Return entity icon."""
|
||||
return cast("str", self._config.get("icon"))
|
||||
|
||||
@callback
|
||||
def update_state(self, status: Any) -> None: # noqa: ANN401
|
||||
"""Update entity state."""
|
||||
if not self.hass:
|
||||
_LOGGER.warning(
|
||||
"MideaEntity update_state for %s [%s] with status %s: HASS is None",
|
||||
self.name,
|
||||
type(self),
|
||||
status,
|
||||
)
|
||||
return
|
||||
|
||||
if self.hass.is_stopping:
|
||||
_LOGGER.debug(
|
||||
"MideaEntity update_state for %s [%s] with status %s: HASS is stopping",
|
||||
self.name,
|
||||
type(self),
|
||||
status,
|
||||
)
|
||||
return
|
||||
|
||||
if self._entity_key in status or "available" in status:
|
||||
self.schedule_update_ha_state()
|
||||
@@ -0,0 +1,102 @@
|
||||
"""Number for Midea Lan."""
|
||||
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.components.number import NumberEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SWITCHES, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealocal.device import MideaDevice
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up numbers for device."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
numbers = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.NUMBER and entity_key in extra_switches:
|
||||
dev = MideaNumber(device, entity_key)
|
||||
numbers.append(dev)
|
||||
async_add_entities(numbers)
|
||||
|
||||
|
||||
class MideaNumber(MideaEntity, NumberEntity):
|
||||
"""Represent a Midea number sensor."""
|
||||
|
||||
def __init__(self, device: MideaDevice, entity_key: str) -> None:
|
||||
"""Midea number sensor init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._max_value = self._config.get("max")
|
||||
self._min_value = self._config.get("min")
|
||||
self._step_value = self._config.get("step")
|
||||
|
||||
@property
|
||||
def native_min_value(self) -> float:
|
||||
"""Return minimum value."""
|
||||
return cast(
|
||||
"float",
|
||||
(
|
||||
self._min_value
|
||||
if isinstance(self._min_value, int)
|
||||
else (
|
||||
self._device.get_attribute(attr=self._min_value)
|
||||
if self._device.get_attribute(attr=self._min_value)
|
||||
else getattr(self._device, self._min_value)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def native_max_value(self) -> float:
|
||||
"""Return maximum value."""
|
||||
return cast(
|
||||
"float",
|
||||
(
|
||||
self._max_value
|
||||
if isinstance(self._max_value, int)
|
||||
else (
|
||||
self._device.get_attribute(attr=self._max_value)
|
||||
if self._device.get_attribute(attr=self._max_value)
|
||||
else getattr(self._device, self._max_value)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def native_step(self) -> float:
|
||||
"""Return step value."""
|
||||
return cast(
|
||||
"float",
|
||||
(
|
||||
self._step_value
|
||||
if isinstance(self._step_value, int)
|
||||
else (
|
||||
self._device.get_attribute(attr=self._step_value)
|
||||
if self._device.get_attribute(attr=self._step_value)
|
||||
else getattr(self._device, self._step_value)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def native_value(self) -> float:
|
||||
"""Return value."""
|
||||
return cast("float", self._device.get_attribute(self._entity_key))
|
||||
|
||||
def set_native_value(self, value: Any) -> None: # noqa: ANN401
|
||||
"""Set value."""
|
||||
self._device.set_attribute(self._entity_key, value)
|
||||
@@ -0,0 +1,57 @@
|
||||
"""Select for Midea Lan."""
|
||||
|
||||
from typing import cast
|
||||
|
||||
from homeassistant.components.select import SelectEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SWITCHES, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealocal.device import MideaDevice
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up selects for device."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
selects = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.SELECT and entity_key in extra_switches:
|
||||
dev = MideaSelect(device, entity_key)
|
||||
selects.append(dev)
|
||||
async_add_entities(selects)
|
||||
|
||||
|
||||
class MideaSelect(MideaEntity, SelectEntity):
|
||||
"""Represent a Midea select."""
|
||||
|
||||
def __init__(self, device: MideaDevice, entity_key: str) -> None:
|
||||
"""Midea select init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._options_name = self._config.get("options")
|
||||
|
||||
@property
|
||||
def options(self) -> list[str]:
|
||||
"""Return entity options."""
|
||||
return cast("list", getattr(self._device, self._options_name))
|
||||
|
||||
@property
|
||||
def current_option(self) -> str:
|
||||
"""Return entity current option."""
|
||||
return cast("str", self._device.get_attribute(self._entity_key))
|
||||
|
||||
def select_option(self, option: str) -> None:
|
||||
"""Select entity option."""
|
||||
self._device.set_attribute(self._entity_key, option)
|
||||
@@ -0,0 +1,67 @@
|
||||
"""Sensor for Midea Lan."""
|
||||
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SENSORS, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up sensors for device."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_sensors = config_entry.options.get(CONF_SENSORS, [])
|
||||
sensors = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.SENSOR and entity_key in extra_sensors:
|
||||
sensor = MideaSensor(device, entity_key)
|
||||
sensors.append(sensor)
|
||||
async_add_entities(sensors)
|
||||
|
||||
|
||||
class MideaSensor(MideaEntity, SensorEntity):
|
||||
"""Represent a Midea sensor."""
|
||||
|
||||
@property
|
||||
def native_value(self) -> StateType:
|
||||
"""Return entity value."""
|
||||
return cast("StateType", self._device.get_attribute(self._entity_key))
|
||||
|
||||
@property
|
||||
def device_class(self) -> SensorDeviceClass:
|
||||
"""Return device class."""
|
||||
return cast("SensorDeviceClass", self._config.get("device_class"))
|
||||
|
||||
@property
|
||||
def state_class(self) -> SensorStateClass | None:
|
||||
"""Return state state."""
|
||||
return cast("SensorStateClass | None", self._config.get("state_class"))
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self) -> str | None:
|
||||
"""Return unit of measurement."""
|
||||
return cast("str | None", self._config.get("unit"))
|
||||
|
||||
@property
|
||||
def capability_attributes(self) -> dict[str, Any] | None:
|
||||
"""Return capabilities."""
|
||||
return {"state_class": self.state_class} if self.state_class else {}
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
set_attribute:
|
||||
fields:
|
||||
device_id:
|
||||
example: "1234567890"
|
||||
attribute:
|
||||
example: "eco_mode"
|
||||
value:
|
||||
example: true
|
||||
|
||||
send_command:
|
||||
fields:
|
||||
device_id:
|
||||
example: "1234567890"
|
||||
cmd_type:
|
||||
example: 2
|
||||
cmd_body:
|
||||
example: "B0FF01370E0000A500"
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Switch for Midea Lan."""
|
||||
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_SWITCHES, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up switches for device."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
switches = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.SWITCH and entity_key in extra_switches:
|
||||
dev = MideaSwitch(device, entity_key)
|
||||
switches.append(dev)
|
||||
async_add_entities(switches)
|
||||
|
||||
|
||||
class MideaSwitch(MideaEntity, ToggleEntity):
|
||||
"""Represent a Midea switch."""
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if switch is on."""
|
||||
return cast("bool", self._device.get_attribute(self._entity_key))
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Turn on switch."""
|
||||
self._device.set_attribute(attr=self._entity_key, value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Turn off switch."""
|
||||
self._device.set_attribute(attr=self._entity_key, value=False)
|
||||
@@ -0,0 +1,715 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "Anmeldung mit voreingestelltem Konto fehlgeschlagen, bitte melden Sie dieses Problem",
|
||||
"login_failed": "Anmeldung fehlgeschlagen, Konto oder Passwort ist falsch",
|
||||
"no_devices": "Keine neuen verfügbaren Geräte im Netzwerk gefunden",
|
||||
"device_exist": "Das Gerät ist bereits konfiguriert",
|
||||
"config_incorrect": "Die Konfiguration ist falsch",
|
||||
"connect_error": "Kann keine Verbindung zum Gerät herstellen",
|
||||
"invalid_token": "Token oder Schlüssel hat ein falsches Format"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "Hinzufügen von Geräten"
|
||||
},
|
||||
"description": "Wählen Sie die Art des Hinzufügens eines Geräts",
|
||||
"title": "Neues Gerät hinzufügen"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "Konto",
|
||||
"password": "Passwort"
|
||||
},
|
||||
"description": "Melden Sie sich mit Ihrem Midea-Konto an. Ihr Konto wird nur verwendet, um die Geräteinformationen zu erhalten.\nSie können die Konfiguration entfernen, nachdem alle Geräte konfiguriert wurden.",
|
||||
"title": "Login"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "IP-Adresse des Geräts, geben Sie \"auto\" ein, um es automatisch zu finden.\nSie können auch eine IP-Adresse verwenden, um innerhalb eines bestimmten Netzwerks zu suchen, z.B. \"192.168.1.255\".",
|
||||
"title": "Suche",
|
||||
"data": {
|
||||
"ip_address": "IP-Adresse"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "Geräte"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "Geräte"
|
||||
},
|
||||
"description": "Wählen Sie ein Gerät zum Hinzufügen",
|
||||
"title": "Neues Gerät gefunden"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "Name (z.B. Klimaanlage Wohnzimmer)",
|
||||
"device_id": "Geräte-ID",
|
||||
"type": "Typ",
|
||||
"ip_address": "IP-Adresse",
|
||||
"port": "Port",
|
||||
"model": "Modell",
|
||||
"subtype": "Untertyp",
|
||||
"protocol": "Protokoll",
|
||||
"token": "Token",
|
||||
"key": "Schlüssel"
|
||||
},
|
||||
"description": "Konfiguration des Geräts",
|
||||
"title": "Neues Gerät"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "Bar Door"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "Bar Door Overtime"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "Bathing Working Status"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "Bottom Compartment Cooling"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "Bottom Compartment Door"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "Bottom Compartment Preheating"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "Burning State"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "Cleaning Reminder"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "Compressor Status"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "Cooking"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "Filter Change Reminder"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "Filter Cleaning Reminder"
|
||||
},
|
||||
"finished": {
|
||||
"name": "Finished"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "Flex Door"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "Flex Zone Door"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "Freezer Door"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "Freezer Door Overtime"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "Full of Dust"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "Heating Working Status"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "Keep Warm"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "Lid Status"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "Middle Compartment Cooling"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "Middle Compartment Door"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "Middle Compartment Preheating"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "Oil-cup Full"
|
||||
},
|
||||
"protection": {
|
||||
"name": "Protection"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "Refrigerator Door"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "Refrigerator Door Overtime"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "Rinse Aid Shortage"
|
||||
},
|
||||
"salt": {
|
||||
"name": "Salt Shortage"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "Seat Status"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "DHW status"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "Heating status"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "IBH status"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "TBH status"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "Tank Ejected"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "Tank status"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "Top Compartment Cooling"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "Top Compartment Door"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "Top Compartment Preheating"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "Water Change Reminder"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "Water Shortage"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "With Pressure"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "Zone1 Room-temperature Mode"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "Zone1 Water-temperature Mode"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "Zone2 Room-temperature Mode"
|
||||
},
|
||||
"zone2_water_temp_mode": {
|
||||
"name": "Zone2 Water-temperature Mode"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "Zone1 Thermostat"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "Zone2 Thermostat"
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "Fresh Air"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "Kindersicherung"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "Dry Level"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "Heating Level"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "Seat Temperature Level"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "Water Temperature Level"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "Detect Mode"
|
||||
},
|
||||
"direction": {
|
||||
"name": "Direction"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "Fan Speed"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "Oscillation Angle"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "Oscillation Mode"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "Silent Level"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "Tilting Angle"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "Water Level Setting"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "Bathing Leaving Water Temperature"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "Bottom Compartment Remaining"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "Bottom Compartment Status"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "Bottom Compartment Temperature"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "Bottom Temperature"
|
||||
},
|
||||
"bright": {
|
||||
"name": "Bright Level"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "Compressor Temperature"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "Condenser Temperature"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "Current Energy Consumption"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "Current Temperature"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "dehydration speed"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "dehydration time"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "detergent"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "Energy Consumption"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Error Code"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "Fan level"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "Filter Life"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "Filter1 Verfügbare Tage"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "Filter1 Lebensdauer Level"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "Filter2 Verfügbare Tage"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "Filter2 Lebensdauer Level"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "Filter3 Verfügbare Tage"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "Filter3 Lebensdauer Level"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "Flex Zone Actual Temperature"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "Flex Zone Setting Temperature"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "Freezer Actual Temperature"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "Freezer Setting Temperature"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "Methanal"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "Heating Leaving Water Temperature"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "Heating Time Remaining"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "TDS-Wert rein"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "Indoor Humidity"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "Indoor Temperature"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "Keep Warm Remaining"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "Keep Warm Time"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "Middle Compartment Remaining"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "Middle Compartment Status"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "Middle Compartment Temperature"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "TDS-Wert raus"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "Outdoor Temperature"
|
||||
},
|
||||
"program": {
|
||||
"name": "Program"
|
||||
},
|
||||
"progress": {
|
||||
"name": "Progress"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "Realtime Power"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "Refrigerator Actual Temperature"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "Refrigerator Setting Temperature"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "Right Flex Zone Actual Temperature"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "Right Flex Zone Setting Temperature"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "rinse level"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "Seat Temperature"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "soak time"
|
||||
},
|
||||
"softener": {
|
||||
"name": "softener"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "Softwater Level"
|
||||
},
|
||||
"status": {
|
||||
"name": "Status"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "Storage Remaining"
|
||||
},
|
||||
"tank": {
|
||||
"name": "Tank"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "Tank Actual Temperature"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "Target Temperature"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "Time Remaining"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "Top Compartment Remaining"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "Top Compartment Status"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "Top Compartment Temperature"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "Top Temperature"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "Total Energy Consumption"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "Total produced energy"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "TVOC"
|
||||
},
|
||||
"wash_level": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "wash strength"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "wash time"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "Wasserverbrauch"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "Water Temperature"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "Water Level"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "Working Time"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "Anion"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "Aux Heating"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "Boost Mode"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "Breezeless"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "Comfort Mode"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "DHW Power"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "Disinfect"
|
||||
},
|
||||
"dry": {
|
||||
"name": "Dry"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "ECO Mode"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "Fast DHW"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "Foam Shield"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "Frost Protect"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "Indirect Wind"
|
||||
},
|
||||
"light": {
|
||||
"name": "Licht"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "Link to AC"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "Main Light"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "Main Power"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "Natural Wind"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "Night Light"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "Oscillate"
|
||||
},
|
||||
"power": {
|
||||
"name": "Strom"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "Powerful Purification"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "Prompt Tone"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "Screen Display Alternate"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "Sensor Light"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "Silent Mode"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "Sleep Mode"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "Smart Eye"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "Smart Volume"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "Geruchssensor"
|
||||
},
|
||||
"standby": {
|
||||
"name": "Standby"
|
||||
},
|
||||
"start": {
|
||||
"name": "Start"
|
||||
},
|
||||
"storage": {
|
||||
"name": "Storage"
|
||||
},
|
||||
"swing": {
|
||||
"name": "swing"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "Swing Horizontal"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "Swing Vertical"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "Variable Heating"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "Lüftung"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "Whole Tank Heating"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "Zero Cold Water (Pulse)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "Zero Cold Water"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "Zone1 Curve"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "Zone1 Power"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "Zone2 Curve"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "Zone2 Power"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "Domestic hot water"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "Bathing"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "IP-Adresse",
|
||||
"refresh_interval": "Aktualisierungsintervall (0 bedeutet, dass nicht aktiv aktualisiert wird)",
|
||||
"sensors": "Zusätzliche Sensoren",
|
||||
"switches": "Zusätzliche Schalter",
|
||||
"customize": "Anpassen"
|
||||
},
|
||||
"title": "Konfiguration"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "Das Konto unterstützt diesen Vorgang nicht.\nKlicken Sie auf \"GERÄT HINZUFÜGEN\" um ein neues Gerät hinzuzufügen."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "Attribut setzen",
|
||||
"description": "Einstellen des Attributwerts des Geräts",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Geräte-ID",
|
||||
"description": "Die Geräte-ID des Geräts"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "Attribut",
|
||||
"description": "Der Name des Attributs, das gesetzt werden soll"
|
||||
},
|
||||
"value": {
|
||||
"name": "Wert",
|
||||
"description": "Der Attributwert, der gesetzt werden soll"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "Befehl an Gerät senden",
|
||||
"description": "Senden eines Befehls an das Gerät",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Geräte-ID",
|
||||
"description": "Die Geräte-ID des Geräts"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "Befehlstyp",
|
||||
"description": "Die Art des Befehls, sollte 3 (abfragen) oder 2 (setzen) sein"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "Befehl",
|
||||
"description": "Der Hauptteil des Befehls (ohne den MSmart-Protokollkopf und die Prüfsumme am Ende)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,834 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "Failed to login with preset account, please report this issue",
|
||||
"login_failed": "Failed to login, account or password was wrong",
|
||||
"no_devices": "No new available appliances found on the network",
|
||||
"device_exist": "Appliance is already configured",
|
||||
"config_incorrect": "The configuration is incorrect",
|
||||
"connect_error": "Can't connect to appliance",
|
||||
"invalid_token": "Token or Key in an incorrect format"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "Adding appliances"
|
||||
},
|
||||
"description": "Choose the way to add a appliance",
|
||||
"title": "Add new appliance"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "Account",
|
||||
"password": "Password"
|
||||
},
|
||||
"description": "Login and storage your Midea account only for getting the appliance info.\nYou can remove this configuration after all appliance configured.",
|
||||
"title": "Login"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "IP address for device, enter \"auto\" to discover automatically\nYou can also use an IP address to search within a specified network, such as \"192.168.1.255\"",
|
||||
"title": "Search",
|
||||
"data": {
|
||||
"ip_address": "IP address"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "Appliances"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "Appliances"
|
||||
},
|
||||
"description": "Choose a appliance to add",
|
||||
"title": "New appliance found"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "Name (e.g. Living room AC)",
|
||||
"device_id": "Appliance code",
|
||||
"type": "Type",
|
||||
"ip_address": "IP address",
|
||||
"port": "Port",
|
||||
"model": "Model",
|
||||
"subtype": "Subtype",
|
||||
"protocol": "Protocol",
|
||||
"token": "Token",
|
||||
"key": "Key"
|
||||
},
|
||||
"description": "Configuration of appliance",
|
||||
"title": "New appliance"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "Bar Door"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "Bar Door Overtime"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "Bathing Working Status"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "Bottom Compartment Cooling"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "Bottom Compartment Door"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "Bottom Compartment Preheating"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "Burning State"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "Cleaning Reminder"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "Compressor Status"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "Cooking"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "Filter Change Reminder"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "Filter Cleaning Reminder"
|
||||
},
|
||||
"finished": {
|
||||
"name": "Finished"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "Flex Door"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "Flex Zone Door"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "Freezer Door"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "Freezer Door Overtime"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "Full of Dust"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "Heating Working Status"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "Keep Warm"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "Lid Status"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "Middle Compartment Cooling"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "Middle Compartment Door"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "Middle Compartment Preheating"
|
||||
},
|
||||
"top_elec_heat": {
|
||||
"name": "Top Electric Heat"
|
||||
},
|
||||
"bottom_elec_heat": {
|
||||
"name": "Bottom Electric Heat"
|
||||
},
|
||||
"mute_effect": {
|
||||
"name": "Mute Effect"
|
||||
},
|
||||
"mute_status": {
|
||||
"name": "Mute Status"
|
||||
},
|
||||
"multi_terminal": {
|
||||
"name": "Multi Terminal"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "Oil-cup Full"
|
||||
},
|
||||
"protection": {
|
||||
"name": "Protection"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "Refrigerator Door"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "Refrigerator Door Overtime"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "Rinse Aid Shortage"
|
||||
},
|
||||
"salt": {
|
||||
"name": "Salt Shortage"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "Seat Status"
|
||||
},
|
||||
"smart_grid": {
|
||||
"name": "Smart Grid"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "DHW status"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "Heating status"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "IBH status"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "TBH status"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "Tank Ejected"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "Tank status"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "Top Compartment Cooling"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "Top Compartment Door"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "Top Compartment Preheating"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "Water Change Reminder"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "Water Shortage"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "With Pressure"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "Zone1 Room-temperature Mode"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "Zone1 Water-temperature Mode"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "Zone2 Room-temperature Mode"
|
||||
},
|
||||
"microcrystal_fresh": {
|
||||
"name": "Microcrystal Fresh"
|
||||
},
|
||||
"electronic_smell": {
|
||||
"name": "Deodorizing sterilizing"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "Zone1 Thermostat"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "Zone2 Thermostat"
|
||||
},
|
||||
"climate_key": {
|
||||
"state_attributes": {
|
||||
"fan_mode": {
|
||||
"state": {
|
||||
"silent": "Silent",
|
||||
"full": "Full"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "Fresh Air"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "Child Lock"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "Dry Level"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "Heating Level"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "Seat Temperature Level"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "Water Temperature Level"
|
||||
},
|
||||
"fan_speed_percent": {
|
||||
"name": "Fan Speed Percent"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "Detect Mode"
|
||||
},
|
||||
"direction": {
|
||||
"name": "Direction"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "Fan Speed"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "Oscillation Angle"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "Oscillation Mode"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "Silent Level"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "Tilting Angle"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "Water Level Setting"
|
||||
},
|
||||
"wind_lr_angle": {
|
||||
"name": "Airflow Horizontal",
|
||||
"state": {
|
||||
"off": "Off",
|
||||
"left": "Left",
|
||||
"left-mid": "Left-Mid",
|
||||
"middle": "Middle",
|
||||
"right-mid": "Right-Mid",
|
||||
"right": "Right"
|
||||
}
|
||||
},
|
||||
"wind_ud_angle": {
|
||||
"name": "Airflow Vertical",
|
||||
"state": {
|
||||
"off": "Off",
|
||||
"up": "Up",
|
||||
"up-mid": "Up-Mid",
|
||||
"middle": "Middle",
|
||||
"down-mid": "Down-Mid",
|
||||
"down": "Down"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "Bathing Leaving Water Temperature"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "Bottom Compartment Remaining"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "Bottom Compartment Status"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "Bottom Compartment Temperature"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "Bottom Temperature"
|
||||
},
|
||||
"bright": {
|
||||
"name": "Bright Level"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "Compressor Temperature"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "Condenser Temperature"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "Current Energy Consumption"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "Current Temperature"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "Dehydration speed"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "Dehydration time"
|
||||
},
|
||||
"dehydration_time_value": {
|
||||
"name": "Dehydration time value"
|
||||
},
|
||||
"wash_time_value": {
|
||||
"name": "Wash time value"
|
||||
},
|
||||
"stains": {
|
||||
"name": "Stains"
|
||||
},
|
||||
"dirty_degree": {
|
||||
"name": "Dirty degree"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "Detergent"
|
||||
},
|
||||
"intensity": {
|
||||
"name": "Intensity"
|
||||
},
|
||||
"dryness_level": {
|
||||
"name": "Dryness Level"
|
||||
},
|
||||
"dry_temperature": {
|
||||
"name": "Dry Temperature"
|
||||
},
|
||||
"door_warn": {
|
||||
"name": "Door Warn"
|
||||
},
|
||||
"ai_switch": {
|
||||
"name": "AI Switch"
|
||||
},
|
||||
"material": {
|
||||
"name": "Material"
|
||||
},
|
||||
"water_box": {
|
||||
"name": "Water Box"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "Energy Consumption"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Error Code"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "Fan level"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "Filter Life"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "Filter1 Available Days"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "Filter1 Life Level"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "Filter2 Available Days"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "Filter2 Life Level"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "Filter3 Available Days"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "Filter3 Life Level"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "Flex Zone Actual Temperature"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "Flex Zone Setting Temperature"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "Freezer Actual Temperature"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "Freezer Setting Temperature"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "Methanal"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "Heating Leaving Water Temperature"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "Heating Time Remaining"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "In TDS"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "Indoor Humidity"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "Indoor Temperature"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "Keep Warm Remaining"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "Keep Warm Time"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "Middle Compartment Remaining"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "Middle Compartment Status"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "Middle Compartment Temperature"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "Out TDS"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "Outdoor Temperature"
|
||||
},
|
||||
"program": {
|
||||
"name": "Program"
|
||||
},
|
||||
"progress": {
|
||||
"name": "Progress"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "Realtime Power"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "Refrigerator Actual Temperature"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "Refrigerator Setting Temperature"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "Right Flex Zone Actual Temperature"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "Right Flex Zone Setting Temperature"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "Rinse count"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "Rinse level"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "Seat Temperature"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "Soak time"
|
||||
},
|
||||
"softener": {
|
||||
"name": "Softener"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "Softwater Level"
|
||||
},
|
||||
"status": {
|
||||
"name": "Status"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "Storage Remaining"
|
||||
},
|
||||
"tank": {
|
||||
"name": "Tank"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "Tank Actual Temperature"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "Target Temperature"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "Time Remaining"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "Top Compartment Remaining"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "Top Compartment Status"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "Top Compartment Temperature"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "Top Temperature"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "Total Energy Consumption"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "Total produced energy"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "TVOC"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "Wash strength"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "Wash time"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "Water Consumption"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "Water Temperature"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "Water Level"
|
||||
},
|
||||
"wind": {
|
||||
"name": "Wind"
|
||||
},
|
||||
"typeinfo": {
|
||||
"name": "Type Info"
|
||||
},
|
||||
"elec_heat": {
|
||||
"name": "Electric Heat"
|
||||
},
|
||||
"water_pump": {
|
||||
"name": "Water Pump"
|
||||
},
|
||||
"four_way": {
|
||||
"name": "Four Way Valve"
|
||||
},
|
||||
"back_water": {
|
||||
"name": "Back Water"
|
||||
},
|
||||
"sterilize": {
|
||||
"name": "Sterilize"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "Working Time"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "Humidity"
|
||||
},
|
||||
"variable_mode": {
|
||||
"name": "Variable Mode"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "Anion"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "Aux Heating"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "Boost Mode"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "Breezeless"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "Comfort Mode"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "DHW Power"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "Disinfect"
|
||||
},
|
||||
"dry": {
|
||||
"name": "Dry"
|
||||
},
|
||||
"cold_water_single": {
|
||||
"name": "Cold Water Single"
|
||||
},
|
||||
"cold_water_dot": {
|
||||
"name": "Cold Water Dot"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "ECO Mode"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "Fast DHW"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "Foam Shield"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "Frost Protect"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "Indirect Wind"
|
||||
},
|
||||
"light": {
|
||||
"name": "Light"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "Link to AC"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "Main Light"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "Main Power"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "Natural Wind"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "Night Light"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "Oscillate"
|
||||
},
|
||||
"power": {
|
||||
"name": "Power"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "Powerful Purification"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "Prompt Tone"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "Screen Display Alternate"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "Sensor Light"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "Silent Mode"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "Sleep Mode"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "Smart Eye"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "Smart Volume"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "Smelly Sensor"
|
||||
},
|
||||
"standby": {
|
||||
"name": "Standby"
|
||||
},
|
||||
"start": {
|
||||
"name": "Start"
|
||||
},
|
||||
"storage": {
|
||||
"name": "Storage"
|
||||
},
|
||||
"swing": {
|
||||
"name": "Swing"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "Swing Horizontal"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "Swing Vertical"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "Variable Heating"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "Ventilation"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "Whole Tank Heating"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "Zero Cold Water (Pulse)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "Zero Cold Water"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "Zone1 Curve"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "Zone1 Power"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "Zone2 Curve"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "Zone2 Power"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "Domestic hot water"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "Bathing"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "IP address",
|
||||
"refresh_interval": "Refresh interval (0 means not refreshing actively)",
|
||||
"sensors": "Extra sensors",
|
||||
"switches": "Extra controls",
|
||||
"customize": "Customize"
|
||||
},
|
||||
"title": "Configure"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "The account does not supports this operation.\nClick \"ADD DEVICE\" to add a new device."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "Set attribute",
|
||||
"description": "Set the attribute value of device",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Appliance code",
|
||||
"description": "The appliance code (Device ID) of appliance"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "Attribute",
|
||||
"description": "The attribute name want to set"
|
||||
},
|
||||
"value": {
|
||||
"name": "Value",
|
||||
"description": "The attribute value want to set"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "Customize command",
|
||||
"description": "Send a customize command to device",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Appliance code",
|
||||
"description": "The appliance code (Device ID) of appliance"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "Command type",
|
||||
"description": "The type of command,should be 3(query) or 2(set)"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "Command body",
|
||||
"description": "The body of command, (not include MSmart protocol head and checksum at the end)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,795 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "Fallo al iniciar sesión con la cuenta preestablecida, por favor reporte este problema",
|
||||
"login_failed": "Fallo al iniciar sesión, la cuenta o la contraseña son incorrectas",
|
||||
"no_devices": "No se encontraron nuevos electrodomésticos disponibles en la red",
|
||||
"device_exist": "El electrodoméstico ya está configurado",
|
||||
"config_incorrect": "La configuración es incorrecta",
|
||||
"connect_error": "No se puede conectar con el electrodoméstico",
|
||||
"invalid_token": "Identificador o clave en un formato incorrecto"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "Añadir electrodomésticos"
|
||||
},
|
||||
"description": "Elija la forma de añadir un electrodoméstico",
|
||||
"title": "Añadir nuevo electrodoméstico"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "Cuenta",
|
||||
"password": "Contraseña"
|
||||
},
|
||||
"description": "Inicie sesión y guarde su cuenta Midea solo para obtener la información del electrodoméstico.\nPuede eliminar esta configuración después de haber configurado todos los dispositivos.",
|
||||
"title": "Iniciar sesión"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "Dirección IP del dispositivo, escriba \"auto\" para descubrir automáticamente.\nTambién puede usar una dirección IP para buscar dentro de una red específica, como \"192.168.1.255\"",
|
||||
"title": "Buscar",
|
||||
"data": {
|
||||
"ip_address": "Dirección IP"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "Electrodomésticos"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "Electrodomésticos"
|
||||
},
|
||||
"description": "Elija un electrodoméstico para añadir",
|
||||
"title": "Nuevo electrodoméstico encontrado"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "Nombre (ej. AA Salón)",
|
||||
"device_id": "Código del electrodoméstico",
|
||||
"type": "Tipo",
|
||||
"ip_address": "Dirección IP",
|
||||
"port": "Puerto",
|
||||
"model": "Modelo",
|
||||
"subtype": "Subtipo",
|
||||
"protocol": "Protocolo",
|
||||
"token": "Token",
|
||||
"key": "Clave"
|
||||
},
|
||||
"description": "Configuración del electrodoméstico",
|
||||
"title": "Nuevo electrodoméstico"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "Puerta del bar"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "Puerta del bar abierta demasiado tiempo"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "Estado de funcionamiento del baño"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "Enfriamiento del compartimento inferior"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "Puerta del compartimento inferior"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "Precalentamiento del compartimento inferior"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "Estado de combustión"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "Recordatorio de limpieza"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "Estado del compresor"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "Cocinando"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "Recordatorio de cambio de filtro"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "Recordatorio de limpieza de filtro"
|
||||
},
|
||||
"finished": {
|
||||
"name": "Terminado"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "Puerta de zona flexible"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "Puerta de zona flexible abierta demasiado tiempo"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "Puerta del congelador"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "Puerta del congelador abierta demasiado tiempo"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "Lleno de polvo"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Calentando"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "Estado de funcionamiento de calefacción"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "Mantener caliente"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "Estado de la tapa"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "Enfriamiento del compartimento medio"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "Puerta del compartimento medio"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "Precalentamiento del compartimento medio"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "Depósito de aceite lleno"
|
||||
},
|
||||
"protection": {
|
||||
"name": "Protección"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "Puerta del frigorífico"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "Puerta del frigorífico abierta demasiado tiempo"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "Escasez de abrillantador"
|
||||
},
|
||||
"salt": {
|
||||
"name": "Escasez de sal"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "Estado del asiento"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "Estado ACS"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "Estado calefacción"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "Estado IBH"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "Estado TBH"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "Depósito extraído"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "Estado del depósito"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "Enfriamiento del compartimento superior"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "Puerta del compartimento superior"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "Precalentamiento del compartimento superior"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "Recordatorio de cambio de agua"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "Escasez de agua"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "Con presión"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "Zona 1 Modo temperatura ambiente"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "Zona 1 Modo temperatura del agua"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "Zona 2 Modo temperatura ambiente"
|
||||
},
|
||||
"microcrystal_fresh": {
|
||||
"name": "Frescura microcristalina"
|
||||
},
|
||||
"electronic_smell": {
|
||||
"name": "Esterilización desodorizante"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "Termostato Zona 1"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "Termostato Zona 2"
|
||||
},
|
||||
"climate_key": {
|
||||
"state_attributes": {
|
||||
"fan_mode": {
|
||||
"state": {
|
||||
"silent": "Silencioso",
|
||||
"full": "Máximo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "Aire fresco"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "Bloqueo infantil"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "Nivel de secado"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "Nivel de calefacción"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "Nivel de temperatura del asiento"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "Nivel de temperatura del agua"
|
||||
},
|
||||
"fan_speed_percent": {
|
||||
"name": "Porcentaje de velocidad del ventilador"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "Modo de detección"
|
||||
},
|
||||
"direction": {
|
||||
"name": "Dirección"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "Velocidad del ventilador"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Modo"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "Ángulo de oscilación"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "Modo de oscilación"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Visualización de pantalla"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "Nivel de silencio"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "Ángulo de inclinación"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "Ajuste de nivel de agua"
|
||||
},
|
||||
"wind_lr_angle": {
|
||||
"name": "Flujo de aire horizontal",
|
||||
"state": {
|
||||
"off": "Apagado",
|
||||
"left": "Izquierda",
|
||||
"left-mid": "Izquierda-Medio",
|
||||
"middle": "Medio",
|
||||
"right-mid": "Derecha-Medio",
|
||||
"right": "Derecha"
|
||||
}
|
||||
},
|
||||
"wind_ud_angle": {
|
||||
"name": "Flujo de aire vertical",
|
||||
"state": {
|
||||
"off": "Apagado",
|
||||
"up": "Arriba",
|
||||
"up-mid": "Arriba-Medio",
|
||||
"middle": "Medio",
|
||||
"down-mid": "Abajo-Medio",
|
||||
"down": "Abajo"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "Temperatura de salida del agua de baño"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "Tiempo restante compartimento inferior"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "Estado del compartimento inferior"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "Temperatura del compartimento inferior"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "Temperatura inferior"
|
||||
},
|
||||
"bright": {
|
||||
"name": "Nivel de brillo"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "Temperatura del compresor"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "Temperatura del condensador"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "Consumo de energía actual"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "Temperatura actual"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "Velocidad de centrifugado"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "Tiempo de centrifugado"
|
||||
},
|
||||
"dehydration_time_value": {
|
||||
"name": "Valor del tiempo de centrifugado"
|
||||
},
|
||||
"wash_time_value": {
|
||||
"name": "Valor del tiempo de lavado"
|
||||
},
|
||||
"stains": {
|
||||
"name": "Manchas"
|
||||
},
|
||||
"dirty_degree": {
|
||||
"name": "Grado de suciedad"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "Detergente"
|
||||
},
|
||||
"intensity": {
|
||||
"name": "Intensidad"
|
||||
},
|
||||
"dryness_level": {
|
||||
"name": "Nivel de sequedad"
|
||||
},
|
||||
"dry_temperature": {
|
||||
"name": "Temperatura de secado"
|
||||
},
|
||||
"door_warn": {
|
||||
"name": "Advertencia de puerta"
|
||||
},
|
||||
"ai_switch": {
|
||||
"name": "Interruptor IA"
|
||||
},
|
||||
"material": {
|
||||
"name": "Material"
|
||||
},
|
||||
"water_box": {
|
||||
"name": "Caja de agua"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "Consumo de energía"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Código de error"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "Nivel del ventilador"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "Vida útil del filtro"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "Días disponibles Filtro 1"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "Nivel de vida Filtro 1"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "Días disponibles Filtro 2"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "Nivel de vida Filtro 2"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "Días disponibles Filtro 3"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "Nivel de vida Filtro 3"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "Temperatura real de zona flexible"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "Temperatura establecida de zona flexible"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "Temperatura real del congelador"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "Temperatura establecida del congelador"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "Formaldehído"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "Temperatura de salida del agua de calefacción"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Potencia de calefacción"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "Tiempo restante de calefacción"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "TDS de entrada"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "Humedad interior"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "Temperatura interior"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "Tiempo restante de mantener caliente"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "Tiempo de mantener caliente"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "Tiempo restante compartimento medio"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "Estado del compartimento medio"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "Temperatura del compartimento medio"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Modo"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "TDS de salida"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "Temperatura exterior"
|
||||
},
|
||||
"program": {
|
||||
"name": "Programa"
|
||||
},
|
||||
"progress": {
|
||||
"name": "Progreso"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "Potencia en tiempo real"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "Temperatura real del frigorífico"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "Temperatura establecida del frigorífico"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "Temperatura real de zona flexible derecha"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "Temperatura establecida de zona flexible derecha"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "Recuento de aclarados"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "Nivel de aclarado"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "Temperatura del asiento"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "Tiempo de remojo"
|
||||
},
|
||||
"softener": {
|
||||
"name": "Suavizante"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "Nivel de agua blanda"
|
||||
},
|
||||
"status": {
|
||||
"name": "Estado"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "Almacenamiento restante"
|
||||
},
|
||||
"tank": {
|
||||
"name": "Depósito"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "Temperatura real del depósito"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "Temperatura objetivo"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "Tiempo restante"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "Tiempo restante compartimento superior"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "Estado del compartimento superior"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "Temperatura del compartimento superior"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "Temperatura superior"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "Consumo total de energía"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "Energía total producida"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "COVT"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "Potencia de lavado"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "Tiempo de lavado"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "Consumo de agua"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "Temperatura del agua"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "Nivel de agua"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "Tiempo de funcionamiento"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "Humedad"
|
||||
},
|
||||
"variable_mode": {
|
||||
"name": "Modo variable"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "Anión"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "Calefacción auxiliar"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "Modo potente"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "Sin corrientes"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "Modo confort"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "Potencia ACS"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "Desinfectar"
|
||||
},
|
||||
"dry": {
|
||||
"name": "Secado"
|
||||
},
|
||||
"cold_water_single": {
|
||||
"name": "Agua fría individual"
|
||||
},
|
||||
"cold_water_dot": {
|
||||
"name": "Agua fría punto"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "Modo ECO"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "ACS Rápido"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "Escudo de espuma"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "Protección contra heladas"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Potencia de calefacción"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "Viento indirecto"
|
||||
},
|
||||
"light": {
|
||||
"name": "Luz"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "Vincular a AA"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "Luz principal"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "Alimentación principal"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "Viento natural"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "Luz nocturna"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "Oscilar"
|
||||
},
|
||||
"power": {
|
||||
"name": "Encendido"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "Purificación potente"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "Tono de aviso"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Visualización de pantalla"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "Pantalla alterna"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "Luz con sensor"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "Modo silencioso"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "Modo sueño"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "Ojo inteligente"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "Volumen inteligente"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "Sensor de olores"
|
||||
},
|
||||
"standby": {
|
||||
"name": "En espera"
|
||||
},
|
||||
"start": {
|
||||
"name": "Iniciar"
|
||||
},
|
||||
"storage": {
|
||||
"name": "Almacenamiento"
|
||||
},
|
||||
"swing": {
|
||||
"name": "Oscilación"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "Oscilación horizontal"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "Oscilación vertical"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "Calefacción variable"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "Ventilación"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "Calentamiento de tanque completo"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "Cero agua fría (Pulso)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "Cero agua fría"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "Curva Zona 1"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "Potencia Zona 1"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "Curva Zona 2"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "Potencia Zona 2"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "Agua caliente sanitaria"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "Baño"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Calefacción"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "Dirección IP",
|
||||
"refresh_interval": "Intervalo de actualización (0 significa no actualizar activamente)",
|
||||
"sensors": "Sensores extra",
|
||||
"switches": "Controles extra",
|
||||
"customize": "Personalizar"
|
||||
},
|
||||
"title": "Configurar"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "La cuenta no admite esta operación.\nHaga clic en \"AÑADIR DISPOSITIVO\" para agregar un nuevo dispositivo."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "Establecer atributo",
|
||||
"description": "Establecer el valor del atributo del dispositivo",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Código del electrodoméstico",
|
||||
"description": "El código (ID de dispositivo) del electrodoméstico"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "Atributo",
|
||||
"description": "El nombre del atributo que desea establecer"
|
||||
},
|
||||
"value": {
|
||||
"name": "Valor",
|
||||
"description": "El valor del atributo que desea establecer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "Comando personalizado",
|
||||
"description": "Enviar un comando personalizado al dispositivo",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Código del electrodoméstico",
|
||||
"description": "El código (ID de dispositivo) del electrodoméstico"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "Tipo de comando",
|
||||
"description": "El tipo de comando, debe ser 3 (consulta) o 2 (ajuste)"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "Cuerpo del comando",
|
||||
"description": "El cuerpo del comando, (no incluye el encabezado del protocolo MSmart ni la suma de comprobación al final)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,715 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "Failed to login with preset account, please report this issue",
|
||||
"login_failed": "Failed to login, account or password was wrong",
|
||||
"no_devices": "Aucun nouvel apparel trouvé sur le réseau",
|
||||
"device_exist": "L'appareil est déjà configurée",
|
||||
"config_incorrect": "La configuration est incorrecte",
|
||||
"connect_error": "Impossible de se connecter à l'appareil",
|
||||
"invalid_token": "Token ou Key dans un format incorrect"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "Ajout d'appareil"
|
||||
},
|
||||
"description": "Choisissez comment ajouter des appareils",
|
||||
"title": "Ajouter un nouvel apparel"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "Account",
|
||||
"password": "Password"
|
||||
},
|
||||
"description": "Login and storage your Midea account only for getting the appliance info.\nYou can remove this configuration after all appliance configured.",
|
||||
"title": "Login"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "Saisissez l'address IP de l'appareil, entrez \"auto\" pour découvrir automatiquement.\nVous pouvez également utiliser une address IP pour rechercher dans un réseau spécifié, comme \"192.168.1.255\".",
|
||||
"title": "Recherche",
|
||||
"data": {
|
||||
"ip_address": "Address IP"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "Apparel"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "Apparel"
|
||||
},
|
||||
"description": "Choisissez un apparel à ajouter",
|
||||
"title": "Nouvel apparel trouvé"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "Nom (ex: Clim Salon)",
|
||||
"device_id": "Code apparel",
|
||||
"type": "Type",
|
||||
"ip_address": "Address IP",
|
||||
"port": "Port",
|
||||
"model": "Modèle",
|
||||
"subtype": "Soustype",
|
||||
"protocol": "Protocole",
|
||||
"token": "Token",
|
||||
"key": "Key"
|
||||
},
|
||||
"description": "Configuration de l'appareil",
|
||||
"title": "Nouvel apparel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "Bar Door"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "Bar Door Overtime"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "Bathing Working Status"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "Bottom Compartment Cooling"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "Bottom Compartment Door"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "Bottom Compartment Preheating"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "Burning State"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "Cleaning Reminder"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "Compressor Status"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "Cooking"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "Filter Change Reminder"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "Filter Cleaning Reminder"
|
||||
},
|
||||
"finished": {
|
||||
"name": "Finished"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "Flex Door"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "Flex Zone Door"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "Freezer Door"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "Freezer Door Overtime"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "Full of Dust"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "Heating Working Status"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "Keep Warm"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "Lid Status"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "Middle Compartment Cooling"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "Middle Compartment Door"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "Middle Compartment Preheating"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "Oil-cup Full"
|
||||
},
|
||||
"protection": {
|
||||
"name": "Protection"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "Refrigerator Door"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "Refrigerator Door Overtime"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "Rinse Aid Shortage"
|
||||
},
|
||||
"salt": {
|
||||
"name": "Salt Shortage"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "Seat Status"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "DHW status"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "Heating status"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "IBH status"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "TBH status"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "Tank Ejected"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "Tank status"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "Top Compartment Cooling"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "Top Compartment Door"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "Top Compartment Preheating"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "Water Change Reminder"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "Water Shortage"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "With Pressure"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "Zone1 Room-temperature Mode"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "Zone1 Water-temperature Mode"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "Zone2 Room-temperature Mode"
|
||||
},
|
||||
"zone2_water_temp_mode": {
|
||||
"name": "Zone2 Water-temperature Mode"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "Zone1 Thermostat"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "Zone2 Thermostat"
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "Fresh Air"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "Child Lock"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "Dry Level"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "Heating Level"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "Seat Temperature Level"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "Water Temperature Level"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "Detect Mode"
|
||||
},
|
||||
"direction": {
|
||||
"name": "Direction"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "Fan Speed"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "Oscillation Angle"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "Oscillation Mode"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "Silent Level"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "Tilting Angle"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "Water Level Setting"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "Bathing Leaving Water Temperature"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "Bottom Compartment Remaining"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "Bottom Compartment Status"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "Bottom Compartment Temperature"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "Bottom Temperature"
|
||||
},
|
||||
"bright": {
|
||||
"name": "Bright Level"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "Compressor Temperature"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "Condenser Temperature"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "Current Energy Consumption"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "Current Temperature"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "dehydration speed"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "dehydration time"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "detergent"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "Energy Consumption"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Error Code"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "Fan level"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "Filter Life"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "Filter1 Available Days"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "Filter1 Life Level"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "Filter2 Available Days"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "Filter2 Life Level"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "Filter3 Available Days"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "Filter3 Life Level"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "Flex Zone Actual Temperature"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "Flex Zone Setting Temperature"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "Freezer Actual Temperature"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "Freezer Setting Temperature"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "Methanal"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "Heating Leaving Water Temperature"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "Heating Time Remaining"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "In TDS"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "Indoor Humidity"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "Indoor Temperature"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "Keep Warm Remaining"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "Keep Warm Time"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "Middle Compartment Remaining"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "Middle Compartment Status"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "Middle Compartment Temperature"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "Out TDS"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "Outdoor Temperature"
|
||||
},
|
||||
"program": {
|
||||
"name": "Program"
|
||||
},
|
||||
"progress": {
|
||||
"name": "Progress"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "Realtime Power"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "Refrigerator Actual Temperature"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "Refrigerator Setting Temperature"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "Right Flex Zone Actual Temperature"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "Right Flex Zone Setting Temperature"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "rinse level"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "Seat Temperature"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "soak time"
|
||||
},
|
||||
"softener": {
|
||||
"name": "softener"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "Softwater Level"
|
||||
},
|
||||
"status": {
|
||||
"name": "Status"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "Storage Remaining"
|
||||
},
|
||||
"tank": {
|
||||
"name": "Tank"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "Tank Actual Temperature"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "Target Temperature"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "Time Remaining"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "Top Compartment Remaining"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "Top Compartment Status"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "Top Compartment Temperature"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "Top Temperature"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "Total Energy Consumption"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "Total produced energy"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "TVOC"
|
||||
},
|
||||
"wash_level": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "wash strength"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "wash time"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "Water Consumption"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "Water Temperature"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "Water Level"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "Working Time"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "Anion"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "Aux Heating"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "Boost Mode"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "Breezeless"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "Comfort Mode"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "DHW Power"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "Disinfect"
|
||||
},
|
||||
"dry": {
|
||||
"name": "Dry"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "ECO Mode"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "Fast DHW"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "Foam Shield"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "Frost Protect"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "Indirect Wind"
|
||||
},
|
||||
"light": {
|
||||
"name": "Light"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "Link to AC"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "Main Light"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "Main Power"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "Natural Wind"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "Night Light"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "Oscillate"
|
||||
},
|
||||
"power": {
|
||||
"name": "Power"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "Powerful Purification"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "Prompt Tone"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "Screen Display Alternate"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "Sensor Light"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "Silent Mode"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "Sleep Mode"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "Smart Eye"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "Smart Volume"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "Smelly Sensor"
|
||||
},
|
||||
"standby": {
|
||||
"name": "Standby"
|
||||
},
|
||||
"start": {
|
||||
"name": "Start"
|
||||
},
|
||||
"storage": {
|
||||
"name": "Storage"
|
||||
},
|
||||
"swing": {
|
||||
"name": "swing"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "Swing Horizontal"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "Swing Vertical"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "Variable Heating"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "Ventilation"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "Whole Tank Heating"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "Zero Cold Water (Pulse)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "Zero Cold Water"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "Zone1 Curve"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "Zone1 Power"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "Zone2 Curve"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "Zone2 Power"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "Domestic hot water"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "Bathing"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "Address IP",
|
||||
"refresh_interval": "Refresh interval (0 means not refreshing actively)",
|
||||
"sensors": "Capteurs supplémentaire",
|
||||
"switches": "Contrôles supplémentaire",
|
||||
"customize": "Personnaliser"
|
||||
},
|
||||
"title": "Configurer"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "The account does not supports this operation.\nClick \"ADD DEVICE\" to add a new device."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "Définir l'attribut",
|
||||
"description": "Définir la valeur d'attribut de l'appareil",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Code apparel",
|
||||
"description": "Code de l'appareil (ID de l'appareil)"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "Attribute",
|
||||
"description": "Nom de l'attribut que vous souhaitez définir"
|
||||
},
|
||||
"value": {
|
||||
"name": "Valeur",
|
||||
"description": "Valeur d'attribut que vous souhaitez définir"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "Customize command",
|
||||
"description": "Send a customize command to device",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Code apparel",
|
||||
"description": "Code de l'appareil (ID de l'appareil)"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "command type",
|
||||
"description": "The type of command,should be 3(query) or 2(set)"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "command body",
|
||||
"description": "The body of command, (not include MSmart protocol head and checksum at the end)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,715 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "Failed to login with preset account, please report this issue",
|
||||
"login_failed": "Bejelentkezés sikertelen, a fiók vagy a jelszó helytelen",
|
||||
"no_devices": "Nem találhatóak új eszközök a hálózaton",
|
||||
"device_exist": "Az eszköz már be van állítva",
|
||||
"config_incorrect": "A beállítások helytelenek",
|
||||
"connect_error": "Nem sikerült csatlakozni az eszközhöz",
|
||||
"invalid_token": "A Token vagy a Key formátuma helytelen"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "Eszközök hozzáadása"
|
||||
},
|
||||
"description": "Válassza ki az eszközök hozzáadásának módját",
|
||||
"title": "Új eszköz hozzáadása"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "Fiók",
|
||||
"password": "Jelszó"
|
||||
},
|
||||
"description": "Jelentkezzen be és tárolja el Midea-fiókját, kizárólag a készülékei információinak a megszerzéséhez.\nAz összes készülékének beállítása után eltávolíthatja ezt a konfigurációt.",
|
||||
"title": "Bejelentkezés"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "Adja meg az eszköz IP címét vagy írja be az \"auto\" kifejezést az automatikus kereséshez.\nIP-címet is használhat egy megadott hálózaton belüli kereséshez, például \"192.168.1.255\".",
|
||||
"title": "Keresés",
|
||||
"data": {
|
||||
"ip_address": "IP cím"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "Eszközök"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "Eszközök"
|
||||
},
|
||||
"description": "Válassza ki a hozzáadandó eszközt",
|
||||
"title": "Új eszköz található"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "Név (pl. Nappali légkondicionáló)",
|
||||
"device_id": "Eszköz kód",
|
||||
"type": "Típus",
|
||||
"ip_address": "IP cím",
|
||||
"port": "Port",
|
||||
"model": "Model",
|
||||
"subtype": "Altípus",
|
||||
"protocol": "Protokoll",
|
||||
"token": "Token",
|
||||
"key": "Key"
|
||||
},
|
||||
"description": "Eszköz konfigurációja",
|
||||
"title": "Új eszköz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "Bar Door"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "Bar Door Overtime"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "Bathing Working Status"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "Bottom Compartment Cooling"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "Bottom Compartment Door"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "Bottom Compartment Preheating"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "Burning State"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "Cleaning Reminder"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "Compressor Status"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "Cooking"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "Filter Change Reminder"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "Filter Cleaning Reminder"
|
||||
},
|
||||
"finished": {
|
||||
"name": "Finished"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "Flex Door"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "Flex Zone Door"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "Freezer Door"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "Freezer Door Overtime"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "Full of Dust"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "Heating Working Status"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "Keep Warm"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "Lid Status"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "Middle Compartment Cooling"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "Middle Compartment Door"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "Middle Compartment Preheating"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "Oil-cup Full"
|
||||
},
|
||||
"protection": {
|
||||
"name": "Protection"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "Refrigerator Door"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "Refrigerator Door Overtime"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "Rinse Aid Shortage"
|
||||
},
|
||||
"salt": {
|
||||
"name": "Salt Shortage"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "Seat Status"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "DHW status"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "Heating status"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "IBH status"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "TBH status"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "Tank Ejected"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "Tank status"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "Top Compartment Cooling"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "Top Compartment Door"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "Top Compartment Preheating"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "Water Change Reminder"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "Water Shortage"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "With Pressure"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "Zone1 Room-temperature Mode"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "Zone1 Water-temperature Mode"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "Zone2 Room-temperature Mode"
|
||||
},
|
||||
"zone2_water_temp_mode": {
|
||||
"name": "Zone2 Water-temperature Mode"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "Zone1 Thermostat"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "Zone2 Thermostat"
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "Fresh Air"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "Child Lock"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "Dry Level"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "Heating Level"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "Seat Temperature Level"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "Water Temperature Level"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "Detect Mode"
|
||||
},
|
||||
"direction": {
|
||||
"name": "Direction"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "Fan Speed"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "Oscillation Angle"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "Oscillation Mode"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "Silent Level"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "Tilting Angle"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "Water Level Setting"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "Bathing Leaving Water Temperature"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "Bottom Compartment Remaining"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "Bottom Compartment Status"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "Bottom Compartment Temperature"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "Bottom Temperature"
|
||||
},
|
||||
"bright": {
|
||||
"name": "Bright Level"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "Compressor Temperature"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "Condenser Temperature"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "Current Energy Consumption"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "Current Temperature"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "dehydration speed"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "dehydration time"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "detergent"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "Energy Consumption"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Error Code"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "Fan level"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "Filter Life"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "Filter1 Available Days"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "Filter1 Life Level"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "Filter2 Available Days"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "Filter2 Life Level"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "Filter3 Available Days"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "Filter3 Life Level"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "Flex Zone Actual Temperature"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "Flex Zone Setting Temperature"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "Freezer Actual Temperature"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "Freezer Setting Temperature"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "Methanal"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "Heating Leaving Water Temperature"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "Heating Time Remaining"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "In TDS"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "Indoor Humidity"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "Indoor Temperature"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "Keep Warm Remaining"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "Keep Warm Time"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "Middle Compartment Remaining"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "Middle Compartment Status"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "Middle Compartment Temperature"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "Out TDS"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "Outdoor Temperature"
|
||||
},
|
||||
"program": {
|
||||
"name": "Program"
|
||||
},
|
||||
"progress": {
|
||||
"name": "Progress"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "Realtime Power"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "Refrigerator Actual Temperature"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "Refrigerator Setting Temperature"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "Right Flex Zone Actual Temperature"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "Right Flex Zone Setting Temperature"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "rinse level"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "Seat Temperature"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "soak time"
|
||||
},
|
||||
"softener": {
|
||||
"name": "softener"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "Softwater Level"
|
||||
},
|
||||
"status": {
|
||||
"name": "Status"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "Storage Remaining"
|
||||
},
|
||||
"tank": {
|
||||
"name": "Tank"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "Tank Actual Temperature"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "Target Temperature"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "Time Remaining"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "Top Compartment Remaining"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "Top Compartment Status"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "Top Compartment Temperature"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "Top Temperature"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "Total Energy Consumption"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "Total produced energy"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "TVOC"
|
||||
},
|
||||
"wash_level": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "wash strength"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "wash time"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "Water Consumption"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "Water Temperature"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "Water Level"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "Working Time"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "Anion"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "Aux Heating"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "Boost Mode"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "Breezeless"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "Comfort Mode"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "DHW Power"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "Disinfect"
|
||||
},
|
||||
"dry": {
|
||||
"name": "Dry"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "ECO Mode"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "Fast DHW"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "Foam Shield"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "Frost Protect"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "Indirect Wind"
|
||||
},
|
||||
"light": {
|
||||
"name": "Light"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "Link to AC"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "Main Light"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "Main Power"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "Natural Wind"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "Night Light"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "Oscillate"
|
||||
},
|
||||
"power": {
|
||||
"name": "Power"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "Powerful Purification"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "Prompt Tone"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "Screen Display Alternate"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "Sensor Light"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "Silent Mode"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "Sleep Mode"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "Smart Eye"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "Smart Volume"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "Smelly Sensor"
|
||||
},
|
||||
"standby": {
|
||||
"name": "Standby"
|
||||
},
|
||||
"start": {
|
||||
"name": "Start"
|
||||
},
|
||||
"storage": {
|
||||
"name": "Storage"
|
||||
},
|
||||
"swing": {
|
||||
"name": "swing"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "Swing Horizontal"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "Swing Vertical"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "Variable Heating"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "Ventilation"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "Whole Tank Heating"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "Zero Cold Water (Pulse)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "Zero Cold Water"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "Zone1 Curve"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "Zone1 Power"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "Zone2 Curve"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "Zone2 Power"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "Domestic hot water"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "Bathing"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "IP cím",
|
||||
"refresh_interval": "Frissítési intervallum (0 azt jelenti, hogy nincs aktív frissítés)",
|
||||
"sensors": "Extra érzékelők",
|
||||
"switches": "Extra vezérlők",
|
||||
"customize": "Személyre szabás"
|
||||
},
|
||||
"title": "Konfigurálás"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "A fiók nem támogatja ezt a műveletet.\nKattintson az \"ESZKÖZ HOZZÁADÁSA\" gombra egy új eszköz hozzáadásához."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "Attribútum beállítása",
|
||||
"description": "Állítsa be az eszköz attribútumának értékét",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Eszköz kód",
|
||||
"description": "A készülék kódja (eszköz ID)"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "Attribútum",
|
||||
"description": "A beállítandó attribútum neve"
|
||||
},
|
||||
"value": {
|
||||
"name": "Érték",
|
||||
"description": "A beállítandó attribútum értéke"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "Egyéni parancs",
|
||||
"description": "Küldjön egy egyéni parancsot az eszköznek",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Eszköz kód",
|
||||
"description": "A készülék kódja (Eszköz ID)"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "Parancs típusa",
|
||||
"description": "A parancs típusa, lehet 3 (lekérdezés) vagy 2 (beállítás)"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "Parancs törzse",
|
||||
"description": "A parancs törzse (nem tartalmazza az MSmart protokoll fejlécét és a végén lévő ellenőrző összeget)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,745 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "Failed to login with preset account, please report this issue",
|
||||
"login_failed": "Не удалось авторизоваться, неверное имя аккаунта или пароль",
|
||||
"no_devices": "Новые доступные устройства в локальной сети не найдены",
|
||||
"device_exist": "Устройство уже настроено",
|
||||
"config_incorrect": "Некорректная конфигурация",
|
||||
"connect_error": "Не удается подключиться к устройству",
|
||||
"invalid_token": "Некорректный формат Token или Key"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "Добавление устройства"
|
||||
},
|
||||
"description": "Выберите способ добавления устройств",
|
||||
"title": "Добавить новое устройство"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "Аккаунт",
|
||||
"password": "Пароль"
|
||||
},
|
||||
"description": "Login and storage your Midea account only for getting the appliance info.\nYou can remove this configuration after all appliance configured.",
|
||||
"title": "Login"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "Введите IP-адрес устройства или \"auto\", чтобы обнаружить устройства автоматически.\nВы также можете использовать IP-адрес для поиска в определенной сети, например, \"192.168.1.255\"",
|
||||
"title": "Поиск",
|
||||
"data": {
|
||||
"ip_address": "IP-адрес"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "Устройства"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "Устройства"
|
||||
},
|
||||
"description": "Выберите устройство для добавления",
|
||||
"title": "Найдено новое устройство"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "Название (например, Кондиционер в гостиной)",
|
||||
"device_id": "Идентификатор устройства",
|
||||
"type": "Тип",
|
||||
"ip_address": "IP-адрес",
|
||||
"port": "Порт",
|
||||
"model": "Модель",
|
||||
"subtype": "Подтип",
|
||||
"protocol": "Протокол",
|
||||
"token": "Token",
|
||||
"key": "Key"
|
||||
},
|
||||
"description": "Настройка устройства",
|
||||
"title": "Новое устройство"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "Bar Door"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "Bar Door Overtime"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "Bathing Working Status"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "Bottom Compartment Cooling"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "Bottom Compartment Door"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "Bottom Compartment Preheating"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "Burning State"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "Требуется очистка"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "Статус компрессора"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "Приготовление"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "Требуется замена фильтра"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "Требуется очистка фильтра"
|
||||
},
|
||||
"finished": {
|
||||
"name": "Завершено"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "Flex Door"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "Flex Zone Door"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "Freezer Door"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "Freezer Door Overtime"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "Загрязнение"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Нагрев"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "Heating Working Status"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "Поддержание температуры"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "Крышка"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "Middle Compartment Cooling"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "Middle Compartment Door"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "Middle Compartment Preheating"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "Oil-cup Full"
|
||||
},
|
||||
"protection": {
|
||||
"name": "Защита"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "Refrigerator Door"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "Refrigerator Door Overtime"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "Нехватка ополаскивателя"
|
||||
},
|
||||
"salt": {
|
||||
"name": "Соль"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "Сиденье"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "DHW status"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "Подогрев"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "IBH status"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "TBH status"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "Tank Ejected"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "Tank status"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "Top Compartment Cooling"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "Top Compartment Door"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "Top Compartment Preheating"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "Water Change Reminder"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "Нехватка воды"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "With Pressure"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "Zone1 Room-temperature Mode"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "Zone1 Water-temperature Mode"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "Zone2 Room-temperature Mode"
|
||||
},
|
||||
"zone2_water_temp_mode": {
|
||||
"name": "Zone2 Water-temperature Mode"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "Zone1 Thermostat"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "Zone2 Thermostat"
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "Fresh Air"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "Блокировка"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "Dry Level"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "Heating Level"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "Seat Temperature Level"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "Water Temperature Level"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "Detect Mode"
|
||||
},
|
||||
"direction": {
|
||||
"name": "Направление"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "Скорость"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Режим"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "Oscillation Angle"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "Oscillation Mode"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "Silent Level"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "Угол поворота"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "Water Level Setting"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "Bathing Leaving Water Temperature"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "Bottom Compartment Remaining"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "Bottom Compartment Status"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "Bottom Compartment Temperature"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "Bottom Temperature"
|
||||
},
|
||||
"bright": {
|
||||
"name": "Bright Level"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "Compressor Temperature"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "Condenser Temperature"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "Current Energy Consumption"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "Текущая температура"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "Dehydration speed"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "Dehydration time"
|
||||
},
|
||||
"dehydration_time_value": {
|
||||
"name": "Dehydration time value"
|
||||
},
|
||||
"wash_time_value": {
|
||||
"name": "Wash time value"
|
||||
},
|
||||
"stains": {
|
||||
"name": "Stains"
|
||||
},
|
||||
"dirty_degree": {
|
||||
"name": "Dirty degree"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "Моющее средство"
|
||||
},
|
||||
"intensity": {
|
||||
"name": "Интенсивность"
|
||||
},
|
||||
"dryness_level": {
|
||||
"name": "Dryness Level"
|
||||
},
|
||||
"dry_temperature": {
|
||||
"name": "Dry Temperature"
|
||||
},
|
||||
"door_warn": {
|
||||
"name": "Door Warn"
|
||||
},
|
||||
"ai_switch": {
|
||||
"name": "AI Switch"
|
||||
},
|
||||
"material": {
|
||||
"name": "Материал"
|
||||
},
|
||||
"water_box": {
|
||||
"name": "Water Box"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "Энергопотребление"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Код ошибки"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "Fan level"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "Состояние фильтра"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "Filter1 Available Days"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "Filter1 Life Level"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "Filter2 Available Days"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "Filter2 Life Level"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "Filter3 Available Days"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "Filter3 Life Level"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "Flex Zone Actual Temperature"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "Flex Zone Setting Temperature"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "Freezer Actual Temperature"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "Freezer Setting Temperature"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "Формальдегид"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "Heating Leaving Water Temperature"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Мощность нагрева"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "Heating Time Remaining"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "In TDS"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "Indoor Humidity"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "Indoor Temperature"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "Keep Warm Remaining"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "Keep Warm Time"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "Middle Compartment Remaining"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "Middle Compartment Status"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "Middle Compartment Temperature"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Режим"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "Out TDS"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "Outdoor Temperature"
|
||||
},
|
||||
"program": {
|
||||
"name": "Программа"
|
||||
},
|
||||
"progress": {
|
||||
"name": "Этап"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "Энергопотребление"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "Refrigerator Actual Temperature"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "Refrigerator Setting Temperature"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "Right Flex Zone Actual Temperature"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "Right Flex Zone Setting Temperature"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "Rinse count"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "Уровень ополаскивателя"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "Температура сиденья"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "Время замачивания"
|
||||
},
|
||||
"softener": {
|
||||
"name": "Умягчитель"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "Уровень умягчителя"
|
||||
},
|
||||
"status": {
|
||||
"name": "Статус"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "Storage Remaining"
|
||||
},
|
||||
"tank": {
|
||||
"name": "Tank"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "Tank Actual Temperature"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "Целевая температура"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "Время цикла"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "Top Compartment Remaining"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "Top Compartment Status"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "Top Compartment Temperature"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "Top Temperature"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "Общее энергопотребление"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "Total produced energy"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "TVOC"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "Wash strength"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "Время мойки"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "Water Consumption"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "Температура воды"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "Уровень воды"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "Время работы"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "Anion"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "Aux Heating"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "Boost Mode"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "Breezeless"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "Comfort Mode"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "DHW Power"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "Дезинфекция"
|
||||
},
|
||||
"dry": {
|
||||
"name": "Dry"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "Эко-режим"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "Fast DHW"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "Foam Shield"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "Защита от замерзания"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Нагреватель"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "Indirect Wind"
|
||||
},
|
||||
"light": {
|
||||
"name": "Свет"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "Link to AC"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "Main Light"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "Main Power"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "Natural Wind"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "Night Light"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "Режим поворота"
|
||||
},
|
||||
"power": {
|
||||
"name": "Питание"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "Powerful Purification"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "Prompt Tone"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "Screen Display Alternate"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "Sensor Light"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "Silent Mode"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "Sleep Mode"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "Smart Eye"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "Smart Volume"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "Smelly Sensor"
|
||||
},
|
||||
"standby": {
|
||||
"name": "Ожидание"
|
||||
},
|
||||
"start": {
|
||||
"name": "Старт"
|
||||
},
|
||||
"storage": {
|
||||
"name": "Storage"
|
||||
},
|
||||
"swing": {
|
||||
"name": "Swing"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "Swing Horizontal"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "Swing Vertical"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "Variable Heating"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "Вентиляция"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "Whole Tank Heating"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "Zero Cold Water (Pulse)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "Zero Cold Water"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "Zone1 Curve"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "Zone1 Power"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "Zone2 Curve"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "Zone2 Power"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "Domestic hot water"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "Bathing"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "IP-адрес",
|
||||
"refresh_interval": "Интервал обновления (0 не выполняет активное обновление)",
|
||||
"sensors": "Дополнительные сенсоры",
|
||||
"switches": "Дополнительные элементы управления",
|
||||
"customize": "Настроить"
|
||||
},
|
||||
"title": "Конфигурация"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "The account does not supports this operation.\nClick \"ADD DEVICE\" to add a new device."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "Установить атрибут",
|
||||
"description": "Установить значение атрибута устройства",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Идентификатор устройства",
|
||||
"description": "Код (Идентификатор) устройства"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "Атрибут",
|
||||
"description": "Название атрибута для установки"
|
||||
},
|
||||
"value": {
|
||||
"name": "Значение",
|
||||
"description": "Значение атрибута для установки"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "Пользовательская команда",
|
||||
"description": "Отправить пользовательскую команду на устройство",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Идентификатор устройства",
|
||||
"description": "Код (Идентификатор) устройства"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "Тип команды",
|
||||
"description": "Тип команды, может быть 3 (запрос) или 2 (установка значения)"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "Тело команды",
|
||||
"description": "Тело команды (без заголовков протокола MSmart и контрольной суммы в конце)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,715 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "Failed to login with preset account, please report this issue",
|
||||
"login_failed": "Failed to login, account or password was wrong",
|
||||
"no_devices": "V sieti sa nenašli žiadne nové dostupné zariadenia",
|
||||
"device_exist": "Spotrebič je už nakonfigurovaný",
|
||||
"config_incorrect": "Konfigurácia je nesprávna",
|
||||
"connect_error": "Nedá sa pripojiť k spotrebiču",
|
||||
"invalid_token": "Token alebo Key v nesprávnom formáte"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "Pridávanie spotrebičov"
|
||||
},
|
||||
"description": "Vyberte spôsob pridávania zariadení",
|
||||
"title": "Pridať nový spotrebič"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "Account",
|
||||
"password": "Password"
|
||||
},
|
||||
"description": "Login and storage your Midea account only for getting the appliance info.\nYou can remove this configuration after all appliance configured.",
|
||||
"title": "Login"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "Zadajte IP adresu pre zariadenie, zadajte \"auto\" pre automatické vyhľadávanie.\nNa vyhľadávanie v rámci určitej siete môžete použiť aj IP adresu, napríklad \"192.168.1.255\".",
|
||||
"title": "Hľadať",
|
||||
"data": {
|
||||
"ip_address": "IP adresa"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "Spotrebiče"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "Spotrebiče"
|
||||
},
|
||||
"description": "Vyberte zariadenie, ktoré chcete pridať",
|
||||
"title": "Našiel sa nový spotrebič"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "Názov (napr. AC obývačka)",
|
||||
"device_id": "Kód spotrebiča",
|
||||
"type": "Typ",
|
||||
"ip_address": "IP adresa",
|
||||
"port": "Port",
|
||||
"model": "Model",
|
||||
"subtype": "Podtyp",
|
||||
"protocol": "Protokol",
|
||||
"token": "Token",
|
||||
"key": "Key"
|
||||
},
|
||||
"description": "Konfigurácia spotrebiča",
|
||||
"title": "Nový spotrebič"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "Bar Door"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "Bar Door Overtime"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "Bathing Working Status"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "Bottom Compartment Cooling"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "Bottom Compartment Door"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "Bottom Compartment Preheating"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "Burning State"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "Cleaning Reminder"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "Compressor Status"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "Cooking"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "Filter Change Reminder"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "Filter Cleaning Reminder"
|
||||
},
|
||||
"finished": {
|
||||
"name": "Finished"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "Flex Door"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "Flex Zone Door"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "Freezer Door"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "Freezer Door Overtime"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "Full of Dust"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "Heating Working Status"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "Keep Warm"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "Lid Status"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "Middle Compartment Cooling"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "Middle Compartment Door"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "Middle Compartment Preheating"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "Oil-cup Full"
|
||||
},
|
||||
"protection": {
|
||||
"name": "Protection"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "Refrigerator Door"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "Refrigerator Door Overtime"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "Rinse Aid Shortage"
|
||||
},
|
||||
"salt": {
|
||||
"name": "Salt Shortage"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "Seat Status"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "DHW status"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "Heating status"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "IBH status"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "TBH status"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "Tank Ejected"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "Tank status"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "Top Compartment Cooling"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "Top Compartment Door"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "Top Compartment Preheating"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "Water Change Reminder"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "Water Shortage"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "With Pressure"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "Zone1 Room-temperature Mode"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "Zone1 Water-temperature Mode"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "Zone2 Room-temperature Mode"
|
||||
},
|
||||
"zone2_water_temp_mode": {
|
||||
"name": "Zone2 Water-temperature Mode"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "Zone1 Thermostat"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "Zone2 Thermostat"
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "Fresh Air"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "Child Lock"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "Dry Level"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "Heating Level"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "Seat Temperature Level"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "Water Temperature Level"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "Detect Mode"
|
||||
},
|
||||
"direction": {
|
||||
"name": "Direction"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "Fan Speed"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "Oscillation Angle"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "Oscillation Mode"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "Silent Level"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "Tilting Angle"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "Water Level Setting"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "Bathing Leaving Water Temperature"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "Bottom Compartment Remaining"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "Bottom Compartment Status"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "Bottom Compartment Temperature"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "Bottom Temperature"
|
||||
},
|
||||
"bright": {
|
||||
"name": "Bright Level"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "Compressor Temperature"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "Condenser Temperature"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "Current Energy Consumption"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "Current Temperature"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "dehydration speed"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "dehydration time"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "detergent"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "Energy Consumption"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Error Code"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "Fan level"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "Filter Life"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "Filter1 Available Days"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "Filter1 Life Level"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "Filter2 Available Days"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "Filter2 Life Level"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "Filter3 Available Days"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "Filter3 Life Level"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "Flex Zone Actual Temperature"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "Flex Zone Setting Temperature"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "Freezer Actual Temperature"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "Freezer Setting Temperature"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "Methanal"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "Heating Leaving Water Temperature"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "Heating Time Remaining"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "In TDS"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "Indoor Humidity"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "Indoor Temperature"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "Keep Warm Remaining"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "Keep Warm Time"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "Middle Compartment Remaining"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "Middle Compartment Status"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "Middle Compartment Temperature"
|
||||
},
|
||||
"mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "Out TDS"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "Outdoor Temperature"
|
||||
},
|
||||
"program": {
|
||||
"name": "Program"
|
||||
},
|
||||
"progress": {
|
||||
"name": "Progress"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "Realtime Power"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "Refrigerator Actual Temperature"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "Refrigerator Setting Temperature"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "Right Flex Zone Actual Temperature"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "Right Flex Zone Setting Temperature"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "rinse level"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "Seat Temperature"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "soak time"
|
||||
},
|
||||
"softener": {
|
||||
"name": "softener"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "Softwater Level"
|
||||
},
|
||||
"status": {
|
||||
"name": "Status"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "Storage Remaining"
|
||||
},
|
||||
"tank": {
|
||||
"name": "Tank"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "Tank Actual Temperature"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "Target Temperature"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "Time Remaining"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "Top Compartment Remaining"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "Top Compartment Status"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "Top Compartment Temperature"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "Top Temperature"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "Total Energy Consumption"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "Total produced energy"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "TVOC"
|
||||
},
|
||||
"wash_level": {
|
||||
"name": "rinse count"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "wash strength"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "wash time"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "Water Consumption"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "Water Temperature"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "Water Level"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "Working Time"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "Anion"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "Aux Heating"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "Boost Mode"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "Breezeless"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "Comfort Mode"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "DHW Power"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "Disinfect"
|
||||
},
|
||||
"dry": {
|
||||
"name": "Dry"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "ECO Mode"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "Fast DHW"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "Foam Shield"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "Frost Protect"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "Heating Power"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "Indirect Wind"
|
||||
},
|
||||
"light": {
|
||||
"name": "Light"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "Link to AC"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "Main Light"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "Main Power"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "Natural Wind"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "Night Light"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "Oscillate"
|
||||
},
|
||||
"power": {
|
||||
"name": "Power"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "Powerful Purification"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "Prompt Tone"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "Screen Display"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "Screen Display Alternate"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "Sensor Light"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "Silent Mode"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "Sleep Mode"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "Smart Eye"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "Smart Volume"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "Smelly Sensor"
|
||||
},
|
||||
"standby": {
|
||||
"name": "Standby"
|
||||
},
|
||||
"start": {
|
||||
"name": "Start"
|
||||
},
|
||||
"storage": {
|
||||
"name": "Storage"
|
||||
},
|
||||
"swing": {
|
||||
"name": "swing"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "Swing Horizontal"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "Swing Vertical"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "Variable Heating"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "Ventilation"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "Whole Tank Heating"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "Zero Cold Water (Pulse)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "Zero Cold Water"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "Zone1 Curve"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "Zone1 Power"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "Zone2 Curve"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "Zone2 Power"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "Domestic hot water"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "Bathing"
|
||||
},
|
||||
"heating": {
|
||||
"name": "Heating"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "IP adresa",
|
||||
"refresh_interval": "Refresh interval (0 means not refreshing actively)",
|
||||
"sensors": "Extra Snímače",
|
||||
"switches": "Extra Ovládacie prvky",
|
||||
"customize": "Voliteľné"
|
||||
},
|
||||
"title": "Konfigurovať"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "The account does not supports this operation.\nClick \"ADD DEVICE\" to add a new device."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "Nastaviť atribút",
|
||||
"description": "Nastavte hodnotu atribútu zariadenia",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Kód spotrebiča",
|
||||
"description": "Kód spotrebiča (ID zariadenia) spotrebiča"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "Atribút",
|
||||
"description": "Názov atribútu, ktorý chcete nastaviť"
|
||||
},
|
||||
"value": {
|
||||
"name": "Hodnota",
|
||||
"description": "Hodnota atribútu, ktorú chcete nastaviť"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "Prispôsobiť príkaz",
|
||||
"description": "Pošlite do zariadenia príkaz na prispôsobenie",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "Kód spotrebiča",
|
||||
"description": "Kód spotrebiča (ID zariadenia) spotrebiča"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "typ príkazu",
|
||||
"description": "Typ príkazu by mal byť 3 (dopyt) alebo 2 (nastaviť)"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "obsah príkazu",
|
||||
"description": "Obsah príkazu, (nezahŕňa hlavičku protokolu MSmart a kontrolný súčet na konci)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,802 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"preset_account": "预置账户登录失败,请报告此问题",
|
||||
"login_failed": "登录失败, 用户名或密码错",
|
||||
"no_devices": "未在网络上发现可用新设备",
|
||||
"device_exist": "设备已经存在, 请添加其它设备",
|
||||
"config_incorrect": "配置信息不正确, 请检查后重新输入",
|
||||
"connect_error": "无法连接到指定设备",
|
||||
"invalid_token": "Token或Key格式不正确"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"way": "添加方式"
|
||||
},
|
||||
"description": "选择添加设备的方式",
|
||||
"title": "添加新设备"
|
||||
},
|
||||
"login": {
|
||||
"data": {
|
||||
"account": "账号",
|
||||
"password": "密码"
|
||||
},
|
||||
"description": "登录并保存你的美的账户,仅用于获取添加设备时设备信息\n添加设备完成后,你可以删除该配置",
|
||||
"title": "登录"
|
||||
},
|
||||
"discovery": {
|
||||
"description": "输入设备的IP地址, 输入\"auto\"自动搜索设备\n你也可以使用IP地址在指定网络中搜索, 比如`192.168.1.255`",
|
||||
"title": "搜索",
|
||||
"data": {
|
||||
"ip_address": "IP地址"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"description": "{table}",
|
||||
"title": "设备"
|
||||
},
|
||||
"auto": {
|
||||
"data": {
|
||||
"device": "设备"
|
||||
},
|
||||
"description": "选择设备并添加",
|
||||
"title": "发现新设备"
|
||||
},
|
||||
"manually": {
|
||||
"data": {
|
||||
"name": "名称(如客厅空调)",
|
||||
"device_id": "设备编号",
|
||||
"type": "设备类型",
|
||||
"ip_address": "IP地址",
|
||||
"port": "端口",
|
||||
"model": "型号",
|
||||
"subtype": "子型号",
|
||||
"protocol": "协议版本",
|
||||
"token": "Token",
|
||||
"key": "Key"
|
||||
},
|
||||
"description": "配置设备参数",
|
||||
"title": "新设备"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"bar_door": {
|
||||
"name": "吧台门状态"
|
||||
},
|
||||
"bar_door_overtime": {
|
||||
"name": "吧台门超时"
|
||||
},
|
||||
"bathing_working": {
|
||||
"name": "淋浴工作状态"
|
||||
},
|
||||
"bottom_compartment_cooling": {
|
||||
"name": "下层冷却"
|
||||
},
|
||||
"bottom_compartment_door": {
|
||||
"name": "下层门状态"
|
||||
},
|
||||
"bottom_compartment_preheating": {
|
||||
"name": "下层预热"
|
||||
},
|
||||
"burning_state": {
|
||||
"name": "燃烧状态"
|
||||
},
|
||||
"cleaning_reminder": {
|
||||
"name": "清洁提示"
|
||||
},
|
||||
"compressor_status": {
|
||||
"name": "压缩机状态"
|
||||
},
|
||||
"cooking": {
|
||||
"name": "烹饪中"
|
||||
},
|
||||
"filter_change_reminder": {
|
||||
"name": "滤芯更换提醒"
|
||||
},
|
||||
"filter_cleaning_reminder": {
|
||||
"name": "滤芯清洁提醒"
|
||||
},
|
||||
"finished": {
|
||||
"name": "完成"
|
||||
},
|
||||
"flex_zone_door": {
|
||||
"name": "变温区门状态"
|
||||
},
|
||||
"flex_zone_door_overtime": {
|
||||
"name": "变温区门超时"
|
||||
},
|
||||
"freezer_door": {
|
||||
"name": "冷冻室门状态"
|
||||
},
|
||||
"freezer_door_overtime": {
|
||||
"name": "冷冻室门超时"
|
||||
},
|
||||
"full_dust": {
|
||||
"name": "尘满"
|
||||
},
|
||||
"heating": {
|
||||
"name": "加热"
|
||||
},
|
||||
"heating_working": {
|
||||
"name": "取暖工作状态"
|
||||
},
|
||||
"keep_warm": {
|
||||
"name": "保温"
|
||||
},
|
||||
"lid_status": {
|
||||
"name": "盖子状态"
|
||||
},
|
||||
"middle_compartment_cooling": {
|
||||
"name": "中层冷却"
|
||||
},
|
||||
"middle_compartment_door": {
|
||||
"name": "中层门状态"
|
||||
},
|
||||
"middle_compartment_preheating": {
|
||||
"name": "中层预热"
|
||||
},
|
||||
"oilcup_full": {
|
||||
"name": "油杯满提示"
|
||||
},
|
||||
"protection": {
|
||||
"name": "安全防护"
|
||||
},
|
||||
"refrigerator_door": {
|
||||
"name": "冷藏室门状态"
|
||||
},
|
||||
"refrigerator_door_overtime": {
|
||||
"name": "冷藏室门超时"
|
||||
},
|
||||
"rinse_aid": {
|
||||
"name": "漂洗剂不足"
|
||||
},
|
||||
"salt": {
|
||||
"name": "软水盐不足"
|
||||
},
|
||||
"seat_status": {
|
||||
"name": "入座状态"
|
||||
},
|
||||
"status_dhw": {
|
||||
"name": "DHW状态"
|
||||
},
|
||||
"status_heating": {
|
||||
"name": "加热状态"
|
||||
},
|
||||
"status_ibh": {
|
||||
"name": "IBH状态"
|
||||
},
|
||||
"status_tbh": {
|
||||
"name": "TBH状态"
|
||||
},
|
||||
"tank_ejected": {
|
||||
"name": "水箱弹出"
|
||||
},
|
||||
"tank_full": {
|
||||
"name": "水箱状态"
|
||||
},
|
||||
"top_compartment_cooling": {
|
||||
"name": "上层冷却"
|
||||
},
|
||||
"top_compartment_door": {
|
||||
"name": "上层门状态"
|
||||
},
|
||||
"top_compartment_preheating": {
|
||||
"name": "上层预热"
|
||||
},
|
||||
"water_change_reminder": {
|
||||
"name": "换水提醒"
|
||||
},
|
||||
"water_shortage": {
|
||||
"name": "缺水"
|
||||
},
|
||||
"with_pressure": {
|
||||
"name": "带压中"
|
||||
},
|
||||
"zone1_room_temp_mode": {
|
||||
"name": "区域1室温模式"
|
||||
},
|
||||
"zone1_water_temp_mode": {
|
||||
"name": "区域1水温模式"
|
||||
},
|
||||
"zone2_room_temp_mode": {
|
||||
"name": "区域2室温模式"
|
||||
},
|
||||
"zone2_water_temp_mode": {
|
||||
"name": "区域2水温模式"
|
||||
},
|
||||
"microcrystal_fresh": {
|
||||
"name": "微晶一周鲜"
|
||||
},
|
||||
"electronic_smell": {
|
||||
"name": "净味杀菌"
|
||||
}
|
||||
},
|
||||
"climate": {
|
||||
"climate_zone1": {
|
||||
"name": "区域1恒温器"
|
||||
},
|
||||
"climate_zone2": {
|
||||
"name": "区域2恒温器"
|
||||
},
|
||||
"climate_key": {
|
||||
"state_attributes": {
|
||||
"fan_mode": {
|
||||
"state": {
|
||||
"silent": "静音",
|
||||
"full": "全速"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fan": {
|
||||
"fresh_air": {
|
||||
"name": "新风"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
"child_lock": {
|
||||
"name": "童锁"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"dry_level": {
|
||||
"name": "烘干档位"
|
||||
},
|
||||
"heating_level": {
|
||||
"name": "加热档位"
|
||||
},
|
||||
"seat_temp_level": {
|
||||
"name": "座温档位"
|
||||
},
|
||||
"water_temp_level": {
|
||||
"name": "水温档位"
|
||||
},
|
||||
"fan_speed_percent": {
|
||||
"name": "风速百分比"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"detect_mode": {
|
||||
"name": "检测模式"
|
||||
},
|
||||
"direction": {
|
||||
"name": "摇摆方向"
|
||||
},
|
||||
"fan_speed": {
|
||||
"name": "风速设定"
|
||||
},
|
||||
"mode": {
|
||||
"name": "模式"
|
||||
},
|
||||
"oscillation_angle": {
|
||||
"name": "水平摆头角度"
|
||||
},
|
||||
"oscillation_mode": {
|
||||
"name": "水平摆头模式"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "屏幕显示"
|
||||
},
|
||||
"silent_level": {
|
||||
"name": "静音级别"
|
||||
},
|
||||
"tilting_angle": {
|
||||
"name": "垂直摆头角度"
|
||||
},
|
||||
"water_level_set": {
|
||||
"name": "水位设定"
|
||||
},
|
||||
"wind_lr_angle": {
|
||||
"name": "水平出风",
|
||||
"state": {
|
||||
"off": "停止",
|
||||
"left": "左方",
|
||||
"left-mid": "左中",
|
||||
"middle": "中部",
|
||||
"right-mid": "右中",
|
||||
"right": "右方"
|
||||
}
|
||||
},
|
||||
"wind_ud_angle": {
|
||||
"name": "垂直出风",
|
||||
"state": {
|
||||
"off": "停止",
|
||||
"up": "上方",
|
||||
"up-mid": "中上",
|
||||
"middle": "中部",
|
||||
"down-mid": "中下",
|
||||
"down": "下方"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"bathing_leaving_temperature": {
|
||||
"name": "淋浴出水温度"
|
||||
},
|
||||
"bottom_compartment_remaining": {
|
||||
"name": "下层剩余时间"
|
||||
},
|
||||
"bottom_compartment_status": {
|
||||
"name": "下层状态"
|
||||
},
|
||||
"bottom_compartment_temperature": {
|
||||
"name": "下层温度"
|
||||
},
|
||||
"bottom_temperature": {
|
||||
"name": "底部温度"
|
||||
},
|
||||
"bright": {
|
||||
"name": "亮碟剂档位"
|
||||
},
|
||||
"compressor_temperature": {
|
||||
"name": "压缩机温度"
|
||||
},
|
||||
"condenser_temperature": {
|
||||
"name": "冷凝器温度"
|
||||
},
|
||||
"current_energy_consumption": {
|
||||
"name": "当前能耗"
|
||||
},
|
||||
"current_temperature": {
|
||||
"name": "当前温度"
|
||||
},
|
||||
"dehydration_speed": {
|
||||
"name": "脱水速度"
|
||||
},
|
||||
"dehydration_time": {
|
||||
"name": "脱水时间档位"
|
||||
},
|
||||
"dehydration_time_value": {
|
||||
"name": "脱水时间值"
|
||||
},
|
||||
"wash_time_value": {
|
||||
"name": "洗涤时间值"
|
||||
},
|
||||
"stains": {
|
||||
"name": "污渍"
|
||||
},
|
||||
"dirty_degree": {
|
||||
"name": "脏度"
|
||||
},
|
||||
"intensity": {
|
||||
"name": "强度"
|
||||
},
|
||||
"dryness_level": {
|
||||
"name": "干燥档位"
|
||||
},
|
||||
"dry_temperature": {
|
||||
"name": "干燥温度"
|
||||
},
|
||||
"door_warn": {
|
||||
"name": "开门警告"
|
||||
},
|
||||
"ai_switch": {
|
||||
"name": "AI开关"
|
||||
},
|
||||
"material": {
|
||||
"name": "材质"
|
||||
},
|
||||
"water_box": {
|
||||
"name": "水箱"
|
||||
},
|
||||
"energy_consumption": {
|
||||
"name": "能耗"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "错误码"
|
||||
},
|
||||
"fan_level": {
|
||||
"name": "当前风扇档位"
|
||||
},
|
||||
"filter_life": {
|
||||
"name": "滤芯寿命"
|
||||
},
|
||||
"filter1_days": {
|
||||
"name": "滤芯1可用天数"
|
||||
},
|
||||
"filter1_life": {
|
||||
"name": "滤芯1剩余寿命"
|
||||
},
|
||||
"filter2_days": {
|
||||
"name": "滤芯2可用天数"
|
||||
},
|
||||
"filter2_life": {
|
||||
"name": "滤芯2剩余寿命"
|
||||
},
|
||||
"filter3_days": {
|
||||
"name": "滤芯3可用天数"
|
||||
},
|
||||
"filter3_life": {
|
||||
"name": "滤芯3剩余寿命"
|
||||
},
|
||||
"flex_zone_actual_temp": {
|
||||
"name": "变温区实际温度"
|
||||
},
|
||||
"flex_zone_setting_temp": {
|
||||
"name": "变温区设置温度"
|
||||
},
|
||||
"freezer_actual_temp": {
|
||||
"name": "冷冻室实际温度"
|
||||
},
|
||||
"freezer_setting_temp": {
|
||||
"name": "冷冻室设置温度"
|
||||
},
|
||||
"hcho": {
|
||||
"name": "甲醛"
|
||||
},
|
||||
"heating_leaving_temperature": {
|
||||
"name": "取暖出水温度"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "加热功率"
|
||||
},
|
||||
"heating_time_remaining": {
|
||||
"name": "加热剩余时间"
|
||||
},
|
||||
"in_tds": {
|
||||
"name": "进水TDS"
|
||||
},
|
||||
"indoor_humidity": {
|
||||
"name": "室内湿度"
|
||||
},
|
||||
"indoor_temperature": {
|
||||
"name": "室内温度"
|
||||
},
|
||||
"keep_warm_remaining": {
|
||||
"name": "保温剩余时间"
|
||||
},
|
||||
"keep_warm_time": {
|
||||
"name": "保温时间"
|
||||
},
|
||||
"middle_compartment_remaining": {
|
||||
"name": "中层剩余时间"
|
||||
},
|
||||
"middle_compartment_status": {
|
||||
"name": "中层状态"
|
||||
},
|
||||
"middle_compartment_temperature": {
|
||||
"name": "中层温度"
|
||||
},
|
||||
"mode": {
|
||||
"name": "模式"
|
||||
},
|
||||
"out_tds": {
|
||||
"name": "出水TDS"
|
||||
},
|
||||
"outdoor_temperature": {
|
||||
"name": "室外温度"
|
||||
},
|
||||
"program": {
|
||||
"name": "程序"
|
||||
},
|
||||
"progress": {
|
||||
"name": "当前程序"
|
||||
},
|
||||
"realtime_power": {
|
||||
"name": "实时功率"
|
||||
},
|
||||
"refrigerator_actual_temp": {
|
||||
"name": "冷藏室实际温度"
|
||||
},
|
||||
"refrigerator_setting_temp": {
|
||||
"name": "冷藏室设置温度"
|
||||
},
|
||||
"right_flex_zone_actual_temp": {
|
||||
"name": "右变温区实际温度"
|
||||
},
|
||||
"right_flex_zone_setting_temp": {
|
||||
"name": "右变温区设置温度"
|
||||
},
|
||||
"rinse_count": {
|
||||
"name": "漂洗次数"
|
||||
},
|
||||
"rinse_level": {
|
||||
"name": "漂洗档位"
|
||||
},
|
||||
"seat_temperature": {
|
||||
"name": "当前座温"
|
||||
},
|
||||
"soak_time": {
|
||||
"name": "浸泡时间"
|
||||
},
|
||||
"softener": {
|
||||
"name": "柔顺剂"
|
||||
},
|
||||
"softwater": {
|
||||
"name": "软水盐档位"
|
||||
},
|
||||
"status": {
|
||||
"name": "状态"
|
||||
},
|
||||
"storage_remaining": {
|
||||
"name": "保管剩余时间"
|
||||
},
|
||||
"tank": {
|
||||
"name": "水箱水位"
|
||||
},
|
||||
"tank_actual_temperature": {
|
||||
"name": "水箱实际温度"
|
||||
},
|
||||
"target_temperature": {
|
||||
"name": "设定温度"
|
||||
},
|
||||
"time_remaining": {
|
||||
"name": "剩余时间"
|
||||
},
|
||||
"top_compartment_remaining": {
|
||||
"name": "上层剩余时间"
|
||||
},
|
||||
"top_compartment_status": {
|
||||
"name": "上层状态"
|
||||
},
|
||||
"top_compartment_temperature": {
|
||||
"name": "上层温度"
|
||||
},
|
||||
"top_temperature": {
|
||||
"name": "顶部温度"
|
||||
},
|
||||
"total_energy_consumption": {
|
||||
"name": "总能耗"
|
||||
},
|
||||
"total_produced_energy": {
|
||||
"name": "总计产生能量"
|
||||
},
|
||||
"tvoc": {
|
||||
"name": "TVOC"
|
||||
},
|
||||
"wash_level": {
|
||||
"name": "洗涤档位"
|
||||
},
|
||||
"wash_strength": {
|
||||
"name": "洗涤强度"
|
||||
},
|
||||
"wash_time": {
|
||||
"name": "洗涤时间档位"
|
||||
},
|
||||
"detergent": {
|
||||
"name": "洗涤剂"
|
||||
},
|
||||
"water_consumption": {
|
||||
"name": "总耗水量"
|
||||
},
|
||||
"water_level": {
|
||||
"name": "水位"
|
||||
},
|
||||
"water_temperature": {
|
||||
"name": "水温"
|
||||
},
|
||||
"working_time": {
|
||||
"name": "工作时间"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "湿度"
|
||||
},
|
||||
"variable_mode": {
|
||||
"name": "变温区模式"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"anion": {
|
||||
"name": "负离子开关"
|
||||
},
|
||||
"aux_heating": {
|
||||
"name": "电辅热"
|
||||
},
|
||||
"boost_mode": {
|
||||
"name": "强劲模式"
|
||||
},
|
||||
"breezeless": {
|
||||
"name": "无风感"
|
||||
},
|
||||
"comfort_mode": {
|
||||
"name": "舒省模式"
|
||||
},
|
||||
"cold_water_single": {
|
||||
"name": "单次零冷水"
|
||||
},
|
||||
"cold_water_dot": {
|
||||
"name": "点动零冷水"
|
||||
},
|
||||
"dhw_power": {
|
||||
"name": "生活热水电源开关"
|
||||
},
|
||||
"disinfect": {
|
||||
"name": "消毒"
|
||||
},
|
||||
"dry": {
|
||||
"name": "干燥"
|
||||
},
|
||||
"eco_mode": {
|
||||
"name": "ECO模式"
|
||||
},
|
||||
"fast_dhw": {
|
||||
"name": "快速生活热水"
|
||||
},
|
||||
"foam_shield": {
|
||||
"name": "泡沫盾"
|
||||
},
|
||||
"frost_protect": {
|
||||
"name": "防霜冻"
|
||||
},
|
||||
"heating_power": {
|
||||
"name": "加热",
|
||||
"_comments": "E2 加热功率, E6 加热开关"
|
||||
},
|
||||
"indirect_wind": {
|
||||
"name": "防直吹"
|
||||
},
|
||||
"light": {
|
||||
"name": "灯光"
|
||||
},
|
||||
"link_to_ac": {
|
||||
"name": "空调联动开关"
|
||||
},
|
||||
"main_light": {
|
||||
"name": "主灯"
|
||||
},
|
||||
"main_power": {
|
||||
"name": "主电源"
|
||||
},
|
||||
"natural_wind": {
|
||||
"name": "自然风"
|
||||
},
|
||||
"night_light": {
|
||||
"name": "夜灯"
|
||||
},
|
||||
"oscillate": {
|
||||
"name": "摆头开关"
|
||||
},
|
||||
"power": {
|
||||
"name": "电源开关"
|
||||
},
|
||||
"powerful_purify": {
|
||||
"name": "强净开关"
|
||||
},
|
||||
"prompt_tone": {
|
||||
"name": "提示音"
|
||||
},
|
||||
"screen_display": {
|
||||
"name": "屏幕显示"
|
||||
},
|
||||
"screen_display_alternate": {
|
||||
"name": "屏幕显示备用开关"
|
||||
},
|
||||
"sensor_light": {
|
||||
"name": "感应夜灯"
|
||||
},
|
||||
"silent_mode": {
|
||||
"name": "静音模式"
|
||||
},
|
||||
"sleep_mode": {
|
||||
"name": "睡眠模式"
|
||||
},
|
||||
"smart_eye": {
|
||||
"name": "智慧眼"
|
||||
},
|
||||
"smart_volume": {
|
||||
"name": "智能变容"
|
||||
},
|
||||
"smelly_sensor": {
|
||||
"name": "异味感应"
|
||||
},
|
||||
"standby": {
|
||||
"name": "待机"
|
||||
},
|
||||
"start": {
|
||||
"name": "启动"
|
||||
},
|
||||
"storage": {
|
||||
"name": "保管开关"
|
||||
},
|
||||
"swing": {
|
||||
"name": "摆风开关"
|
||||
},
|
||||
"swing_horizontal": {
|
||||
"name": "水平摆风"
|
||||
},
|
||||
"swing_vertical": {
|
||||
"name": "垂直摆风"
|
||||
},
|
||||
"tbh": {
|
||||
"name": "TBH"
|
||||
},
|
||||
"variable_heating": {
|
||||
"name": "变频加热"
|
||||
},
|
||||
"ventilation": {
|
||||
"name": "换气"
|
||||
},
|
||||
"whole_tank_heating": {
|
||||
"name": "全胆速热"
|
||||
},
|
||||
"zero_cold_pulse": {
|
||||
"name": "零冷水(点动)"
|
||||
},
|
||||
"zero_cold_water": {
|
||||
"name": "零冷水"
|
||||
},
|
||||
"zone1_curve": {
|
||||
"name": "区域1曲线"
|
||||
},
|
||||
"zone1_power": {
|
||||
"name": "区域1恒温器开关"
|
||||
},
|
||||
"zone2_curve": {
|
||||
"name": "区域2曲线"
|
||||
},
|
||||
"zone2_power": {
|
||||
"name": "区域2恒温器开关"
|
||||
}
|
||||
},
|
||||
"water_heater": {
|
||||
"domestic_hot_water": {
|
||||
"name": "生活热水"
|
||||
},
|
||||
"bathing": {
|
||||
"name": "淋浴"
|
||||
},
|
||||
"heating": {
|
||||
"name": "加热"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"ip_address": "IP地址",
|
||||
"refresh_interval": "刷新间隔(设0为不进行主动刷新)",
|
||||
"sensors": "扩展传感器",
|
||||
"switches": "扩展控制",
|
||||
"customize": "自定义"
|
||||
},
|
||||
"title": "配置"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"account_option": "账户配置不支持此操作.\n点击\"添加设备\"完成添加新设备的操作"
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"set_attribute": {
|
||||
"name": "设置属性",
|
||||
"description": "设置设备的属性值",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "设备编码",
|
||||
"description": "设备编码(Device ID)"
|
||||
},
|
||||
"attribute": {
|
||||
"name": "属性",
|
||||
"description": "要设置的属性名称"
|
||||
},
|
||||
"value": {
|
||||
"name": "值",
|
||||
"description": "要设置的属性值"
|
||||
}
|
||||
}
|
||||
},
|
||||
"send_command": {
|
||||
"name": "自定义命令",
|
||||
"description": "向设备发送一个自定义命令",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "设备编码",
|
||||
"description": "设备编码(Device ID)"
|
||||
},
|
||||
"cmd_type": {
|
||||
"name": "命令类型",
|
||||
"description": "命令类型,可以为2(查询)或3(设置)"
|
||||
},
|
||||
"cmd_body": {
|
||||
"name": "命令体",
|
||||
"description": "命令的消息体(不包括前部的MSmart协议头及后部的校验码)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,455 @@
|
||||
"""Midea Water Heater entries."""
|
||||
|
||||
import functools as ft
|
||||
import logging
|
||||
from typing import Any, ClassVar, TypeAlias, cast
|
||||
|
||||
from homeassistant.components.water_heater import (
|
||||
WaterHeaterEntity,
|
||||
WaterHeaterEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_TEMPERATURE,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_SWITCHES,
|
||||
PRECISION_HALVES,
|
||||
PRECISION_WHOLE,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
Platform,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealocal.device import DeviceType
|
||||
from midealocal.devices.c3 import DeviceAttributes as C3Attributes
|
||||
from midealocal.devices.c3 import MideaC3Device
|
||||
from midealocal.devices.cd import DeviceAttributes as CDAttributes
|
||||
from midealocal.devices.cd import MideaCDDevice
|
||||
from midealocal.devices.e2 import DeviceAttributes as E2Attributes
|
||||
from midealocal.devices.e2 import MideaE2Device
|
||||
from midealocal.devices.e3 import MideaE3Device
|
||||
from midealocal.devices.e6 import DeviceAttributes as E6Attributes
|
||||
from midealocal.devices.e6 import MideaE6Device
|
||||
|
||||
from .const import DEVICES, DOMAIN
|
||||
from .midea_devices import MIDEA_DEVICES
|
||||
from .midea_entity import MideaEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
E2_TEMPERATURE_MAX = 75
|
||||
E2_TEMPERATURE_MIN = 30
|
||||
E3_TEMPERATURE_MAX = 65
|
||||
E3_TEMPERATURE_MIN = 35
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up water heater entries."""
|
||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||
device = hass.data[DOMAIN][DEVICES].get(device_id)
|
||||
extra_switches = config_entry.options.get(CONF_SWITCHES, [])
|
||||
devs: list[
|
||||
MideaE2WaterHeater
|
||||
| MideaE3WaterHeater
|
||||
| MideaE6WaterHeater
|
||||
| MideaC3WaterHeater
|
||||
| MideaCDWaterHeater
|
||||
] = []
|
||||
for entity_key, config in cast(
|
||||
"dict",
|
||||
MIDEA_DEVICES[device.device_type]["entities"],
|
||||
).items():
|
||||
if config["type"] == Platform.WATER_HEATER and (
|
||||
config.get("default") or entity_key in extra_switches
|
||||
):
|
||||
if device.device_type == DeviceType.E2:
|
||||
devs.append(MideaE2WaterHeater(device, entity_key))
|
||||
elif device.device_type == DeviceType.E3:
|
||||
devs.append(MideaE3WaterHeater(device, entity_key))
|
||||
elif device.device_type == DeviceType.E6:
|
||||
devs.append(MideaE6WaterHeater(device, entity_key, config["use"]))
|
||||
elif device.device_type == DeviceType.C3:
|
||||
devs.append(MideaC3WaterHeater(device, entity_key))
|
||||
elif device.device_type == DeviceType.CD:
|
||||
devs.append(MideaCDWaterHeater(device, entity_key))
|
||||
async_add_entities(devs)
|
||||
|
||||
|
||||
MideaWaterHeaterDevice: TypeAlias = (
|
||||
MideaE2Device | MideaE3Device | MideaC3Device | MideaE6Device | MideaCDDevice
|
||||
)
|
||||
|
||||
|
||||
class MideaWaterHeater(MideaEntity, WaterHeaterEntity):
|
||||
"""Midea Water Heater Entries Base Class."""
|
||||
|
||||
_device: MideaWaterHeaterDevice
|
||||
|
||||
def __init__(self, device: MideaWaterHeaterDevice, entity_key: str) -> None:
|
||||
"""Midea Water Heater entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._operations: list[str] = []
|
||||
|
||||
@property
|
||||
def supported_features(self) -> WaterHeaterEntityFeature:
|
||||
"""Midea Water Heater supported features."""
|
||||
return WaterHeaterEntityFeature.TARGET_TEMPERATURE
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Midea Water Heater extra state attributes."""
|
||||
attrs: dict[str, Any] = self._device.attributes
|
||||
if hasattr(self._device, "temperature_step"):
|
||||
attrs["target_temperature_step"] = self._device.temperature_step
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea Water Heater min temperature."""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea Water Heater max temperature."""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def precision(self) -> float:
|
||||
"""Midea Water Heater precision."""
|
||||
return float(PRECISION_WHOLE)
|
||||
|
||||
@property
|
||||
def temperature_unit(self) -> UnitOfTemperature:
|
||||
"""Midea Water Heater temperature unix."""
|
||||
return UnitOfTemperature.CELSIUS
|
||||
|
||||
@property
|
||||
def current_operation(self) -> str | None:
|
||||
"""Midea Water Heater current operation."""
|
||||
return cast(
|
||||
"str",
|
||||
(
|
||||
self._device.get_attribute("mode")
|
||||
if self._device.get_attribute("power")
|
||||
else STATE_OFF
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float:
|
||||
"""Midea Water Heater current temperature."""
|
||||
return cast("float", self._device.get_attribute("current_temperature"))
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float:
|
||||
"""Midea Water Heater target temperature."""
|
||||
return cast("float", self._device.get_attribute("target_temperature"))
|
||||
|
||||
def set_temperature(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea Water Heater set temperature."""
|
||||
if ATTR_TEMPERATURE not in kwargs:
|
||||
return
|
||||
# input target_temperature should be float
|
||||
temperature = float(kwargs[ATTR_TEMPERATURE])
|
||||
self._device.set_attribute("target_temperature", temperature)
|
||||
|
||||
def set_operation_mode(self, operation_mode: str) -> None:
|
||||
"""Midea Water Heater set operation mode."""
|
||||
self._device.set_attribute(attr="mode", value=operation_mode)
|
||||
|
||||
@property
|
||||
def operation_list(self) -> list[str] | None:
|
||||
"""Midea Water Heater operation list."""
|
||||
if not hasattr(self._device, "preset_modes"):
|
||||
return None
|
||||
return cast("list", self._device.preset_modes)
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Water Heater turn on."""
|
||||
self._device.set_attribute(attr="power", value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Water Heater turn off."""
|
||||
self._device.set_attribute(attr="power", value=False)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea Water Heater async turn on."""
|
||||
await self.hass.async_add_executor_job(ft.partial(self.turn_on, **kwargs))
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea Water Heater async off."""
|
||||
await self.hass.async_add_executor_job(ft.partial(self.turn_off, **kwargs))
|
||||
|
||||
def update_state(self, status: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea Water Heater update state."""
|
||||
if not self.hass:
|
||||
_LOGGER.warning(
|
||||
"Water update_state skipped for %s [%s]: HASS is None",
|
||||
self.name,
|
||||
type(self),
|
||||
)
|
||||
return
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
|
||||
class MideaE2WaterHeater(MideaWaterHeater):
|
||||
"""Midea E2 Water Heater Entries."""
|
||||
|
||||
_device: MideaE2Device
|
||||
|
||||
def __init__(self, device: MideaE2Device, entity_key: str) -> None:
|
||||
"""Midea E2 Water Heater entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
|
||||
@property
|
||||
def current_operation(self) -> str:
|
||||
"""Midea E2 Water Heater current operation."""
|
||||
return str(
|
||||
STATE_ON if self._device.get_attribute(E2Attributes.power) else STATE_OFF,
|
||||
)
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea E2 Water Heater min temperature."""
|
||||
return E2_TEMPERATURE_MIN
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea E2 Water Heater max temperature."""
|
||||
return E2_TEMPERATURE_MAX
|
||||
|
||||
@property
|
||||
def supported_features(self) -> WaterHeaterEntityFeature:
|
||||
"""Midea E2 Water Heater supported features."""
|
||||
return (
|
||||
WaterHeaterEntityFeature.TARGET_TEMPERATURE
|
||||
| WaterHeaterEntityFeature.ON_OFF
|
||||
)
|
||||
|
||||
|
||||
class MideaE3WaterHeater(MideaWaterHeater):
|
||||
"""Midea E3 Water Heater Entries."""
|
||||
|
||||
_device: MideaE3Device
|
||||
|
||||
def __init__(self, device: MideaE3Device, entity_key: str) -> None:
|
||||
"""Midea E3 Water Heater entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea E3 Water Heater min temperature."""
|
||||
return E3_TEMPERATURE_MIN
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea E3 Water Heater max temperature."""
|
||||
return E3_TEMPERATURE_MAX
|
||||
|
||||
@property
|
||||
def precision(self) -> float:
|
||||
"""Midea E3 Water Heater precision."""
|
||||
return float(
|
||||
PRECISION_HALVES if self._device.precision_halves else PRECISION_WHOLE,
|
||||
)
|
||||
|
||||
@property
|
||||
def current_operation(self) -> str:
|
||||
"""Midea E3 Water Heater current operation."""
|
||||
return str(
|
||||
STATE_ON if self._device.get_attribute("power") else STATE_OFF,
|
||||
)
|
||||
|
||||
|
||||
class MideaC3WaterHeater(MideaWaterHeater):
|
||||
"""Midea C3 Water Heater Entries."""
|
||||
|
||||
_device: MideaC3Device
|
||||
|
||||
def __init__(self, device: MideaC3Device, entity_key: str) -> None:
|
||||
"""Midea C3 Water Heater entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
|
||||
@property
|
||||
def current_operation(self) -> str:
|
||||
"""Midea C3 Water Heater current operation."""
|
||||
return str(
|
||||
(
|
||||
STATE_ON
|
||||
if self._device.get_attribute(C3Attributes.dhw_power)
|
||||
else STATE_OFF
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float:
|
||||
"""Midea C3 Water Heater current temperature."""
|
||||
return cast(
|
||||
"float",
|
||||
self._device.get_attribute(C3Attributes.tank_actual_temperature),
|
||||
)
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float:
|
||||
"""Midea C3 Water Heater target temperature."""
|
||||
return cast("float", self._device.get_attribute(C3Attributes.dhw_target_temp))
|
||||
|
||||
def set_temperature(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea C3 Water Heater set temperature."""
|
||||
if ATTR_TEMPERATURE not in kwargs:
|
||||
return
|
||||
temperature = float(kwargs[ATTR_TEMPERATURE])
|
||||
self._device.set_attribute(C3Attributes.dhw_target_temp, temperature)
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea C3 Water Heater min temperature."""
|
||||
return cast("float", self._device.get_attribute(C3Attributes.dhw_temp_min))
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea C3 Water Heater max temperature."""
|
||||
return cast("float", self._device.get_attribute(C3Attributes.dhw_temp_max))
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea C3 Water Heater turn on."""
|
||||
self._device.set_attribute(attr=C3Attributes.dhw_power, value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea C3 Water Heater turn off."""
|
||||
self._device.set_attribute(attr=C3Attributes.dhw_power, value=False)
|
||||
|
||||
|
||||
class MideaE6WaterHeater(MideaWaterHeater):
|
||||
"""Midea E6 Water Heater Entries."""
|
||||
|
||||
_device: MideaE6Device
|
||||
|
||||
_powers: ClassVar[list[E6Attributes]] = [
|
||||
E6Attributes.heating_power,
|
||||
E6Attributes.main_power,
|
||||
]
|
||||
_current_temperatures: ClassVar[list[E6Attributes]] = [
|
||||
E6Attributes.heating_leaving_temperature,
|
||||
E6Attributes.bathing_leaving_temperature,
|
||||
]
|
||||
_target_temperatures: ClassVar[list[E6Attributes]] = [
|
||||
E6Attributes.heating_temperature,
|
||||
E6Attributes.bathing_temperature,
|
||||
]
|
||||
|
||||
def __init__(self, device: MideaE6Device, entity_key: str, use: int) -> None:
|
||||
"""Midea E6 Water Heater entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._use = use
|
||||
self._power_attr = MideaE6WaterHeater._powers[self._use]
|
||||
self._current_temperature_attr = MideaE6WaterHeater._current_temperatures[
|
||||
self._use
|
||||
]
|
||||
self._target_temperature_attr = MideaE6WaterHeater._target_temperatures[
|
||||
self._use
|
||||
]
|
||||
|
||||
@property
|
||||
def current_operation(self) -> str:
|
||||
"""Midea E6 Water Heater current operation."""
|
||||
if self._use == 0: # for heating
|
||||
return str(
|
||||
(
|
||||
STATE_ON
|
||||
if self._device.get_attribute(E6Attributes.main_power)
|
||||
and self._device.get_attribute(E6Attributes.heating_power)
|
||||
else STATE_OFF
|
||||
),
|
||||
)
|
||||
# for bathing
|
||||
return str(
|
||||
(
|
||||
STATE_ON
|
||||
if self._device.get_attribute(E6Attributes.main_power)
|
||||
else STATE_OFF
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float:
|
||||
"""Midea E6 Water Heater current temperature."""
|
||||
return cast("float", self._device.get_attribute(self._current_temperature_attr))
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float:
|
||||
"""Midea E6 Water Heater target temperature."""
|
||||
return cast("float", self._device.get_attribute(self._target_temperature_attr))
|
||||
|
||||
def set_temperature(self, **kwargs: Any) -> None: # noqa: ANN401
|
||||
"""Midea E6 Water Heater set temperature."""
|
||||
if ATTR_TEMPERATURE not in kwargs:
|
||||
return
|
||||
temperature = float(kwargs[ATTR_TEMPERATURE])
|
||||
self._device.set_attribute(self._target_temperature_attr, temperature)
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea E6 Water Heater min temperature."""
|
||||
min_temperature = cast(
|
||||
"list[str]",
|
||||
self._device.get_attribute(E6Attributes.min_temperature),
|
||||
)
|
||||
return cast(
|
||||
"float",
|
||||
min_temperature[self._use],
|
||||
)
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea E6 Water Heater max temperature."""
|
||||
max_temperature = cast(
|
||||
"list[str]",
|
||||
self._device.get_attribute(E6Attributes.max_temperature),
|
||||
)
|
||||
return cast(
|
||||
"float",
|
||||
max_temperature[self._use],
|
||||
)
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea E6 Water Heater turn on."""
|
||||
self._device.set_attribute(attr=self._power_attr, value=True)
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None: # noqa: ANN401, ARG002
|
||||
"""Midea E6 Water Heater turn off."""
|
||||
self._device.set_attribute(attr=self._power_attr, value=False)
|
||||
|
||||
|
||||
class MideaCDWaterHeater(MideaWaterHeater):
|
||||
"""Midea CD Water Heater Entries."""
|
||||
|
||||
_device: MideaCDDevice
|
||||
|
||||
def __init__(self, device: MideaCDDevice, entity_key: str) -> None:
|
||||
"""Midea CD Water Heater entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
|
||||
@property
|
||||
def supported_features(self) -> WaterHeaterEntityFeature:
|
||||
"""Midea CD Water Heater supported features."""
|
||||
return (
|
||||
WaterHeaterEntityFeature.TARGET_TEMPERATURE
|
||||
| WaterHeaterEntityFeature.OPERATION_MODE
|
||||
)
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Midea CD Water Heater min temperature."""
|
||||
return cast("float", self._device.get_attribute(CDAttributes.min_temperature))
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Midea CD Water Heater max temperature."""
|
||||
return cast("float", self._device.get_attribute(CDAttributes.max_temperature))
|
||||
Reference in New Issue
Block a user