From 0a0b60566d93ddc319c81c6516661bca33b74533 Mon Sep 17 00:00:00 2001
From: jfearon <1884400+jfearon@users.noreply.github.com>
Date: Wed, 1 Jul 2020 15:20:50 +0100
Subject: [PATCH] Add a service for setting the timer to tado water heaters
 (#36533)

* Add service to support setting timer on water heater component

* Update water_heater.py

Remove info logging
Return if unsupported option used

* Added default temperature as it is optional

* Update homeassistant/components/tado/services.yaml

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

* Update homeassistant/components/tado/services.yaml

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

* Update homeassistant/components/tado/services.yaml

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

* Update homeassistant/components/tado/water_heater.py

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

* Fix to remove else statement, and fix lint error

* Reinstate entity id on schema, allow setting with temperature on devices that dont support it

* Remove entity id from schema as not required

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
---
 homeassistant/components/tado/services.yaml   | 12 ++++++
 homeassistant/components/tado/water_heater.py | 42 ++++++++++++++++---
 2 files changed, 48 insertions(+), 6 deletions(-)
 create mode 100644 homeassistant/components/tado/services.yaml

diff --git a/homeassistant/components/tado/services.yaml b/homeassistant/components/tado/services.yaml
new file mode 100644
index 00000000000..a6d37dc26ce
--- /dev/null
+++ b/homeassistant/components/tado/services.yaml
@@ -0,0 +1,12 @@
+set_water_heater_timer:
+  description: Turn on water heater for a set time.
+  fields:
+    entity_id:
+      description: Entity ID for the tado component to turn on for a set time.
+      example: water_heater.hot_water
+    time_period:
+      description: Set the time period for the boost.
+      example: "01:30:00"
+    temperature:
+      description: Temperature to set heater to
+      example: 25
diff --git a/homeassistant/components/tado/water_heater.py b/homeassistant/components/tado/water_heater.py
index 1c0d37c90df..be3be0f545a 100644
--- a/homeassistant/components/tado/water_heater.py
+++ b/homeassistant/components/tado/water_heater.py
@@ -1,6 +1,8 @@
 """Support for Tado hot water zones."""
 import logging
 
+import voluptuous as vol
+
 from homeassistant.components.water_heater import (
     SUPPORT_OPERATION_MODE,
     SUPPORT_TARGET_TEMPERATURE,
@@ -9,6 +11,7 @@ from homeassistant.components.water_heater import (
 from homeassistant.config_entries import ConfigEntry
 from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
 from homeassistant.core import HomeAssistant, callback
+from homeassistant.helpers import config_validation as cv, entity_platform
 from homeassistant.helpers.dispatcher import async_dispatcher_connect
 
 from .const import (
@@ -46,6 +49,16 @@ WATER_HEATER_MAP_TADO = {
 
 SUPPORT_FLAGS_HEATER = SUPPORT_OPERATION_MODE
 
+SERVICE_WATER_HEATER_TIMER = "set_water_heater_timer"
+ATTR_TIME_PERIOD = "time_period"
+
+WATER_HEATER_TIMER_SCHEMA = {
+    vol.Required(ATTR_TIME_PERIOD, default="01:00:00"): vol.All(
+        cv.time_period, cv.positive_timedelta, lambda td: td.total_seconds()
+    ),
+    vol.Optional(ATTR_TEMPERATURE): vol.Coerce(float),
+}
+
 
 async def async_setup_entry(
     hass: HomeAssistant, entry: ConfigEntry, async_add_entities
@@ -55,6 +68,12 @@ async def async_setup_entry(
     tado = hass.data[DOMAIN][entry.entry_id][DATA]
     entities = await hass.async_add_executor_job(_generate_entities, tado)
 
+    platform = entity_platform.current_platform.get()
+
+    platform.async_register_entity_service(
+        SERVICE_WATER_HEATER_TIMER, WATER_HEATER_TIMER_SCHEMA, "set_timer",
+    )
+
     if entities:
         async_add_entities(entities, True)
 
@@ -212,6 +231,15 @@ class TadoWaterHeater(TadoZoneEntity, WaterHeaterEntity):
 
         self._control_heater(hvac_mode=mode)
 
+    def set_timer(self, time_period, temperature=None):
+        """Set the timer on the entity, and temperature if supported."""
+        if not self._supports_temperature_control and temperature is not None:
+            temperature = None
+
+        self._control_heater(
+            hvac_mode=CONST_MODE_HEAT, target_temp=temperature, duration=time_period
+        )
+
     def set_temperature(self, **kwargs):
         """Set new target temperature."""
         temperature = kwargs.get(ATTR_TEMPERATURE)
@@ -241,7 +269,7 @@ class TadoWaterHeater(TadoZoneEntity, WaterHeaterEntity):
         self._tado_zone_data = self._tado.data["zone"][self.zone_id]
         self._current_tado_hvac_mode = self._tado_zone_data.current_hvac_mode
 
-    def _control_heater(self, hvac_mode=None, target_temp=None):
+    def _control_heater(self, hvac_mode=None, target_temp=None, duration=None):
         """Send new target temperature."""
 
         if hvac_mode:
@@ -270,10 +298,12 @@ class TadoWaterHeater(TadoZoneEntity, WaterHeaterEntity):
             self._tado.set_zone_off(self.zone_id, CONST_OVERLAY_MANUAL, TYPE_HOT_WATER)
             return
 
-        # Fallback to Smart Schedule at next Schedule switch if we have fallback enabled
-        overlay_mode = (
-            CONST_OVERLAY_TADO_MODE if self._tado.fallback else CONST_OVERLAY_MANUAL
-        )
+        overlay_mode = CONST_OVERLAY_MANUAL
+        if duration:
+            overlay_mode = CONST_OVERLAY_TIMER
+        elif self._tado.fallback:
+            # Fallback to Smart Schedule at next Schedule switch if we have fallback enabled
+            overlay_mode = CONST_OVERLAY_TADO_MODE
 
         _LOGGER.debug(
             "Switching to %s for zone %s (%d) with temperature %s",
@@ -286,7 +316,7 @@ class TadoWaterHeater(TadoZoneEntity, WaterHeaterEntity):
             zone_id=self.zone_id,
             overlay_mode=overlay_mode,
             temperature=self._target_temp,
-            duration=None,
+            duration=duration,
             device_type=TYPE_HOT_WATER,
         )
         self._overlay_mode = self._current_tado_hvac_mode
-- 
GitLab