35 files
This commit is contained in:
@@ -44,6 +44,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from midealan.device import DeviceType
|
||||
from midealan.devices.ac import DeviceAttributes as ACAttributes
|
||||
from midealan.devices.ac import MideaACDevice
|
||||
from midealan.devices.c1 import DeviceAttributes as C1Attributes
|
||||
from midealan.devices.c1 import MideaC1Device
|
||||
from midealan.devices.c3 import DeviceAttributes as C3Attributes
|
||||
from midealan.devices.c3 import MideaC3Device
|
||||
from midealan.devices.cc import DeviceAttributes as CCAttributes
|
||||
@@ -83,6 +85,7 @@ async def async_setup_entry(
|
||||
| MideaCCClimate
|
||||
| MideaCFClimate
|
||||
| MideaC3Climate
|
||||
| MideaC1Climate
|
||||
| MideaFBClimate
|
||||
| MideaEDTeaBarClimate
|
||||
] = []
|
||||
@@ -104,6 +107,8 @@ async def async_setup_entry(
|
||||
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.C1:
|
||||
devs.append(MideaC1Climate(device, entity_key))
|
||||
elif device.device_type == DeviceType.FB:
|
||||
devs.append(MideaFBClimate(device, entity_key))
|
||||
elif device.device_type == DeviceType.ED:
|
||||
@@ -111,9 +116,10 @@ async def async_setup_entry(
|
||||
async_add_entities(devs)
|
||||
|
||||
|
||||
type MideaClimateDevice = (
|
||||
type MideaSetTemperatureDevice = (
|
||||
MideaACDevice | MideaCCDevice | MideaCFDevice | MideaC3Device | MideaFBDevice
|
||||
)
|
||||
type MideaClimateDevice = MideaSetTemperatureDevice | MideaC1Device
|
||||
|
||||
|
||||
class MideaClimate(MideaEntity, ClimateEntity):
|
||||
@@ -211,7 +217,8 @@ class MideaClimate(MideaEntity, ClimateEntity):
|
||||
else:
|
||||
try:
|
||||
mode = self.hvac_modes.index(hvac_mode.lower()) if hvac_mode else None
|
||||
self._device.set_target_temperature(
|
||||
target_device = cast("MideaSetTemperatureDevice", self._device)
|
||||
target_device.set_target_temperature(
|
||||
target_temperature=temperature,
|
||||
mode=mode,
|
||||
zone=None,
|
||||
@@ -1019,6 +1026,124 @@ class MideaC3Climate(MideaClimate):
|
||||
self._device.set_mode(self._zone, self.hvac_modes.index(hvac_mode))
|
||||
|
||||
|
||||
class MideaC1Climate(MideaClimate):
|
||||
"""Midea C1 electric wall-hung boiler (space heating as climate)."""
|
||||
|
||||
_device: MideaC1Device
|
||||
|
||||
_attr_max_temp: float = 60
|
||||
_attr_min_temp: float = 30
|
||||
_attr_target_temperature_high: float | None = 60
|
||||
_attr_target_temperature_low: float | None = 30
|
||||
_attr_target_temperature_step: float | None = PRECISION_WHOLE
|
||||
|
||||
def __init__(self, device: MideaC1Device, entity_key: str) -> None:
|
||||
"""Midea C1 climate entity init."""
|
||||
super().__init__(device, entity_key)
|
||||
self._attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT]
|
||||
self._attr_preset_modes: list[str] = self._device.heating_modes
|
||||
|
||||
@property
|
||||
def supported_features(self) -> ClimateEntityFeature:
|
||||
"""Midea C1 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 hvac_mode(self) -> HVACMode:
|
||||
"""Midea C1 climate hvac mode."""
|
||||
return (
|
||||
HVACMode.HEAT
|
||||
if self._device.get_attribute(C1Attributes.power)
|
||||
else HVACMode.OFF
|
||||
)
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str:
|
||||
"""Midea C1 climate preset mode (comfort / activity / sleep)."""
|
||||
mode = cast("str", self._device.get_attribute(C1Attributes.heating_mode))
|
||||
if mode == "unknown" and self._attr_preset_modes:
|
||||
return self._attr_preset_modes[0]
|
||||
return mode
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Midea C1 climate current temperature."""
|
||||
raw = self._device.get_attribute(C1Attributes.current_temperature)
|
||||
if isinstance(raw, int | float):
|
||||
return float(raw)
|
||||
return None
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> float:
|
||||
"""Midea C1 climate heating target setpoint."""
|
||||
raw = self._device.get_attribute(C1Attributes.heating_target_temperature)
|
||||
if isinstance(raw, int | float):
|
||||
return float(raw)
|
||||
return float(self.min_temp)
|
||||
|
||||
def set_temperature(self, **kwargs: Any) -> None: # ruff:ignore[any-type]
|
||||
"""Midea C1 climate set heating target temperature."""
|
||||
if ATTR_TEMPERATURE not in kwargs:
|
||||
return
|
||||
temperature = float(round(float(kwargs[ATTR_TEMPERATURE])))
|
||||
hvac_mode = kwargs.get(ATTR_HVAC_MODE)
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
self.turn_off()
|
||||
return
|
||||
# Writing heating_target_temperature only sends MessageSetHeating, not a
|
||||
# power-on command. When the service call carries an explicit non-OFF
|
||||
# mode, turn the boiler on first so a combined change on an off device
|
||||
# actually starts heating instead of silently staying off.
|
||||
if hvac_mode is not None:
|
||||
self.turn_on()
|
||||
self._device.set_attribute(
|
||||
attr=C1Attributes.heating_target_temperature,
|
||||
value=temperature,
|
||||
)
|
||||
|
||||
def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Midea C1 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 C1 climate set heating schedule mode.
|
||||
|
||||
Send the requested preset's own stored setpoint together with the mode
|
||||
change. The device library's plain ``heating_mode`` setter re-applies
|
||||
the cached general ``heating_target_temperature`` under the new mode, so
|
||||
switching presets would otherwise carry over the previous mode's target
|
||||
instead of that preset's per-mode setpoint. Fall back to the plain mode
|
||||
change when the per-mode setpoint has not been reported yet.
|
||||
"""
|
||||
# Lua mode codes: user=1, activity=2, sleep=3 (see midealan c1.message).
|
||||
per_mode = {
|
||||
"user": (1, C1Attributes.user_mode_target_temperature),
|
||||
"activity": (2, C1Attributes.activity_mode_target_temperature),
|
||||
"sleep": (3, C1Attributes.sleep_mode_target_temperature),
|
||||
}.get(preset_mode)
|
||||
if per_mode is not None:
|
||||
mode_code, per_mode_attr = per_mode
|
||||
raw = self._device.get_attribute(per_mode_attr)
|
||||
if isinstance(raw, int | float):
|
||||
self._device.set_heating_target_temperature(
|
||||
float(raw),
|
||||
heating_mode=mode_code,
|
||||
)
|
||||
return
|
||||
self._device.set_attribute(
|
||||
attr=C1Attributes.heating_mode,
|
||||
value=preset_mode,
|
||||
)
|
||||
|
||||
|
||||
class MideaFBClimate(MideaClimate):
|
||||
"""Midea FB Climate Entries."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user