diff --git a/custom_components/sonoff/climate.py b/custom_components/sonoff/climate.py index 929f6bfc..1e4339b8 100644 --- a/custom_components/sonoff/climate.py +++ b/custom_components/sonoff/climate.py @@ -144,7 +144,16 @@ async def async_set_temperature( # noinspection PyAbstractClass class XClimateNS(XEntity, ClimateEntity): - params = {"ATCEnable", "ATCMode", "temperature", "tempCorrection"} + params = { + "ATCEnable", + "ATCMode", + "ATCExpect0", + "HMI_ATCDevice", + "ATCEnable", + "ATCMode", + "temperature", + "tempCorrection", + } _attr_entity_registry_enabled_default = False _attr_hvac_modes = [HVAC_MODE_OFF, HVAC_MODE_HEAT_COOL, HVAC_MODE_AUTO] @@ -152,6 +161,7 @@ class XClimateNS(XEntity, ClimateEntity): _attr_min_temp = 16 _attr_temperature_unit = TEMP_CELSIUS _attr_target_temperature_step = 1 + _attr_supported_features = 0 | SUPPORT_TARGET_TEMPERATURE def set_state(self, params: dict): cache = self.device["params"] @@ -159,23 +169,19 @@ def set_state(self, params: dict): cache.update(params) if "HMI_ATCDevice" in params and "etype" in params["HMI_ATCDevice"]: - self._attr_hvac_modes[1] = ( - HVAC_MODE_COOL - if cache["HMI_ATCDevice"]["etype"] == "cold" - else HVAC_MODE_HEAT - ) + if cache["HMI_ATCDevice"]["etype"] == "cold": + self._attr_hvac_modes[1] = HVAC_MODE_COOL + else: + self._attr_hvac_modes[1] = HVAC_MODE_HEAT if "ATCEnable" in params or "ATCMode" in params: if cache["ATCEnable"]: if cache["ATCMode"]: - self._attr_hvac_mode = HVAC_MODE_AUTO - self._attr_supported_features = 0 + self.set_hvac_attr(HVAC_MODE_AUTO) else: - self._attr_hvac_mode = self.hvac_modes[1] - self._attr_supported_features = SUPPORT_TARGET_TEMPERATURE + self.set_hvac_attr(self._attr_hvac_modes[1]) else: - self._attr_hvac_mode = HVAC_MODE_OFF - self._attr_supported_features = SUPPORT_TARGET_TEMPERATURE + self.set_hvac_attr(HVAC_MODE_OFF) if "ATCExpect0" in params: self._attr_target_temperature = cache["ATCExpect0"] @@ -187,11 +193,25 @@ def set_state(self, params: dict): "tempCorrection", 0 ) + def set_hvac_attr(self, hvac_mode: str) -> None: + if not hvac_mode: + return + + if hvac_mode in (HVAC_MODE_AUTO): + self._attr_hvac_mode = hvac_mode + self._attr_supported_features = 0 + elif hvac_mode in (HVAC_MODE_OFF): + self._attr_hvac_mode = hvac_mode + self._attr_supported_features = SUPPORT_TARGET_TEMPERATURE + elif hvac_mode in (HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL): + self._attr_hvac_mode = self._attr_hvac_modes[1] + self._attr_supported_features = SUPPORT_TARGET_TEMPERATURE + @staticmethod def get_params(hvac_mode: str) -> dict: if hvac_mode == HVAC_MODE_AUTO: return {"ATCEnable": 1, "ATCMode": 1} - elif hvac_mode in (HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT): + elif hvac_mode in (HVAC_MODE_COOL, HVAC_MODE_HEAT): return {"ATCEnable": 1, "ATCMode": 0} elif hvac_mode == HVAC_MODE_HEAT_COOL: return {"ATCEnable": 1} # async_turn_on @@ -202,17 +222,30 @@ def get_params(hvac_mode: str) -> dict: async def async_set_hvac_mode(self, hvac_mode: str) -> None: params = self.get_params(hvac_mode) + await self.ewelink.cloud.send(self.device, params) + self.set_hvac_attr(hvac_mode) + self._async_write_ha_state() async def async_set_temperature( self, temperature: float = None, hvac_mode: str = None, **kwargs ) -> None: + if temperature is None: + return + + # Set manual operation and temperature params = self.get_params(hvac_mode) - if temperature is not None: - params["ATCExpect0"] = temperature - if not params: - params["ATCEnable"] = 1 + params.update( + { + "ATCMode": 0, + "ATCExpect0": temperature, + } + ) + await self.ewelink.cloud.send(self.device, params) + self._attr_target_temperature = temperature + self.set_hvac_attr(hvac_mode) + self._async_write_ha_state() # noinspection PyAbstractClass diff --git a/custom_components/sonoff/core/devices.py b/custom_components/sonoff/core/devices.py index b1c582f3..66b3f08d 100644 --- a/custom_components/sonoff/core/devices.py +++ b/custom_components/sonoff/core/devices.py @@ -17,7 +17,6 @@ from homeassistant.components.sensor import SensorEntity from homeassistant.components.switch import SwitchEntity -from .ewelink import XDevice from ..binary_sensor import XBinarySensor, XWiFiDoor, XZigbeeMotion from ..climate import XClimateNS, XClimateTH, XThermostat from ..core.entity import XEntity @@ -39,6 +38,7 @@ from ..remote import XRemote from ..sensor import ( XEnergySensor, + XEnergySensorDualR3, XHumidityTH, XOutdoorTempNS, XRemoteButton, @@ -47,9 +47,9 @@ XTemperatureTH, XUnknown, XWiFiDoorBattery, - XEnergySensorDualR3, ) from ..switch import XSwitch, XSwitches, XSwitchTH, XToggle, XZigbeeSwitches +from .ewelink import XDevice # supported custom device_class DEVICE_CLASS = { diff --git a/tests/test_entity.py b/tests/test_entity.py index a5aac59e..478d822b 100644 --- a/tests/test_entity.py +++ b/tests/test_entity.py @@ -38,6 +38,7 @@ from custom_components.sonoff.number import XNumber, XPulseWidth from custom_components.sonoff.sensor import ( XEnergySensor, + XEnergySensorDualR3, XOutdoorTempNS, XRemoteButton, XSensor, @@ -450,13 +451,9 @@ def test_dual_r3(): "getKwh_01": 2, "calibration": 1, }, - }, { - "devices": { - DEVICEID: { - "reporting": {"energy_1": [3600, 3]} - } - } - }) + }, + {"devices": {DEVICEID: {"reporting": {"energy_1": [3600, 3]}}}}, + ) volt: XSensor = next(e for e in entities if e.uid == "voltage_1") assert volt.state == 247.62 @@ -468,16 +465,16 @@ def test_dual_r3(): assert cover.state_attributes == {"current_position": 0} # Get history if we use reporting - energy_1: XEnergySensor_DualR3 = next(e for e in entities if e.uid == "energy_1") - energy_1.internal_update({'kwhHistories_00': '0034007412340000'}) + energy_1: XEnergySensorDualR3 = next(e for e in entities if e.uid == "energy_1") + energy_1.internal_update({"kwhHistories_00": "0034007412340000"}) assert energy_1.state == 0.34 assert energy_1.extra_state_attributes == {"history": [0.34, 0.74, 12.34]} # Skip history if we don't use reporting - energy_2: XEnergySensor_DualR3 = next(e for e in entities if e.uid == "energy_2") - energy_2.internal_update({'kwhHistories_01': '0201000000000000'}) + energy_2: XEnergySensorDualR3 = next(e for e in entities if e.uid == "energy_2") + energy_2.internal_update({"kwhHistories_01": "0201000000000000"}) assert energy_2.state == 2.01 - assert energy_2.extra_state_attributes == None + assert energy_2.extra_state_attributes is None def test_diffuser():