Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 50 additions & 17 deletions custom_components/sonoff/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,38 +144,44 @@ 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]
_attr_max_temp = 31
_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"]
if cache != params:
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"]
Expand All @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions custom_components/sonoff/core/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -39,6 +38,7 @@
from ..remote import XRemote
from ..sensor import (
XEnergySensor,
XEnergySensorDualR3,
XHumidityTH,
XOutdoorTempNS,
XRemoteButton,
Expand All @@ -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 = {
Expand Down
21 changes: 9 additions & 12 deletions tests/test_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from custom_components.sonoff.number import XNumber, XPulseWidth
from custom_components.sonoff.sensor import (
XEnergySensor,
XEnergySensorDualR3,
XOutdoorTempNS,
XRemoteButton,
XSensor,
Expand Down Expand Up @@ -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
Expand All @@ -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():
Expand Down