From 1faef0a4d429e8c636beed2728ad564f379f650c Mon Sep 17 00:00:00 2001
From: Robert Svensson <Kane610@users.noreply.github.com>
Date: Tue, 1 Dec 2020 18:49:58 +0100
Subject: [PATCH] Make simple deCONZ thermostats work (#43781)
---
homeassistant/components/deconz/climate.py | 9 +-
tests/components/deconz/test_climate.py | 121 +++++++++++++++++++++
2 files changed, 129 insertions(+), 1 deletion(-)
diff --git a/homeassistant/components/deconz/climate.py b/homeassistant/components/deconz/climate.py
index afa9e8dcd9f..0c1fe2da1e3 100644
--- a/homeassistant/components/deconz/climate.py
+++ b/homeassistant/components/deconz/climate.py
@@ -72,7 +72,12 @@ class DeconzThermostat(DeconzDevice, ClimateEntity):
super().__init__(device, gateway)
self._hvac_modes = dict(HVAC_MODES)
- if "coolsetpoint" not in device.raw["config"]:
+ if "mode" not in device.raw["config"]:
+ self._hvac_modes = {
+ HVAC_MODE_HEAT: True,
+ HVAC_MODE_OFF: False,
+ }
+ elif "coolsetpoint" not in device.raw["config"]:
self._hvac_modes.pop(HVAC_MODE_COOL)
self._features = SUPPORT_TARGET_TEMPERATURE
@@ -110,6 +115,8 @@ class DeconzThermostat(DeconzDevice, ClimateEntity):
raise ValueError(f"Unsupported HVAC mode {hvac_mode}")
data = {"mode": self._hvac_modes[hvac_mode]}
+ if len(self._hvac_modes) == 2: # Only allow turn on and off thermostat
+ data = {"on": self._hvac_modes[hvac_mode]}
await self._device.async_set_config(data)
diff --git a/tests/components/deconz/test_climate.py b/tests/components/deconz/test_climate.py
index 751f1572239..cea660b855b 100644
--- a/tests/components/deconz/test_climate.py
+++ b/tests/components/deconz/test_climate.py
@@ -73,6 +73,127 @@ async def test_no_sensors(hass):
assert len(hass.states.async_all()) == 0
+async def test_simple_climate_device(hass):
+ """Test successful creation of climate entities.
+
+ This is a simple water heater that only supports setting temperature and on and off.
+ """
+ data = deepcopy(DECONZ_WEB_REQUEST)
+ data["sensors"] = {
+ "0": {
+ "config": {
+ "battery": 59,
+ "displayflipped": None,
+ "heatsetpoint": 2100,
+ "locked": None,
+ "mountingmode": None,
+ "offset": 0,
+ "on": True,
+ "reachable": True,
+ },
+ "ep": 1,
+ "etag": "6130553ac247174809bae47144ee23f8",
+ "lastseen": "2020-11-29T19:31Z",
+ "manufacturername": "Danfoss",
+ "modelid": "eTRV0100",
+ "name": "thermostat",
+ "state": {
+ "errorcode": None,
+ "lastupdated": "2020-11-29T19:28:40.665",
+ "mountingmodeactive": False,
+ "on": True,
+ "temperature": 2102,
+ "valve": 24,
+ "windowopen": "Closed",
+ },
+ "swversion": "01.02.0008 01.02",
+ "type": "ZHAThermostat",
+ "uniqueid": "14:b4:57:ff:fe:d5:4e:77-01-0201",
+ }
+ }
+ config_entry = await setup_deconz_integration(hass, get_state_response=data)
+ gateway = get_gateway_from_config_entry(hass, config_entry)
+
+ assert len(hass.states.async_all()) == 2
+ climate_thermostat = hass.states.get("climate.thermostat")
+ assert climate_thermostat.state == HVAC_MODE_HEAT
+ assert climate_thermostat.attributes["hvac_modes"] == [
+ HVAC_MODE_HEAT,
+ HVAC_MODE_OFF,
+ ]
+ assert climate_thermostat.attributes["current_temperature"] == 21.0
+ assert climate_thermostat.attributes["temperature"] == 21.0
+ assert hass.states.get("sensor.thermostat_battery_level").state == "59"
+
+ # Event signals thermostat configured off
+
+ state_changed_event = {
+ "t": "event",
+ "e": "changed",
+ "r": "sensors",
+ "id": "0",
+ "state": {"on": False},
+ }
+ gateway.api.event_handler(state_changed_event)
+ await hass.async_block_till_done()
+
+ assert hass.states.get("climate.thermostat").state == STATE_OFF
+
+ # Event signals thermostat state on
+
+ state_changed_event = {
+ "t": "event",
+ "e": "changed",
+ "r": "sensors",
+ "id": "0",
+ "state": {"on": True},
+ }
+ gateway.api.event_handler(state_changed_event)
+ await hass.async_block_till_done()
+
+ assert hass.states.get("climate.thermostat").state == HVAC_MODE_HEAT
+
+ # Verify service calls
+
+ thermostat_device = gateway.api.sensors["0"]
+
+ # Service turn on thermostat
+
+ with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
+ await hass.services.async_call(
+ CLIMATE_DOMAIN,
+ SERVICE_SET_HVAC_MODE,
+ {ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_HEAT},
+ blocking=True,
+ )
+ await hass.async_block_till_done()
+ set_callback.assert_called_with("put", "/sensors/0/config", json={"on": True})
+
+ # Service turn on thermostat
+
+ with patch.object(thermostat_device, "_request", return_value=True) as set_callback:
+ await hass.services.async_call(
+ CLIMATE_DOMAIN,
+ SERVICE_SET_HVAC_MODE,
+ {ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_OFF},
+ blocking=True,
+ )
+ await hass.async_block_till_done()
+ set_callback.assert_called_with("put", "/sensors/0/config", json={"on": False})
+
+ # Service set HVAC mode to unsupported value
+
+ with patch.object(
+ thermostat_device, "_request", return_value=True
+ ) as set_callback, pytest.raises(ValueError):
+ await hass.services.async_call(
+ CLIMATE_DOMAIN,
+ SERVICE_SET_HVAC_MODE,
+ {ATTR_ENTITY_ID: "climate.thermostat", ATTR_HVAC_MODE: HVAC_MODE_AUTO},
+ blocking=True,
+ )
+
+
async def test_climate_device_without_cooling_support(hass):
"""Test successful creation of sensor entities."""
data = deepcopy(DECONZ_WEB_REQUEST)